@fluenti/react 0.1.1 → 0.1.3

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.
@@ -12,5 +12,5 @@ export interface DateTimeProps {
12
12
  * <DateTime value={new Date()} style="long" />
13
13
  * ```
14
14
  */
15
- export declare function DateTime({ value, style }: DateTimeProps): import("react/jsx-runtime").JSX.Element;
15
+ export declare const DateTime: import('react').NamedExoticComponent<DateTimeProps>;
16
16
  //# sourceMappingURL=DateTime.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"DateTime.d.ts","sourceRoot":"","sources":["../../src/components/DateTime.tsx"],"names":[],"mappings":"AAGA,MAAM,WAAW,aAAa;IAC5B,2BAA2B;IAC3B,KAAK,EAAE,IAAI,GAAG,MAAM,CAAA;IACpB,yBAAyB;IACzB,KAAK,CAAC,EAAE,MAAM,CAAA;CACf;AAED;;;;;;;GAOG;AACH,wBAAgB,QAAQ,CAAC,EAAE,KAAK,EAAE,KAAK,EAAE,EAAE,aAAa,2CAMvD"}
1
+ {"version":3,"file":"DateTime.d.ts","sourceRoot":"","sources":["../../src/components/DateTime.tsx"],"names":[],"mappings":"AAGA,MAAM,WAAW,aAAa;IAC5B,2BAA2B;IAC3B,KAAK,EAAE,IAAI,GAAG,MAAM,CAAA;IACpB,yBAAyB;IACzB,KAAK,CAAC,EAAE,MAAM,CAAA;CACf;AAED;;;;;;;GAOG;AACH,eAAO,MAAM,QAAQ,qDAMnB,CAAA"}
@@ -12,5 +12,5 @@ export interface NumberProps {
12
12
  * <Number value={1234.56} style="currency" />
13
13
  * ```
14
14
  */
15
- export declare function NumberFormat({ value, style }: NumberProps): import("react/jsx-runtime").JSX.Element;
15
+ export declare const NumberFormat: import('react').NamedExoticComponent<NumberProps>;
16
16
  //# sourceMappingURL=Number.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"Number.d.ts","sourceRoot":"","sources":["../../src/components/Number.tsx"],"names":[],"mappings":"AAGA,MAAM,WAAW,WAAW;IAC1B,6BAA6B;IAC7B,KAAK,EAAE,MAAM,CAAA;IACb,yBAAyB;IACzB,KAAK,CAAC,EAAE,MAAM,CAAA;CACf;AAED;;;;;;;GAOG;AACH,wBAAgB,YAAY,CAAC,EAAE,KAAK,EAAE,KAAK,EAAE,EAAE,WAAW,2CAMzD"}
1
+ {"version":3,"file":"Number.d.ts","sourceRoot":"","sources":["../../src/components/Number.tsx"],"names":[],"mappings":"AAGA,MAAM,WAAW,WAAW;IAC1B,6BAA6B;IAC7B,KAAK,EAAE,MAAM,CAAA;IACb,yBAAyB;IACzB,KAAK,CAAC,EAAE,MAAM,CAAA;CACf;AAED;;;;;;;GAOG;AACH,eAAO,MAAM,YAAY,mDAMvB,CAAA"}
@@ -28,5 +28,5 @@ export interface SelectProps {
28
28
  * />
29
29
  * ```
30
30
  */
31
- export declare function Select(props: SelectProps): import("react/jsx-runtime").JSX.Element;
31
+ export declare const Select: import('react').NamedExoticComponent<SelectProps>;
32
32
  //# sourceMappingURL=Select.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"Select.d.ts","sourceRoot":"","sources":["../../src/components/Select.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAc,KAAK,SAAS,EAAE,MAAM,OAAO,CAAA;AAKlD,MAAM,WAAW,WAAW;IAC1B,yBAAyB;IACzB,KAAK,EAAE,MAAM,CAAA;IACb,2DAA2D;IAC3D,EAAE,CAAC,EAAE,MAAM,CAAA;IACX,sEAAsE;IACtE,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,8DAA8D;IAC9D,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,mBAAmB;IACnB,KAAK,EAAE,SAAS,CAAA;IAChB,wEAAwE;IACxE,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,CAAA;IACnC,uDAAuD;IACvD,CAAC,GAAG,EAAE,MAAM,GAAG,SAAS,GAAG,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,GAAG,SAAS,CAAA;CACjE;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,MAAM,CAAC,KAAK,EAAE,WAAW,2CAyCxC"}
1
+ {"version":3,"file":"Select.d.ts","sourceRoot":"","sources":["../../src/components/Select.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAoB,KAAK,SAAS,EAAE,MAAM,OAAO,CAAA;AAKxD,MAAM,WAAW,WAAW;IAC1B,yBAAyB;IACzB,KAAK,EAAE,MAAM,CAAA;IACb,2DAA2D;IAC3D,EAAE,CAAC,EAAE,MAAM,CAAA;IACX,sEAAsE;IACtE,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,8DAA8D;IAC9D,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,mBAAmB;IACnB,KAAK,EAAE,SAAS,CAAA;IAChB,wEAAwE;IACxE,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,CAAA;IACnC,uDAAuD;IACvD,CAAC,GAAG,EAAE,MAAM,GAAG,SAAS,GAAG,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,GAAG,SAAS,CAAA;CACjE;AAED;;;;;;;;;;;;GAYG;AACH,eAAO,MAAM,MAAM,mDAyCjB,CAAA"}
package/dist/index.cjs CHANGED
@@ -1,3 +1,3 @@
1
1
  "use client";
2
- "use client";Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require(`./icu-rich-XY1SdM5K.cjs`);let t=require(`react`),n=require(`@fluenti/core`),r=require(`react/jsx-runtime`);var i=(0,t.createContext)(null),a=Symbol.for(`fluenti.runtime.react`);function o(){let e=globalThis[a];return typeof e==`object`&&e?e:null}function s({locale:e,fallbackLocale:a,messages:s,loadMessages:c,fallbackChain:l,dateFormats:u,numberFormats:d,missing:f,children:p}){let[m,h]=(0,t.useState)(e),[g,_]=(0,t.useState)(!1),[v,y]=(0,t.useState)(s??{}),[b,x]=(0,t.useState)(s?Object.keys(s):[]),S=(0,t.useRef)(v);S.current=v;let C=(0,t.useRef)(0),w=(0,t.useMemo)(()=>{let e={locale:m,messages:v};return a!==void 0&&(e.fallbackLocale=a),l!==void 0&&(e.fallbackChain=l),u!==void 0&&(e.dateFormats=u),d!==void 0&&(e.numberFormats=d),f!==void 0&&(e.missing=f),(0,n.createFluent)(e)},[m,v,a,l,u,d,f]);(0,t.useEffect)(()=>{e!==m&&T(e)},[e]);let T=(0,t.useCallback)(async e=>{let t=++C.current;if(S.current[e]&&!c){h(e);return}let n=c?o():null;if(S.current[e]){n?.__switchLocale&&await n.__switchLocale(e),h(e);return}if(!c){console.warn(`[fluenti] No messages for locale "${e}" and no loadMessages function provided`);return}_(!0);try{let r=await c(e);if(t!==C.current)return;let i=typeof r==`object`&&r&&`default`in r?r.default:r;y(t=>({...t,[e]:i})),x(t=>[...new Set([...t,e])]),n?.__switchLocale&&await n.__switchLocale(e),h(e)}catch(n){t===C.current&&console.error(`[fluenti] Failed to load locale "${e}"`,n)}finally{t===C.current&&_(!1)}},[c]),E=(0,t.useCallback)(async e=>{let t=o();if(!(S.current[e]||!c))try{let n=await c(e),r=typeof n==`object`&&n&&`default`in n?n.default:n;y(t=>({...t,[e]:r})),x(t=>[...new Set([...t,e])]),t?.__preloadLocale&&await t.__preloadLocale(e)}catch{}},[c]),D=(0,t.useMemo)(()=>({i18n:w,t:w.t.bind(w),d:w.d.bind(w),n:w.n.bind(w),format:w.format.bind(w),loadMessages:w.loadMessages.bind(w),getLocales:w.getLocales.bind(w),locale:m,setLocale:T,isLoading:g,loadedLocales:b,preloadLocale:E}),[w,m,T,g,b,E]);return(0,r.jsx)(i.Provider,{value:D,children:p})}function c(){let e=(0,t.useContext)(i);if(!e)throw Error(`[fluenti] useI18n() must be used within an <I18nProvider>. Wrap your app with <I18nProvider> to provide i18n context.`);return e}var l=((...e)=>{throw Error("[fluenti] `t` imported from '@fluenti/react' is a compile-time API. Use it only with the Fluenti build transform inside a component or custom hook. For runtime lookups, use useI18n().t(...).")}),u=(0,t.memo)(function({children:a,id:o,context:s,comment:c,render:l,__id:u,__message:d,__components:f}){let p=(0,t.useContext)(i);if(!p)throw Error(`[fluenti] <Trans> must be used within an <I18nProvider>`);let m=d!==void 0,{message:h,components:g}=(0,t.useMemo)(()=>m?{message:d,components:f??[]}:e.s(a),[m,d,f,a]),_=(0,t.useMemo)(()=>o??u??(0,n.hashMessage)(h,s),[o,u,h,s]),v=e.c(p.i18n.t({id:_,message:h,...s===void 0?{}:{context:s},...c===void 0?{}:{comment:c}}),g);return l?l(v):(0,r.jsx)(r.Fragment,{children:v})}),d=(0,t.memo)(function({value:a,id:o,context:s,comment:c,zero:l,one:u,two:d,few:f,many:p,other:m,offset:h}){let g=(0,t.useContext)(i);if(!g)throw Error(`[fluenti] <Plural> must be used within an <I18nProvider>`);let{messages:_,components:v}=e.a(e.o,{zero:l,one:u,two:d,few:f,many:p,other:m}),y=e.t({..._.zero!==void 0&&{zero:_.zero},..._.one!==void 0&&{one:_.one},..._.two!==void 0&&{two:_.two},..._.few!==void 0&&{few:_.few},..._.many!==void 0&&{many:_.many},other:_.other??``},h);return(0,r.jsx)(r.Fragment,{children:e.i({id:o??(s===void 0?y:(0,n.hashMessage)(y,s)),message:y,...s===void 0?{}:{context:s},...c===void 0?{}:{comment:c}},{count:a},(e,t)=>g.i18n.t(e,t),v)})});function f(a){let o=(0,t.useContext)(i);if(!o)throw Error(`[fluenti] <Select> must be used within an <I18nProvider>`);let{value:s,id:c,context:l,comment:u,other:d,options:f,...p}=a,m=f===void 0?{...Object.fromEntries(Object.entries(p).filter(([e])=>![`value`,`id`,`context`,`comment`,`options`,`other`].includes(e))),other:d}:{...f,other:d},h=[...Object.keys(m).filter(e=>e!==`other`),`other`],{messages:g,components:_}=e.a(h,m),v=e.r(Object.fromEntries([...h].map(e=>[e,g[e]??``]))),y=e.n(v.forms);return(0,r.jsx)(r.Fragment,{children:e.i({id:c??(l===void 0?y:(0,n.hashMessage)(y,l)),message:y,...l===void 0?{}:{context:l},...u===void 0?{}:{comment:u}},{value:v.valueMap[s]??`other`},(e,t)=>o.i18n.t(e,t),_)})}function p({value:e,style:n}){let a=(0,t.useContext)(i);if(!a)throw Error(`[fluenti] <DateTime> must be used within an <I18nProvider>`);return(0,r.jsx)(r.Fragment,{children:a.i18n.d(e,n)})}function m({value:e,style:n}){let a=(0,t.useContext)(i);if(!a)throw Error(`[fluenti] <Number> must be used within an <I18nProvider>`);return(0,r.jsx)(r.Fragment,{children:a.i18n.n(e,n)})}exports.DateTime=p,exports.I18nContext=i,exports.I18nProvider=s,exports.NumberFormat=m,exports.Plural=d,exports.Select=f,exports.Trans=u,Object.defineProperty(exports,`msg`,{enumerable:!0,get:function(){return n.msg}}),exports.t=l,exports.useI18n=c;
2
+ "use client";Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require(`./icu-rich-XY1SdM5K.cjs`);let t=require(`react`),n=require(`@fluenti/core`),r=require(`react/jsx-runtime`);var i=(0,t.createContext)(null),a=Symbol.for(`fluenti.runtime.react`);function o(){let e=globalThis[a];return typeof e==`object`&&e?e:null}function s({locale:e,fallbackLocale:a,messages:s,loadMessages:c,fallbackChain:l,dateFormats:u,numberFormats:d,missing:f,children:p}){let[m,h]=(0,t.useState)(e),[g,_]=(0,t.useState)(!1),[v,y]=(0,t.useState)(s??{}),[b,x]=(0,t.useState)(s?Object.keys(s):[]),S=(0,t.useRef)(v);S.current=v;let C=(0,t.useRef)(0),w=(0,t.useMemo)(()=>{let e={locale:m,messages:v};return a!==void 0&&(e.fallbackLocale=a),l!==void 0&&(e.fallbackChain=l),u!==void 0&&(e.dateFormats=u),d!==void 0&&(e.numberFormats=d),f!==void 0&&(e.missing=f),(0,n.createFluent)(e)},[m,v,a,l,u,d,f]);(0,t.useEffect)(()=>{e!==m&&T(e)},[e]);let T=(0,t.useCallback)(async e=>{let t=++C.current;if(S.current[e]&&!c){h(e);return}let n=c?o():null;if(S.current[e]){n?.__switchLocale&&await n.__switchLocale(e),h(e);return}if(!c){console.warn(`[fluenti] No messages for locale "${e}" and no loadMessages function provided`);return}_(!0);try{let r=await c(e);if(t!==C.current)return;let i=typeof r==`object`&&r&&`default`in r?r.default:r;y(t=>({...t,[e]:i})),x(t=>[...new Set([...t,e])]),n?.__switchLocale&&await n.__switchLocale(e),h(e)}catch(n){t===C.current&&console.error(`[fluenti] Failed to load locale "${e}"`,n)}finally{t===C.current&&_(!1)}},[c]),E=(0,t.useCallback)(async e=>{let t=o();if(!(S.current[e]||!c))try{let n=await c(e),r=typeof n==`object`&&n&&`default`in n?n.default:n;y(t=>({...t,[e]:r})),x(t=>[...new Set([...t,e])]),t?.__preloadLocale&&await t.__preloadLocale(e)}catch{}},[c]),D=(0,t.useMemo)(()=>({i18n:w,t:w.t.bind(w),d:w.d.bind(w),n:w.n.bind(w),format:w.format.bind(w),loadMessages:w.loadMessages.bind(w),getLocales:w.getLocales.bind(w),locale:m,setLocale:T,isLoading:g,loadedLocales:b,preloadLocale:E}),[w,m,T,g,b,E]);return(0,r.jsx)(i.Provider,{value:D,children:p})}function c(){let e=(0,t.useContext)(i);if(!e)throw Error(`[fluenti] useI18n() must be used within an <I18nProvider>. Wrap your app with <I18nProvider> to provide i18n context.`);return e}var l=((...e)=>{throw Error("[fluenti] `t` imported from '@fluenti/react' is a compile-time API. Use it only with the Fluenti build transform inside a component or custom hook. For runtime lookups, use useI18n().t(...).")}),u=(0,t.memo)(function({children:a,id:o,context:s,comment:c,render:l,__id:u,__message:d,__components:f}){let p=(0,t.useContext)(i);if(!p)throw Error(`[fluenti] <Trans> must be used within an <I18nProvider>`);let m=d!==void 0,{message:h,components:g}=(0,t.useMemo)(()=>m?{message:d,components:f??[]}:e.s(a),[m,d,f,a]),_=(0,t.useMemo)(()=>o??u??(0,n.hashMessage)(h,s),[o,u,h,s]),v=e.c(p.i18n.t({id:_,message:h,...s===void 0?{}:{context:s},...c===void 0?{}:{comment:c}}),g);return l?l(v):(0,r.jsx)(r.Fragment,{children:v})}),d=(0,t.memo)(function({value:a,id:o,context:s,comment:c,zero:l,one:u,two:d,few:f,many:p,other:m,offset:h}){let g=(0,t.useContext)(i);if(!g)throw Error(`[fluenti] <Plural> must be used within an <I18nProvider>`);let{messages:_,components:v}=e.a(e.o,{zero:l,one:u,two:d,few:f,many:p,other:m}),y=e.t({..._.zero!==void 0&&{zero:_.zero},..._.one!==void 0&&{one:_.one},..._.two!==void 0&&{two:_.two},..._.few!==void 0&&{few:_.few},..._.many!==void 0&&{many:_.many},other:_.other??``},h);return(0,r.jsx)(r.Fragment,{children:e.i({id:o??(s===void 0?y:(0,n.hashMessage)(y,s)),message:y,...s===void 0?{}:{context:s},...c===void 0?{}:{comment:c}},{count:a},(e,t)=>g.i18n.t(e,t),v)})}),f=(0,t.memo)(function(a){let o=(0,t.useContext)(i);if(!o)throw Error(`[fluenti] <Select> must be used within an <I18nProvider>`);let{value:s,id:c,context:l,comment:u,other:d,options:f,...p}=a,m=f===void 0?{...Object.fromEntries(Object.entries(p).filter(([e])=>![`value`,`id`,`context`,`comment`,`options`,`other`].includes(e))),other:d}:{...f,other:d},h=[...Object.keys(m).filter(e=>e!==`other`),`other`],{messages:g,components:_}=e.a(h,m),v=e.r(Object.fromEntries([...h].map(e=>[e,g[e]??``]))),y=e.n(v.forms);return(0,r.jsx)(r.Fragment,{children:e.i({id:c??(l===void 0?y:(0,n.hashMessage)(y,l)),message:y,...l===void 0?{}:{context:l},...u===void 0?{}:{comment:u}},{value:v.valueMap[s]??`other`},(e,t)=>o.i18n.t(e,t),_)})}),p=(0,t.memo)(function({value:e,style:n}){let a=(0,t.useContext)(i);if(!a)throw Error(`[fluenti] <DateTime> must be used within an <I18nProvider>`);return(0,r.jsx)(r.Fragment,{children:a.i18n.d(e,n)})}),m=(0,t.memo)(function({value:e,style:n}){let a=(0,t.useContext)(i);if(!a)throw Error(`[fluenti] <Number> must be used within an <I18nProvider>`);return(0,r.jsx)(r.Fragment,{children:a.i18n.n(e,n)})});exports.DateTime=p,exports.I18nContext=i,exports.I18nProvider=s,exports.NumberFormat=m,exports.Plural=d,exports.Select=f,exports.Trans=u,Object.defineProperty(exports,`msg`,{enumerable:!0,get:function(){return n.msg}}),exports.t=l,exports.useI18n=c;
3
3
  //# sourceMappingURL=index.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.cjs","names":[],"sources":["../src/context.ts","../src/provider.tsx","../src/hooks/useI18n.ts","../src/compile-time-t.ts","../src/components/Trans.tsx","../src/components/Plural.tsx","../src/components/Select.tsx","../src/components/DateTime.tsx","../src/components/Number.tsx"],"sourcesContent":["import { createContext } from 'react'\nimport type { I18nContextValue } from './types'\n\nexport const I18nContext = createContext<I18nContextValue | null>(null)\n","import { useState, useCallback, useEffect, useMemo, useRef } from 'react'\nimport { createFluent } from '@fluenti/core'\nimport type { Messages } from '@fluenti/core'\nimport { I18nContext } from './context'\nimport type { I18nProviderProps } from './types'\n\ninterface SplitRuntimeModule {\n __switchLocale?: (locale: string) => Promise<void>\n __preloadLocale?: (locale: string) => Promise<void>\n}\n\nconst SPLIT_RUNTIME_KEY = Symbol.for('fluenti.runtime.react')\n\nfunction getSplitRuntimeModule(): SplitRuntimeModule | null {\n const runtime = (globalThis as Record<PropertyKey, unknown>)[SPLIT_RUNTIME_KEY]\n return typeof runtime === 'object' && runtime !== null\n ? runtime as SplitRuntimeModule\n : null\n}\n\nexport function I18nProvider({\n locale,\n fallbackLocale,\n messages,\n loadMessages,\n fallbackChain,\n dateFormats,\n numberFormats,\n missing,\n children,\n}: I18nProviderProps) {\n const [currentLocale, setCurrentLocale] = useState(locale)\n const [isLoading, setIsLoading] = useState(false)\n const [loadedMessages, setLoadedMessages] = useState<Record<string, Messages>>(\n messages ?? {},\n )\n const [loadedLocales, setLoadedLocales] = useState<string[]>(\n messages ? Object.keys(messages) : [],\n )\n\n // Use ref to avoid stale closures in callbacks\n const loadedMessagesRef = useRef(loadedMessages)\n loadedMessagesRef.current = loadedMessages\n\n // Guard against out-of-order async locale loads (race condition protection)\n const localeRequestRef = useRef(0)\n\n const i18n = useMemo(() => {\n const config: Parameters<typeof createFluent>[0] = {\n locale: currentLocale,\n messages: loadedMessages,\n }\n if (fallbackLocale !== undefined) config.fallbackLocale = fallbackLocale\n if (fallbackChain !== undefined) config.fallbackChain = fallbackChain\n if (dateFormats !== undefined) config.dateFormats = dateFormats\n if (numberFormats !== undefined) config.numberFormats = numberFormats\n if (missing !== undefined) config.missing = missing\n return createFluent(config)\n }, [currentLocale, loadedMessages, fallbackLocale, fallbackChain, dateFormats, numberFormats, missing])\n\n // Sync external locale prop changes\n useEffect(() => {\n if (locale !== currentLocale) {\n void handleSetLocale(locale)\n }\n // Intentionally only depend on `locale` — we want to sync when the\n // external prop changes, not when internal state (`currentLocale`,\n // `handleSetLocale`) updates, which would cause infinite re-renders.\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [locale])\n\n const handleSetLocale = useCallback(\n async (newLocale: string) => {\n const requestId = ++localeRequestRef.current\n\n if (loadedMessagesRef.current[newLocale] && !loadMessages) {\n setCurrentLocale(newLocale)\n return\n }\n\n const splitRuntime = loadMessages ? getSplitRuntimeModule() : null\n\n if (loadedMessagesRef.current[newLocale]) {\n if (splitRuntime?.__switchLocale) {\n await splitRuntime.__switchLocale(newLocale)\n }\n setCurrentLocale(newLocale)\n return\n }\n\n if (!loadMessages) {\n console.warn(\n `[fluenti] No messages for locale \"${newLocale}\" and no loadMessages function provided`,\n )\n return\n }\n\n setIsLoading(true)\n try {\n const msgs = await loadMessages(newLocale)\n\n // A newer request has superseded this one — discard stale result\n if (requestId !== localeRequestRef.current) return\n\n const resolved: Messages =\n typeof msgs === 'object' && msgs !== null && 'default' in msgs\n ? (msgs as { default: Messages }).default\n : (msgs as Messages)\n setLoadedMessages((prev) => ({ ...prev, [newLocale]: resolved }))\n setLoadedLocales((prev) => [...new Set([...prev, newLocale])])\n if (splitRuntime?.__switchLocale) {\n await splitRuntime.__switchLocale(newLocale)\n }\n setCurrentLocale(newLocale)\n } catch (err) {\n // Only log if this request is still the latest\n if (requestId === localeRequestRef.current) {\n console.error(`[fluenti] Failed to load locale \"${newLocale}\"`, err)\n }\n } finally {\n if (requestId === localeRequestRef.current) {\n setIsLoading(false)\n }\n }\n },\n [loadMessages],\n )\n\n const preloadLocale = useCallback(\n async (loc: string) => {\n const splitRuntime = getSplitRuntimeModule()\n if (loadedMessagesRef.current[loc] || !loadMessages) return\n try {\n const msgs = await loadMessages(loc)\n const resolved: Messages =\n typeof msgs === 'object' && msgs !== null && 'default' in msgs\n ? (msgs as { default: Messages }).default\n : (msgs as Messages)\n setLoadedMessages((prev) => ({ ...prev, [loc]: resolved }))\n setLoadedLocales((prev) => [...new Set([...prev, loc])])\n if (splitRuntime?.__preloadLocale) {\n await splitRuntime.__preloadLocale(loc)\n }\n } catch {\n // Silent fail for preload\n }\n },\n [loadMessages],\n )\n\n const ctx = useMemo(\n () => ({\n i18n,\n t: i18n.t.bind(i18n),\n d: i18n.d.bind(i18n),\n n: i18n.n.bind(i18n),\n format: i18n.format.bind(i18n),\n loadMessages: i18n.loadMessages.bind(i18n),\n getLocales: i18n.getLocales.bind(i18n),\n locale: currentLocale,\n setLocale: handleSetLocale,\n isLoading,\n loadedLocales,\n preloadLocale,\n }),\n [i18n, currentLocale, handleSetLocale, isLoading, loadedLocales, preloadLocale],\n )\n\n return <I18nContext.Provider value={ctx}>{children}</I18nContext.Provider>\n}\n","import { useContext } from 'react'\nimport { I18nContext } from '../context'\nimport type { I18nContextValue } from '../types'\n\n/**\n * Primary hook for accessing i18n functions.\n *\n * Returns locale, setLocale, isLoading, loadedLocales, preloadLocale,\n * and the underlying i18n instance with t(), d(), n() methods.\n *\n * @throws If used outside of `<I18nProvider>`\n */\nexport function useI18n(): I18nContextValue {\n const ctx = useContext(I18nContext)\n if (!ctx) {\n throw new Error(\n '[fluenti] useI18n() must be used within an <I18nProvider>. ' +\n 'Wrap your app with <I18nProvider> to provide i18n context.',\n )\n }\n return ctx\n}\n","import type { CompileTimeT } from '@fluenti/core'\n\nexport const t: CompileTimeT = ((..._args: unknown[]) => {\n throw new Error(\n \"[fluenti] `t` imported from '@fluenti/react' is a compile-time API. \" +\n 'Use it only with the Fluenti build transform inside a component or custom hook. ' +\n 'For runtime lookups, use useI18n().t(...).',\n )\n}) as CompileTimeT\n","import {\n memo,\n useContext,\n useMemo,\n type ReactElement,\n type ReactNode,\n} from 'react'\nimport { I18nContext } from '../context'\nimport { hashMessage, extractMessage, reconstruct } from './trans-core'\n\nexport interface TransProps {\n /** Source text with embedded components */\n children: ReactNode\n /** Override auto-generated hash ID */\n id?: string\n /** Message context used for identity and translator disambiguation */\n context?: string\n /** Context comment for translators */\n comment?: string\n /** Custom render wrapper */\n render?: (translation: ReactNode) => ReactNode\n /** @internal Pre-computed message ID from build plugin */\n __id?: string\n /** @internal Pre-computed ICU message from build plugin */\n __message?: string\n /** @internal Pre-computed component list from build plugin */\n __components?: ReactElement[]\n}\n\n/**\n * `<Trans>` component for rich-text translations containing nested React elements.\n *\n * @example\n * ```tsx\n * <Trans>Read the <a href=\"/docs\">documentation</a> for more info.</Trans>\n * ```\n */\nexport const Trans = memo(function Trans({\n children,\n id,\n context,\n comment,\n render,\n __id,\n __message,\n __components,\n}: TransProps) {\n const ctx = useContext(I18nContext)\n if (!ctx) {\n throw new Error('[fluenti] <Trans> must be used within an <I18nProvider>')\n }\n\n // Fast path: build plugin pre-computed message and components\n const hasPrecomputed = __message !== undefined\n\n const { message, components } = useMemo(\n () => hasPrecomputed\n ? { message: __message!, components: __components ?? [] }\n : extractMessage(children),\n [hasPrecomputed, __message, __components, children],\n )\n const messageId = useMemo(\n () => id ?? __id ?? hashMessage(message, context),\n [id, __id, message, context],\n )\n\n const translated = ctx.i18n.t(\n {\n id: messageId,\n message,\n ...(context !== undefined ? { context } : {}),\n ...(comment !== undefined ? { comment } : {}),\n },\n )\n\n const result = reconstruct(translated, components)\n return render ? render(result) : <>{result}</>\n})\n","import { memo, useContext, type ReactNode } from 'react'\nimport { hashMessage } from '@fluenti/core'\nimport { I18nContext } from '../context'\nimport { PLURAL_CATEGORIES, type PluralCategory } from './plural-core'\nimport { buildICUPluralMessage, renderRichTranslation, serializeRichForms } from './icu-rich'\n\nexport interface PluralProps {\n /** The count value */\n value: number\n /** Override the auto-generated synthetic ICU message id */\n id?: string\n /** Message context used for identity and translator disambiguation */\n context?: string\n /** Translator-facing note preserved in extraction catalogs */\n comment?: string\n /** Text for zero (if language supports) */\n zero?: ReactNode\n /** Singular form. `#` replaced with value */\n one?: ReactNode\n /** Dual form (Arabic, etc.) */\n two?: ReactNode\n /** Few form (Slavic languages, etc.) */\n few?: ReactNode\n /** Many form */\n many?: ReactNode\n /** Default plural form */\n other: ReactNode\n /** Offset from value before selecting form */\n offset?: number\n}\n\n/**\n * `<Plural>` — ICU plural handling as a component.\n *\n * @example\n * ```tsx\n * <Plural value={count} zero=\"No messages\" one=\"# message\" other=\"# messages\" />\n * ```\n */\nexport const Plural = memo(function Plural({\n value,\n id,\n context,\n comment,\n zero,\n one,\n two,\n few,\n many,\n other,\n offset,\n}: PluralProps) {\n const ctx = useContext(I18nContext)\n if (!ctx) {\n throw new Error('[fluenti] <Plural> must be used within an <I18nProvider>')\n }\n\n const forms: Record<PluralCategory, ReactNode | undefined> = {\n zero,\n one,\n two,\n few,\n many,\n other,\n }\n const { messages, components } = serializeRichForms(PLURAL_CATEGORIES, forms)\n const icuMessage = buildICUPluralMessage(\n {\n ...(messages.zero !== undefined && { zero: messages.zero }),\n ...(messages.one !== undefined && { one: messages.one }),\n ...(messages.two !== undefined && { two: messages.two }),\n ...(messages.few !== undefined && { few: messages.few }),\n ...(messages.many !== undefined && { many: messages.many }),\n other: messages.other ?? '',\n },\n offset,\n )\n\n const descriptor = {\n id: id ?? (context === undefined ? icuMessage : hashMessage(icuMessage, context)),\n message: icuMessage,\n ...(context !== undefined ? { context } : {}),\n ...(comment !== undefined ? { comment } : {}),\n }\n\n return <>{renderRichTranslation(descriptor, { count: value }, (desc, values) => ctx.i18n.t(desc, values), components)}</>\n})\n","import { useContext, type ReactNode } from 'react'\nimport { hashMessage } from '@fluenti/core'\nimport { I18nContext } from '../context'\nimport { buildICUSelectMessage, normalizeSelectForms, renderRichTranslation, serializeRichForms } from './icu-rich'\n\nexport interface SelectProps {\n /** The selector value */\n value: string\n /** Override the auto-generated synthetic ICU message id */\n id?: string\n /** Message context used for identity and translator disambiguation */\n context?: string\n /** Translator-facing note preserved in extraction catalogs */\n comment?: string\n /** Default case */\n other: ReactNode\n /** Type-safe named options. Takes precedence over direct case props. */\n options?: Record<string, ReactNode>\n /** Named cases — any string key maps to a ReactNode */\n [key: string]: ReactNode | Record<string, ReactNode> | undefined\n}\n\n/**\n * `<Select>` — ICU select for gender, role, or other categorical values.\n *\n * @example\n * ```tsx\n * <Select\n * value={gender}\n * male=\"He liked your post\"\n * female=\"She liked your post\"\n * other=\"They liked your post\"\n * />\n * ```\n */\nexport function Select(props: SelectProps) {\n const ctx = useContext(I18nContext)\n if (!ctx) {\n throw new Error('[fluenti] <Select> must be used within an <I18nProvider>')\n }\n\n const { value, id, context, comment, other, options, ...cases } = props\n const forms: Record<string, ReactNode | undefined> = options === undefined\n ? {\n ...Object.fromEntries(\n Object.entries(cases).filter(([key]) => !['value', 'id', 'context', 'comment', 'options', 'other'].includes(key)),\n ),\n other,\n }\n : {\n ...options,\n other,\n }\n\n const orderedKeys = [...Object.keys(forms).filter(key => key !== 'other'), 'other'] as const\n const { messages, components } = serializeRichForms(orderedKeys, forms)\n const normalized = normalizeSelectForms(\n Object.fromEntries(\n [...orderedKeys].map((key) => [key, messages[key] ?? '']),\n ),\n )\n const icuMessage = buildICUSelectMessage(normalized.forms)\n\n const descriptor = {\n id: id ?? (context === undefined ? icuMessage : hashMessage(icuMessage, context)),\n message: icuMessage,\n ...(context !== undefined ? { context } : {}),\n ...(comment !== undefined ? { comment } : {}),\n }\n\n return <>{renderRichTranslation(\n descriptor,\n { value: normalized.valueMap[value] ?? 'other' },\n (desc, values) => ctx.i18n.t(desc, values),\n components,\n )}</>\n}\n","import { useContext } from 'react'\nimport { I18nContext } from '../context'\n\nexport interface DateTimeProps {\n /** Date value to format */\n value: Date | number\n /** Named format style */\n style?: string\n}\n\n/**\n * `<DateTime>` — formatting component using Intl APIs.\n *\n * @example\n * ```tsx\n * <DateTime value={new Date()} style=\"long\" />\n * ```\n */\nexport function DateTime({ value, style }: DateTimeProps) {\n const ctx = useContext(I18nContext)\n if (!ctx) {\n throw new Error('[fluenti] <DateTime> must be used within an <I18nProvider>')\n }\n return <>{ctx.i18n.d(value, style)}</>\n}\n","import { useContext } from 'react'\nimport { I18nContext } from '../context'\n\nexport interface NumberProps {\n /** Number value to format */\n value: number\n /** Named format style */\n style?: string\n}\n\n/**\n * `<Number>` — number formatting component using Intl APIs.\n *\n * @example\n * ```tsx\n * <Number value={1234.56} style=\"currency\" />\n * ```\n */\nexport function NumberFormat({ value, style }: NumberProps) {\n const ctx = useContext(I18nContext)\n if (!ctx) {\n throw new Error('[fluenti] <Number> must be used within an <I18nProvider>')\n }\n return <>{ctx.i18n.n(value, style)}</>\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"index.cjs","names":[],"sources":["../src/context.ts","../src/provider.tsx","../src/hooks/useI18n.ts","../src/compile-time-t.ts","../src/components/Trans.tsx","../src/components/Plural.tsx","../src/components/Select.tsx","../src/components/DateTime.tsx","../src/components/Number.tsx"],"sourcesContent":["import { createContext } from 'react'\nimport type { I18nContextValue } from './types'\n\nexport const I18nContext = createContext<I18nContextValue | null>(null)\n","import { useState, useCallback, useEffect, useMemo, useRef } from 'react'\nimport { createFluent } from '@fluenti/core'\nimport type { Messages } from '@fluenti/core'\nimport { I18nContext } from './context'\nimport type { I18nProviderProps } from './types'\n\ninterface SplitRuntimeModule {\n __switchLocale?: (locale: string) => Promise<void>\n __preloadLocale?: (locale: string) => Promise<void>\n}\n\nconst SPLIT_RUNTIME_KEY = Symbol.for('fluenti.runtime.react')\n\nfunction getSplitRuntimeModule(): SplitRuntimeModule | null {\n const runtime = (globalThis as Record<PropertyKey, unknown>)[SPLIT_RUNTIME_KEY]\n return typeof runtime === 'object' && runtime !== null\n ? runtime as SplitRuntimeModule\n : null\n}\n\nexport function I18nProvider({\n locale,\n fallbackLocale,\n messages,\n loadMessages,\n fallbackChain,\n dateFormats,\n numberFormats,\n missing,\n children,\n}: I18nProviderProps) {\n const [currentLocale, setCurrentLocale] = useState(locale)\n const [isLoading, setIsLoading] = useState(false)\n const [loadedMessages, setLoadedMessages] = useState<Record<string, Messages>>(\n messages ?? {},\n )\n const [loadedLocales, setLoadedLocales] = useState<string[]>(\n messages ? Object.keys(messages) : [],\n )\n\n // Use ref to avoid stale closures in callbacks\n const loadedMessagesRef = useRef(loadedMessages)\n loadedMessagesRef.current = loadedMessages\n\n // Guard against out-of-order async locale loads (race condition protection)\n const localeRequestRef = useRef(0)\n\n const i18n = useMemo(() => {\n const config: Parameters<typeof createFluent>[0] = {\n locale: currentLocale,\n messages: loadedMessages,\n }\n if (fallbackLocale !== undefined) config.fallbackLocale = fallbackLocale\n if (fallbackChain !== undefined) config.fallbackChain = fallbackChain\n if (dateFormats !== undefined) config.dateFormats = dateFormats\n if (numberFormats !== undefined) config.numberFormats = numberFormats\n if (missing !== undefined) config.missing = missing\n return createFluent(config)\n }, [currentLocale, loadedMessages, fallbackLocale, fallbackChain, dateFormats, numberFormats, missing])\n\n // Sync external locale prop changes\n useEffect(() => {\n if (locale !== currentLocale) {\n void handleSetLocale(locale)\n }\n // Intentionally only depend on `locale` — we want to sync when the\n // external prop changes, not when internal state (`currentLocale`,\n // `handleSetLocale`) updates, which would cause infinite re-renders.\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [locale])\n\n const handleSetLocale = useCallback(\n async (newLocale: string) => {\n const requestId = ++localeRequestRef.current\n\n if (loadedMessagesRef.current[newLocale] && !loadMessages) {\n setCurrentLocale(newLocale)\n return\n }\n\n const splitRuntime = loadMessages ? getSplitRuntimeModule() : null\n\n if (loadedMessagesRef.current[newLocale]) {\n if (splitRuntime?.__switchLocale) {\n await splitRuntime.__switchLocale(newLocale)\n }\n setCurrentLocale(newLocale)\n return\n }\n\n if (!loadMessages) {\n console.warn(\n `[fluenti] No messages for locale \"${newLocale}\" and no loadMessages function provided`,\n )\n return\n }\n\n setIsLoading(true)\n try {\n const msgs = await loadMessages(newLocale)\n\n // A newer request has superseded this one — discard stale result\n if (requestId !== localeRequestRef.current) return\n\n const resolved: Messages =\n typeof msgs === 'object' && msgs !== null && 'default' in msgs\n ? (msgs as { default: Messages }).default\n : (msgs as Messages)\n setLoadedMessages((prev) => ({ ...prev, [newLocale]: resolved }))\n setLoadedLocales((prev) => [...new Set([...prev, newLocale])])\n if (splitRuntime?.__switchLocale) {\n await splitRuntime.__switchLocale(newLocale)\n }\n setCurrentLocale(newLocale)\n } catch (err) {\n // Only log if this request is still the latest\n if (requestId === localeRequestRef.current) {\n console.error(`[fluenti] Failed to load locale \"${newLocale}\"`, err)\n }\n } finally {\n if (requestId === localeRequestRef.current) {\n setIsLoading(false)\n }\n }\n },\n [loadMessages],\n )\n\n const preloadLocale = useCallback(\n async (loc: string) => {\n const splitRuntime = getSplitRuntimeModule()\n if (loadedMessagesRef.current[loc] || !loadMessages) return\n try {\n const msgs = await loadMessages(loc)\n const resolved: Messages =\n typeof msgs === 'object' && msgs !== null && 'default' in msgs\n ? (msgs as { default: Messages }).default\n : (msgs as Messages)\n setLoadedMessages((prev) => ({ ...prev, [loc]: resolved }))\n setLoadedLocales((prev) => [...new Set([...prev, loc])])\n if (splitRuntime?.__preloadLocale) {\n await splitRuntime.__preloadLocale(loc)\n }\n } catch {\n // Silent fail for preload\n }\n },\n [loadMessages],\n )\n\n const ctx = useMemo(\n () => ({\n i18n,\n t: i18n.t.bind(i18n),\n d: i18n.d.bind(i18n),\n n: i18n.n.bind(i18n),\n format: i18n.format.bind(i18n),\n loadMessages: i18n.loadMessages.bind(i18n),\n getLocales: i18n.getLocales.bind(i18n),\n locale: currentLocale,\n setLocale: handleSetLocale,\n isLoading,\n loadedLocales,\n preloadLocale,\n }),\n [i18n, currentLocale, handleSetLocale, isLoading, loadedLocales, preloadLocale],\n )\n\n return <I18nContext.Provider value={ctx}>{children}</I18nContext.Provider>\n}\n","import { useContext } from 'react'\nimport { I18nContext } from '../context'\nimport type { I18nContextValue } from '../types'\n\n/**\n * Primary hook for accessing i18n functions.\n *\n * Returns locale, setLocale, isLoading, loadedLocales, preloadLocale,\n * and the underlying i18n instance with t(), d(), n() methods.\n *\n * @throws If used outside of `<I18nProvider>`\n */\nexport function useI18n(): I18nContextValue {\n const ctx = useContext(I18nContext)\n if (!ctx) {\n throw new Error(\n '[fluenti] useI18n() must be used within an <I18nProvider>. ' +\n 'Wrap your app with <I18nProvider> to provide i18n context.',\n )\n }\n return ctx\n}\n","import type { CompileTimeT } from '@fluenti/core'\n\nexport const t: CompileTimeT = ((..._args: unknown[]) => {\n throw new Error(\n \"[fluenti] `t` imported from '@fluenti/react' is a compile-time API. \" +\n 'Use it only with the Fluenti build transform inside a component or custom hook. ' +\n 'For runtime lookups, use useI18n().t(...).',\n )\n}) as CompileTimeT\n","import {\n memo,\n useContext,\n useMemo,\n type ReactElement,\n type ReactNode,\n} from 'react'\nimport { I18nContext } from '../context'\nimport { hashMessage, extractMessage, reconstruct } from './trans-core'\n\nexport interface TransProps {\n /** Source text with embedded components */\n children: ReactNode\n /** Override auto-generated hash ID */\n id?: string\n /** Message context used for identity and translator disambiguation */\n context?: string\n /** Context comment for translators */\n comment?: string\n /** Custom render wrapper */\n render?: (translation: ReactNode) => ReactNode\n /** @internal Pre-computed message ID from build plugin */\n __id?: string\n /** @internal Pre-computed ICU message from build plugin */\n __message?: string\n /** @internal Pre-computed component list from build plugin */\n __components?: ReactElement[]\n}\n\n/**\n * `<Trans>` component for rich-text translations containing nested React elements.\n *\n * @example\n * ```tsx\n * <Trans>Read the <a href=\"/docs\">documentation</a> for more info.</Trans>\n * ```\n */\nexport const Trans = memo(function Trans({\n children,\n id,\n context,\n comment,\n render,\n __id,\n __message,\n __components,\n}: TransProps) {\n const ctx = useContext(I18nContext)\n if (!ctx) {\n throw new Error('[fluenti] <Trans> must be used within an <I18nProvider>')\n }\n\n // Fast path: build plugin pre-computed message and components\n const hasPrecomputed = __message !== undefined\n\n const { message, components } = useMemo(\n () => hasPrecomputed\n ? { message: __message!, components: __components ?? [] }\n : extractMessage(children),\n [hasPrecomputed, __message, __components, children],\n )\n const messageId = useMemo(\n () => id ?? __id ?? hashMessage(message, context),\n [id, __id, message, context],\n )\n\n const translated = ctx.i18n.t(\n {\n id: messageId,\n message,\n ...(context !== undefined ? { context } : {}),\n ...(comment !== undefined ? { comment } : {}),\n },\n )\n\n const result = reconstruct(translated, components)\n return render ? render(result) : <>{result}</>\n})\n","import { memo, useContext, type ReactNode } from 'react'\nimport { hashMessage } from '@fluenti/core'\nimport { I18nContext } from '../context'\nimport { PLURAL_CATEGORIES, type PluralCategory } from './plural-core'\nimport { buildICUPluralMessage, renderRichTranslation, serializeRichForms } from './icu-rich'\n\nexport interface PluralProps {\n /** The count value */\n value: number\n /** Override the auto-generated synthetic ICU message id */\n id?: string\n /** Message context used for identity and translator disambiguation */\n context?: string\n /** Translator-facing note preserved in extraction catalogs */\n comment?: string\n /** Text for zero (if language supports) */\n zero?: ReactNode\n /** Singular form. `#` replaced with value */\n one?: ReactNode\n /** Dual form (Arabic, etc.) */\n two?: ReactNode\n /** Few form (Slavic languages, etc.) */\n few?: ReactNode\n /** Many form */\n many?: ReactNode\n /** Default plural form */\n other: ReactNode\n /** Offset from value before selecting form */\n offset?: number\n}\n\n/**\n * `<Plural>` — ICU plural handling as a component.\n *\n * @example\n * ```tsx\n * <Plural value={count} zero=\"No messages\" one=\"# message\" other=\"# messages\" />\n * ```\n */\nexport const Plural = memo(function Plural({\n value,\n id,\n context,\n comment,\n zero,\n one,\n two,\n few,\n many,\n other,\n offset,\n}: PluralProps) {\n const ctx = useContext(I18nContext)\n if (!ctx) {\n throw new Error('[fluenti] <Plural> must be used within an <I18nProvider>')\n }\n\n const forms: Record<PluralCategory, ReactNode | undefined> = {\n zero,\n one,\n two,\n few,\n many,\n other,\n }\n const { messages, components } = serializeRichForms(PLURAL_CATEGORIES, forms)\n const icuMessage = buildICUPluralMessage(\n {\n ...(messages.zero !== undefined && { zero: messages.zero }),\n ...(messages.one !== undefined && { one: messages.one }),\n ...(messages.two !== undefined && { two: messages.two }),\n ...(messages.few !== undefined && { few: messages.few }),\n ...(messages.many !== undefined && { many: messages.many }),\n other: messages.other ?? '',\n },\n offset,\n )\n\n const descriptor = {\n id: id ?? (context === undefined ? icuMessage : hashMessage(icuMessage, context)),\n message: icuMessage,\n ...(context !== undefined ? { context } : {}),\n ...(comment !== undefined ? { comment } : {}),\n }\n\n return <>{renderRichTranslation(descriptor, { count: value }, (desc, values) => ctx.i18n.t(desc, values), components)}</>\n})\n","import { memo, useContext, type ReactNode } from 'react'\nimport { hashMessage } from '@fluenti/core'\nimport { I18nContext } from '../context'\nimport { buildICUSelectMessage, normalizeSelectForms, renderRichTranslation, serializeRichForms } from './icu-rich'\n\nexport interface SelectProps {\n /** The selector value */\n value: string\n /** Override the auto-generated synthetic ICU message id */\n id?: string\n /** Message context used for identity and translator disambiguation */\n context?: string\n /** Translator-facing note preserved in extraction catalogs */\n comment?: string\n /** Default case */\n other: ReactNode\n /** Type-safe named options. Takes precedence over direct case props. */\n options?: Record<string, ReactNode>\n /** Named cases — any string key maps to a ReactNode */\n [key: string]: ReactNode | Record<string, ReactNode> | undefined\n}\n\n/**\n * `<Select>` — ICU select for gender, role, or other categorical values.\n *\n * @example\n * ```tsx\n * <Select\n * value={gender}\n * male=\"He liked your post\"\n * female=\"She liked your post\"\n * other=\"They liked your post\"\n * />\n * ```\n */\nexport const Select = memo(function Select(props: SelectProps) {\n const ctx = useContext(I18nContext)\n if (!ctx) {\n throw new Error('[fluenti] <Select> must be used within an <I18nProvider>')\n }\n\n const { value, id, context, comment, other, options, ...cases } = props\n const forms: Record<string, ReactNode | undefined> = options === undefined\n ? {\n ...Object.fromEntries(\n Object.entries(cases).filter(([key]) => !['value', 'id', 'context', 'comment', 'options', 'other'].includes(key)),\n ),\n other,\n }\n : {\n ...options,\n other,\n }\n\n const orderedKeys = [...Object.keys(forms).filter(key => key !== 'other'), 'other'] as const\n const { messages, components } = serializeRichForms(orderedKeys, forms)\n const normalized = normalizeSelectForms(\n Object.fromEntries(\n [...orderedKeys].map((key) => [key, messages[key] ?? '']),\n ),\n )\n const icuMessage = buildICUSelectMessage(normalized.forms)\n\n const descriptor = {\n id: id ?? (context === undefined ? icuMessage : hashMessage(icuMessage, context)),\n message: icuMessage,\n ...(context !== undefined ? { context } : {}),\n ...(comment !== undefined ? { comment } : {}),\n }\n\n return <>{renderRichTranslation(\n descriptor,\n { value: normalized.valueMap[value] ?? 'other' },\n (desc, values) => ctx.i18n.t(desc, values),\n components,\n )}</>\n})\n","import { memo, useContext } from 'react'\nimport { I18nContext } from '../context'\n\nexport interface DateTimeProps {\n /** Date value to format */\n value: Date | number\n /** Named format style */\n style?: string\n}\n\n/**\n * `<DateTime>` — formatting component using Intl APIs.\n *\n * @example\n * ```tsx\n * <DateTime value={new Date()} style=\"long\" />\n * ```\n */\nexport const DateTime = memo(function DateTime({ value, style }: DateTimeProps) {\n const ctx = useContext(I18nContext)\n if (!ctx) {\n throw new Error('[fluenti] <DateTime> must be used within an <I18nProvider>')\n }\n return <>{ctx.i18n.d(value, style)}</>\n})\n","import { memo, useContext } from 'react'\nimport { I18nContext } from '../context'\n\nexport interface NumberProps {\n /** Number value to format */\n value: number\n /** Named format style */\n style?: string\n}\n\n/**\n * `<Number>` — number formatting component using Intl APIs.\n *\n * @example\n * ```tsx\n * <Number value={1234.56} style=\"currency\" />\n * ```\n */\nexport const NumberFormat = memo(function NumberFormat({ value, style }: NumberProps) {\n const ctx = useContext(I18nContext)\n if (!ctx) {\n throw new Error('[fluenti] <Number> must be used within an <I18nProvider>')\n }\n return <>{ctx.i18n.n(value, style)}</>\n})\n"],"mappings":"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"}
package/dist/index.js CHANGED
@@ -153,10 +153,7 @@ var D = ((...e) => {
153
153
  ...i === void 0 ? {} : { context: i },
154
154
  ...o === void 0 ? {} : { comment: o }
155
155
  }, { count: t }, (e, t) => g.i18n.t(e, t), y) });
156
- });
157
- //#endregion
158
- //#region src/components/Select.tsx
159
- function A(t) {
156
+ }), A = u(function(t) {
160
157
  let r = f(S);
161
158
  if (!r) throw Error("[fluenti] <Select> must be used within an <I18nProvider>");
162
159
  let { value: a, id: s, context: c, comment: l, other: u, options: d, ...p } = t, m = d === void 0 ? {
@@ -179,21 +176,15 @@ function A(t) {
179
176
  ...c === void 0 ? {} : { context: c },
180
177
  ...l === void 0 ? {} : { comment: l }
181
178
  }, { value: y.valueMap[a] ?? "other" }, (e, t) => r.i18n.t(e, t), _) });
182
- }
183
- //#endregion
184
- //#region src/components/DateTime.tsx
185
- function j({ value: e, style: t }) {
179
+ }), j = u(function({ value: e, style: t }) {
186
180
  let n = f(S);
187
181
  if (!n) throw Error("[fluenti] <DateTime> must be used within an <I18nProvider>");
188
182
  return /* @__PURE__ */ x(b, { children: n.i18n.d(e, t) });
189
- }
190
- //#endregion
191
- //#region src/components/Number.tsx
192
- function M({ value: e, style: t }) {
183
+ }), M = u(function({ value: e, style: t }) {
193
184
  let n = f(S);
194
185
  if (!n) throw Error("[fluenti] <Number> must be used within an <I18nProvider>");
195
186
  return /* @__PURE__ */ x(b, { children: n.i18n.n(e, t) });
196
- }
187
+ });
197
188
  //#endregion
198
189
  export { j as DateTime, S as I18nContext, T as I18nProvider, M as NumberFormat, k as Plural, A as Select, O as Trans, y as msg, D as t, E as useI18n };
199
190
 
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":[],"sources":["../src/context.ts","../src/provider.tsx","../src/hooks/useI18n.ts","../src/compile-time-t.ts","../src/components/Trans.tsx","../src/components/Plural.tsx","../src/components/Select.tsx","../src/components/DateTime.tsx","../src/components/Number.tsx"],"sourcesContent":["import { createContext } from 'react'\nimport type { I18nContextValue } from './types'\n\nexport const I18nContext = createContext<I18nContextValue | null>(null)\n","import { useState, useCallback, useEffect, useMemo, useRef } from 'react'\nimport { createFluent } from '@fluenti/core'\nimport type { Messages } from '@fluenti/core'\nimport { I18nContext } from './context'\nimport type { I18nProviderProps } from './types'\n\ninterface SplitRuntimeModule {\n __switchLocale?: (locale: string) => Promise<void>\n __preloadLocale?: (locale: string) => Promise<void>\n}\n\nconst SPLIT_RUNTIME_KEY = Symbol.for('fluenti.runtime.react')\n\nfunction getSplitRuntimeModule(): SplitRuntimeModule | null {\n const runtime = (globalThis as Record<PropertyKey, unknown>)[SPLIT_RUNTIME_KEY]\n return typeof runtime === 'object' && runtime !== null\n ? runtime as SplitRuntimeModule\n : null\n}\n\nexport function I18nProvider({\n locale,\n fallbackLocale,\n messages,\n loadMessages,\n fallbackChain,\n dateFormats,\n numberFormats,\n missing,\n children,\n}: I18nProviderProps) {\n const [currentLocale, setCurrentLocale] = useState(locale)\n const [isLoading, setIsLoading] = useState(false)\n const [loadedMessages, setLoadedMessages] = useState<Record<string, Messages>>(\n messages ?? {},\n )\n const [loadedLocales, setLoadedLocales] = useState<string[]>(\n messages ? Object.keys(messages) : [],\n )\n\n // Use ref to avoid stale closures in callbacks\n const loadedMessagesRef = useRef(loadedMessages)\n loadedMessagesRef.current = loadedMessages\n\n // Guard against out-of-order async locale loads (race condition protection)\n const localeRequestRef = useRef(0)\n\n const i18n = useMemo(() => {\n const config: Parameters<typeof createFluent>[0] = {\n locale: currentLocale,\n messages: loadedMessages,\n }\n if (fallbackLocale !== undefined) config.fallbackLocale = fallbackLocale\n if (fallbackChain !== undefined) config.fallbackChain = fallbackChain\n if (dateFormats !== undefined) config.dateFormats = dateFormats\n if (numberFormats !== undefined) config.numberFormats = numberFormats\n if (missing !== undefined) config.missing = missing\n return createFluent(config)\n }, [currentLocale, loadedMessages, fallbackLocale, fallbackChain, dateFormats, numberFormats, missing])\n\n // Sync external locale prop changes\n useEffect(() => {\n if (locale !== currentLocale) {\n void handleSetLocale(locale)\n }\n // Intentionally only depend on `locale` — we want to sync when the\n // external prop changes, not when internal state (`currentLocale`,\n // `handleSetLocale`) updates, which would cause infinite re-renders.\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [locale])\n\n const handleSetLocale = useCallback(\n async (newLocale: string) => {\n const requestId = ++localeRequestRef.current\n\n if (loadedMessagesRef.current[newLocale] && !loadMessages) {\n setCurrentLocale(newLocale)\n return\n }\n\n const splitRuntime = loadMessages ? getSplitRuntimeModule() : null\n\n if (loadedMessagesRef.current[newLocale]) {\n if (splitRuntime?.__switchLocale) {\n await splitRuntime.__switchLocale(newLocale)\n }\n setCurrentLocale(newLocale)\n return\n }\n\n if (!loadMessages) {\n console.warn(\n `[fluenti] No messages for locale \"${newLocale}\" and no loadMessages function provided`,\n )\n return\n }\n\n setIsLoading(true)\n try {\n const msgs = await loadMessages(newLocale)\n\n // A newer request has superseded this one — discard stale result\n if (requestId !== localeRequestRef.current) return\n\n const resolved: Messages =\n typeof msgs === 'object' && msgs !== null && 'default' in msgs\n ? (msgs as { default: Messages }).default\n : (msgs as Messages)\n setLoadedMessages((prev) => ({ ...prev, [newLocale]: resolved }))\n setLoadedLocales((prev) => [...new Set([...prev, newLocale])])\n if (splitRuntime?.__switchLocale) {\n await splitRuntime.__switchLocale(newLocale)\n }\n setCurrentLocale(newLocale)\n } catch (err) {\n // Only log if this request is still the latest\n if (requestId === localeRequestRef.current) {\n console.error(`[fluenti] Failed to load locale \"${newLocale}\"`, err)\n }\n } finally {\n if (requestId === localeRequestRef.current) {\n setIsLoading(false)\n }\n }\n },\n [loadMessages],\n )\n\n const preloadLocale = useCallback(\n async (loc: string) => {\n const splitRuntime = getSplitRuntimeModule()\n if (loadedMessagesRef.current[loc] || !loadMessages) return\n try {\n const msgs = await loadMessages(loc)\n const resolved: Messages =\n typeof msgs === 'object' && msgs !== null && 'default' in msgs\n ? (msgs as { default: Messages }).default\n : (msgs as Messages)\n setLoadedMessages((prev) => ({ ...prev, [loc]: resolved }))\n setLoadedLocales((prev) => [...new Set([...prev, loc])])\n if (splitRuntime?.__preloadLocale) {\n await splitRuntime.__preloadLocale(loc)\n }\n } catch {\n // Silent fail for preload\n }\n },\n [loadMessages],\n )\n\n const ctx = useMemo(\n () => ({\n i18n,\n t: i18n.t.bind(i18n),\n d: i18n.d.bind(i18n),\n n: i18n.n.bind(i18n),\n format: i18n.format.bind(i18n),\n loadMessages: i18n.loadMessages.bind(i18n),\n getLocales: i18n.getLocales.bind(i18n),\n locale: currentLocale,\n setLocale: handleSetLocale,\n isLoading,\n loadedLocales,\n preloadLocale,\n }),\n [i18n, currentLocale, handleSetLocale, isLoading, loadedLocales, preloadLocale],\n )\n\n return <I18nContext.Provider value={ctx}>{children}</I18nContext.Provider>\n}\n","import { useContext } from 'react'\nimport { I18nContext } from '../context'\nimport type { I18nContextValue } from '../types'\n\n/**\n * Primary hook for accessing i18n functions.\n *\n * Returns locale, setLocale, isLoading, loadedLocales, preloadLocale,\n * and the underlying i18n instance with t(), d(), n() methods.\n *\n * @throws If used outside of `<I18nProvider>`\n */\nexport function useI18n(): I18nContextValue {\n const ctx = useContext(I18nContext)\n if (!ctx) {\n throw new Error(\n '[fluenti] useI18n() must be used within an <I18nProvider>. ' +\n 'Wrap your app with <I18nProvider> to provide i18n context.',\n )\n }\n return ctx\n}\n","import type { CompileTimeT } from '@fluenti/core'\n\nexport const t: CompileTimeT = ((..._args: unknown[]) => {\n throw new Error(\n \"[fluenti] `t` imported from '@fluenti/react' is a compile-time API. \" +\n 'Use it only with the Fluenti build transform inside a component or custom hook. ' +\n 'For runtime lookups, use useI18n().t(...).',\n )\n}) as CompileTimeT\n","import {\n memo,\n useContext,\n useMemo,\n type ReactElement,\n type ReactNode,\n} from 'react'\nimport { I18nContext } from '../context'\nimport { hashMessage, extractMessage, reconstruct } from './trans-core'\n\nexport interface TransProps {\n /** Source text with embedded components */\n children: ReactNode\n /** Override auto-generated hash ID */\n id?: string\n /** Message context used for identity and translator disambiguation */\n context?: string\n /** Context comment for translators */\n comment?: string\n /** Custom render wrapper */\n render?: (translation: ReactNode) => ReactNode\n /** @internal Pre-computed message ID from build plugin */\n __id?: string\n /** @internal Pre-computed ICU message from build plugin */\n __message?: string\n /** @internal Pre-computed component list from build plugin */\n __components?: ReactElement[]\n}\n\n/**\n * `<Trans>` component for rich-text translations containing nested React elements.\n *\n * @example\n * ```tsx\n * <Trans>Read the <a href=\"/docs\">documentation</a> for more info.</Trans>\n * ```\n */\nexport const Trans = memo(function Trans({\n children,\n id,\n context,\n comment,\n render,\n __id,\n __message,\n __components,\n}: TransProps) {\n const ctx = useContext(I18nContext)\n if (!ctx) {\n throw new Error('[fluenti] <Trans> must be used within an <I18nProvider>')\n }\n\n // Fast path: build plugin pre-computed message and components\n const hasPrecomputed = __message !== undefined\n\n const { message, components } = useMemo(\n () => hasPrecomputed\n ? { message: __message!, components: __components ?? [] }\n : extractMessage(children),\n [hasPrecomputed, __message, __components, children],\n )\n const messageId = useMemo(\n () => id ?? __id ?? hashMessage(message, context),\n [id, __id, message, context],\n )\n\n const translated = ctx.i18n.t(\n {\n id: messageId,\n message,\n ...(context !== undefined ? { context } : {}),\n ...(comment !== undefined ? { comment } : {}),\n },\n )\n\n const result = reconstruct(translated, components)\n return render ? render(result) : <>{result}</>\n})\n","import { memo, useContext, type ReactNode } from 'react'\nimport { hashMessage } from '@fluenti/core'\nimport { I18nContext } from '../context'\nimport { PLURAL_CATEGORIES, type PluralCategory } from './plural-core'\nimport { buildICUPluralMessage, renderRichTranslation, serializeRichForms } from './icu-rich'\n\nexport interface PluralProps {\n /** The count value */\n value: number\n /** Override the auto-generated synthetic ICU message id */\n id?: string\n /** Message context used for identity and translator disambiguation */\n context?: string\n /** Translator-facing note preserved in extraction catalogs */\n comment?: string\n /** Text for zero (if language supports) */\n zero?: ReactNode\n /** Singular form. `#` replaced with value */\n one?: ReactNode\n /** Dual form (Arabic, etc.) */\n two?: ReactNode\n /** Few form (Slavic languages, etc.) */\n few?: ReactNode\n /** Many form */\n many?: ReactNode\n /** Default plural form */\n other: ReactNode\n /** Offset from value before selecting form */\n offset?: number\n}\n\n/**\n * `<Plural>` — ICU plural handling as a component.\n *\n * @example\n * ```tsx\n * <Plural value={count} zero=\"No messages\" one=\"# message\" other=\"# messages\" />\n * ```\n */\nexport const Plural = memo(function Plural({\n value,\n id,\n context,\n comment,\n zero,\n one,\n two,\n few,\n many,\n other,\n offset,\n}: PluralProps) {\n const ctx = useContext(I18nContext)\n if (!ctx) {\n throw new Error('[fluenti] <Plural> must be used within an <I18nProvider>')\n }\n\n const forms: Record<PluralCategory, ReactNode | undefined> = {\n zero,\n one,\n two,\n few,\n many,\n other,\n }\n const { messages, components } = serializeRichForms(PLURAL_CATEGORIES, forms)\n const icuMessage = buildICUPluralMessage(\n {\n ...(messages.zero !== undefined && { zero: messages.zero }),\n ...(messages.one !== undefined && { one: messages.one }),\n ...(messages.two !== undefined && { two: messages.two }),\n ...(messages.few !== undefined && { few: messages.few }),\n ...(messages.many !== undefined && { many: messages.many }),\n other: messages.other ?? '',\n },\n offset,\n )\n\n const descriptor = {\n id: id ?? (context === undefined ? icuMessage : hashMessage(icuMessage, context)),\n message: icuMessage,\n ...(context !== undefined ? { context } : {}),\n ...(comment !== undefined ? { comment } : {}),\n }\n\n return <>{renderRichTranslation(descriptor, { count: value }, (desc, values) => ctx.i18n.t(desc, values), components)}</>\n})\n","import { useContext, type ReactNode } from 'react'\nimport { hashMessage } from '@fluenti/core'\nimport { I18nContext } from '../context'\nimport { buildICUSelectMessage, normalizeSelectForms, renderRichTranslation, serializeRichForms } from './icu-rich'\n\nexport interface SelectProps {\n /** The selector value */\n value: string\n /** Override the auto-generated synthetic ICU message id */\n id?: string\n /** Message context used for identity and translator disambiguation */\n context?: string\n /** Translator-facing note preserved in extraction catalogs */\n comment?: string\n /** Default case */\n other: ReactNode\n /** Type-safe named options. Takes precedence over direct case props. */\n options?: Record<string, ReactNode>\n /** Named cases — any string key maps to a ReactNode */\n [key: string]: ReactNode | Record<string, ReactNode> | undefined\n}\n\n/**\n * `<Select>` — ICU select for gender, role, or other categorical values.\n *\n * @example\n * ```tsx\n * <Select\n * value={gender}\n * male=\"He liked your post\"\n * female=\"She liked your post\"\n * other=\"They liked your post\"\n * />\n * ```\n */\nexport function Select(props: SelectProps) {\n const ctx = useContext(I18nContext)\n if (!ctx) {\n throw new Error('[fluenti] <Select> must be used within an <I18nProvider>')\n }\n\n const { value, id, context, comment, other, options, ...cases } = props\n const forms: Record<string, ReactNode | undefined> = options === undefined\n ? {\n ...Object.fromEntries(\n Object.entries(cases).filter(([key]) => !['value', 'id', 'context', 'comment', 'options', 'other'].includes(key)),\n ),\n other,\n }\n : {\n ...options,\n other,\n }\n\n const orderedKeys = [...Object.keys(forms).filter(key => key !== 'other'), 'other'] as const\n const { messages, components } = serializeRichForms(orderedKeys, forms)\n const normalized = normalizeSelectForms(\n Object.fromEntries(\n [...orderedKeys].map((key) => [key, messages[key] ?? '']),\n ),\n )\n const icuMessage = buildICUSelectMessage(normalized.forms)\n\n const descriptor = {\n id: id ?? (context === undefined ? icuMessage : hashMessage(icuMessage, context)),\n message: icuMessage,\n ...(context !== undefined ? { context } : {}),\n ...(comment !== undefined ? { comment } : {}),\n }\n\n return <>{renderRichTranslation(\n descriptor,\n { value: normalized.valueMap[value] ?? 'other' },\n (desc, values) => ctx.i18n.t(desc, values),\n components,\n )}</>\n}\n","import { useContext } from 'react'\nimport { I18nContext } from '../context'\n\nexport interface DateTimeProps {\n /** Date value to format */\n value: Date | number\n /** Named format style */\n style?: string\n}\n\n/**\n * `<DateTime>` — formatting component using Intl APIs.\n *\n * @example\n * ```tsx\n * <DateTime value={new Date()} style=\"long\" />\n * ```\n */\nexport function DateTime({ value, style }: DateTimeProps) {\n const ctx = useContext(I18nContext)\n if (!ctx) {\n throw new Error('[fluenti] <DateTime> must be used within an <I18nProvider>')\n }\n return <>{ctx.i18n.d(value, style)}</>\n}\n","import { useContext } from 'react'\nimport { I18nContext } from '../context'\n\nexport interface NumberProps {\n /** Number value to format */\n value: number\n /** Named format style */\n style?: string\n}\n\n/**\n * `<Number>` — number formatting component using Intl APIs.\n *\n * @example\n * ```tsx\n * <Number value={1234.56} style=\"currency\" />\n * ```\n */\nexport function NumberFormat({ value, style }: NumberProps) {\n const ctx = useContext(I18nContext)\n if (!ctx) {\n throw new Error('[fluenti] <Number> must be used within an <I18nProvider>')\n }\n return <>{ctx.i18n.n(value, style)}</>\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"index.js","names":[],"sources":["../src/context.ts","../src/provider.tsx","../src/hooks/useI18n.ts","../src/compile-time-t.ts","../src/components/Trans.tsx","../src/components/Plural.tsx","../src/components/Select.tsx","../src/components/DateTime.tsx","../src/components/Number.tsx"],"sourcesContent":["import { createContext } from 'react'\nimport type { I18nContextValue } from './types'\n\nexport const I18nContext = createContext<I18nContextValue | null>(null)\n","import { useState, useCallback, useEffect, useMemo, useRef } from 'react'\nimport { createFluent } from '@fluenti/core'\nimport type { Messages } from '@fluenti/core'\nimport { I18nContext } from './context'\nimport type { I18nProviderProps } from './types'\n\ninterface SplitRuntimeModule {\n __switchLocale?: (locale: string) => Promise<void>\n __preloadLocale?: (locale: string) => Promise<void>\n}\n\nconst SPLIT_RUNTIME_KEY = Symbol.for('fluenti.runtime.react')\n\nfunction getSplitRuntimeModule(): SplitRuntimeModule | null {\n const runtime = (globalThis as Record<PropertyKey, unknown>)[SPLIT_RUNTIME_KEY]\n return typeof runtime === 'object' && runtime !== null\n ? runtime as SplitRuntimeModule\n : null\n}\n\nexport function I18nProvider({\n locale,\n fallbackLocale,\n messages,\n loadMessages,\n fallbackChain,\n dateFormats,\n numberFormats,\n missing,\n children,\n}: I18nProviderProps) {\n const [currentLocale, setCurrentLocale] = useState(locale)\n const [isLoading, setIsLoading] = useState(false)\n const [loadedMessages, setLoadedMessages] = useState<Record<string, Messages>>(\n messages ?? {},\n )\n const [loadedLocales, setLoadedLocales] = useState<string[]>(\n messages ? Object.keys(messages) : [],\n )\n\n // Use ref to avoid stale closures in callbacks\n const loadedMessagesRef = useRef(loadedMessages)\n loadedMessagesRef.current = loadedMessages\n\n // Guard against out-of-order async locale loads (race condition protection)\n const localeRequestRef = useRef(0)\n\n const i18n = useMemo(() => {\n const config: Parameters<typeof createFluent>[0] = {\n locale: currentLocale,\n messages: loadedMessages,\n }\n if (fallbackLocale !== undefined) config.fallbackLocale = fallbackLocale\n if (fallbackChain !== undefined) config.fallbackChain = fallbackChain\n if (dateFormats !== undefined) config.dateFormats = dateFormats\n if (numberFormats !== undefined) config.numberFormats = numberFormats\n if (missing !== undefined) config.missing = missing\n return createFluent(config)\n }, [currentLocale, loadedMessages, fallbackLocale, fallbackChain, dateFormats, numberFormats, missing])\n\n // Sync external locale prop changes\n useEffect(() => {\n if (locale !== currentLocale) {\n void handleSetLocale(locale)\n }\n // Intentionally only depend on `locale` — we want to sync when the\n // external prop changes, not when internal state (`currentLocale`,\n // `handleSetLocale`) updates, which would cause infinite re-renders.\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [locale])\n\n const handleSetLocale = useCallback(\n async (newLocale: string) => {\n const requestId = ++localeRequestRef.current\n\n if (loadedMessagesRef.current[newLocale] && !loadMessages) {\n setCurrentLocale(newLocale)\n return\n }\n\n const splitRuntime = loadMessages ? getSplitRuntimeModule() : null\n\n if (loadedMessagesRef.current[newLocale]) {\n if (splitRuntime?.__switchLocale) {\n await splitRuntime.__switchLocale(newLocale)\n }\n setCurrentLocale(newLocale)\n return\n }\n\n if (!loadMessages) {\n console.warn(\n `[fluenti] No messages for locale \"${newLocale}\" and no loadMessages function provided`,\n )\n return\n }\n\n setIsLoading(true)\n try {\n const msgs = await loadMessages(newLocale)\n\n // A newer request has superseded this one — discard stale result\n if (requestId !== localeRequestRef.current) return\n\n const resolved: Messages =\n typeof msgs === 'object' && msgs !== null && 'default' in msgs\n ? (msgs as { default: Messages }).default\n : (msgs as Messages)\n setLoadedMessages((prev) => ({ ...prev, [newLocale]: resolved }))\n setLoadedLocales((prev) => [...new Set([...prev, newLocale])])\n if (splitRuntime?.__switchLocale) {\n await splitRuntime.__switchLocale(newLocale)\n }\n setCurrentLocale(newLocale)\n } catch (err) {\n // Only log if this request is still the latest\n if (requestId === localeRequestRef.current) {\n console.error(`[fluenti] Failed to load locale \"${newLocale}\"`, err)\n }\n } finally {\n if (requestId === localeRequestRef.current) {\n setIsLoading(false)\n }\n }\n },\n [loadMessages],\n )\n\n const preloadLocale = useCallback(\n async (loc: string) => {\n const splitRuntime = getSplitRuntimeModule()\n if (loadedMessagesRef.current[loc] || !loadMessages) return\n try {\n const msgs = await loadMessages(loc)\n const resolved: Messages =\n typeof msgs === 'object' && msgs !== null && 'default' in msgs\n ? (msgs as { default: Messages }).default\n : (msgs as Messages)\n setLoadedMessages((prev) => ({ ...prev, [loc]: resolved }))\n setLoadedLocales((prev) => [...new Set([...prev, loc])])\n if (splitRuntime?.__preloadLocale) {\n await splitRuntime.__preloadLocale(loc)\n }\n } catch {\n // Silent fail for preload\n }\n },\n [loadMessages],\n )\n\n const ctx = useMemo(\n () => ({\n i18n,\n t: i18n.t.bind(i18n),\n d: i18n.d.bind(i18n),\n n: i18n.n.bind(i18n),\n format: i18n.format.bind(i18n),\n loadMessages: i18n.loadMessages.bind(i18n),\n getLocales: i18n.getLocales.bind(i18n),\n locale: currentLocale,\n setLocale: handleSetLocale,\n isLoading,\n loadedLocales,\n preloadLocale,\n }),\n [i18n, currentLocale, handleSetLocale, isLoading, loadedLocales, preloadLocale],\n )\n\n return <I18nContext.Provider value={ctx}>{children}</I18nContext.Provider>\n}\n","import { useContext } from 'react'\nimport { I18nContext } from '../context'\nimport type { I18nContextValue } from '../types'\n\n/**\n * Primary hook for accessing i18n functions.\n *\n * Returns locale, setLocale, isLoading, loadedLocales, preloadLocale,\n * and the underlying i18n instance with t(), d(), n() methods.\n *\n * @throws If used outside of `<I18nProvider>`\n */\nexport function useI18n(): I18nContextValue {\n const ctx = useContext(I18nContext)\n if (!ctx) {\n throw new Error(\n '[fluenti] useI18n() must be used within an <I18nProvider>. ' +\n 'Wrap your app with <I18nProvider> to provide i18n context.',\n )\n }\n return ctx\n}\n","import type { CompileTimeT } from '@fluenti/core'\n\nexport const t: CompileTimeT = ((..._args: unknown[]) => {\n throw new Error(\n \"[fluenti] `t` imported from '@fluenti/react' is a compile-time API. \" +\n 'Use it only with the Fluenti build transform inside a component or custom hook. ' +\n 'For runtime lookups, use useI18n().t(...).',\n )\n}) as CompileTimeT\n","import {\n memo,\n useContext,\n useMemo,\n type ReactElement,\n type ReactNode,\n} from 'react'\nimport { I18nContext } from '../context'\nimport { hashMessage, extractMessage, reconstruct } from './trans-core'\n\nexport interface TransProps {\n /** Source text with embedded components */\n children: ReactNode\n /** Override auto-generated hash ID */\n id?: string\n /** Message context used for identity and translator disambiguation */\n context?: string\n /** Context comment for translators */\n comment?: string\n /** Custom render wrapper */\n render?: (translation: ReactNode) => ReactNode\n /** @internal Pre-computed message ID from build plugin */\n __id?: string\n /** @internal Pre-computed ICU message from build plugin */\n __message?: string\n /** @internal Pre-computed component list from build plugin */\n __components?: ReactElement[]\n}\n\n/**\n * `<Trans>` component for rich-text translations containing nested React elements.\n *\n * @example\n * ```tsx\n * <Trans>Read the <a href=\"/docs\">documentation</a> for more info.</Trans>\n * ```\n */\nexport const Trans = memo(function Trans({\n children,\n id,\n context,\n comment,\n render,\n __id,\n __message,\n __components,\n}: TransProps) {\n const ctx = useContext(I18nContext)\n if (!ctx) {\n throw new Error('[fluenti] <Trans> must be used within an <I18nProvider>')\n }\n\n // Fast path: build plugin pre-computed message and components\n const hasPrecomputed = __message !== undefined\n\n const { message, components } = useMemo(\n () => hasPrecomputed\n ? { message: __message!, components: __components ?? [] }\n : extractMessage(children),\n [hasPrecomputed, __message, __components, children],\n )\n const messageId = useMemo(\n () => id ?? __id ?? hashMessage(message, context),\n [id, __id, message, context],\n )\n\n const translated = ctx.i18n.t(\n {\n id: messageId,\n message,\n ...(context !== undefined ? { context } : {}),\n ...(comment !== undefined ? { comment } : {}),\n },\n )\n\n const result = reconstruct(translated, components)\n return render ? render(result) : <>{result}</>\n})\n","import { memo, useContext, type ReactNode } from 'react'\nimport { hashMessage } from '@fluenti/core'\nimport { I18nContext } from '../context'\nimport { PLURAL_CATEGORIES, type PluralCategory } from './plural-core'\nimport { buildICUPluralMessage, renderRichTranslation, serializeRichForms } from './icu-rich'\n\nexport interface PluralProps {\n /** The count value */\n value: number\n /** Override the auto-generated synthetic ICU message id */\n id?: string\n /** Message context used for identity and translator disambiguation */\n context?: string\n /** Translator-facing note preserved in extraction catalogs */\n comment?: string\n /** Text for zero (if language supports) */\n zero?: ReactNode\n /** Singular form. `#` replaced with value */\n one?: ReactNode\n /** Dual form (Arabic, etc.) */\n two?: ReactNode\n /** Few form (Slavic languages, etc.) */\n few?: ReactNode\n /** Many form */\n many?: ReactNode\n /** Default plural form */\n other: ReactNode\n /** Offset from value before selecting form */\n offset?: number\n}\n\n/**\n * `<Plural>` — ICU plural handling as a component.\n *\n * @example\n * ```tsx\n * <Plural value={count} zero=\"No messages\" one=\"# message\" other=\"# messages\" />\n * ```\n */\nexport const Plural = memo(function Plural({\n value,\n id,\n context,\n comment,\n zero,\n one,\n two,\n few,\n many,\n other,\n offset,\n}: PluralProps) {\n const ctx = useContext(I18nContext)\n if (!ctx) {\n throw new Error('[fluenti] <Plural> must be used within an <I18nProvider>')\n }\n\n const forms: Record<PluralCategory, ReactNode | undefined> = {\n zero,\n one,\n two,\n few,\n many,\n other,\n }\n const { messages, components } = serializeRichForms(PLURAL_CATEGORIES, forms)\n const icuMessage = buildICUPluralMessage(\n {\n ...(messages.zero !== undefined && { zero: messages.zero }),\n ...(messages.one !== undefined && { one: messages.one }),\n ...(messages.two !== undefined && { two: messages.two }),\n ...(messages.few !== undefined && { few: messages.few }),\n ...(messages.many !== undefined && { many: messages.many }),\n other: messages.other ?? '',\n },\n offset,\n )\n\n const descriptor = {\n id: id ?? (context === undefined ? icuMessage : hashMessage(icuMessage, context)),\n message: icuMessage,\n ...(context !== undefined ? { context } : {}),\n ...(comment !== undefined ? { comment } : {}),\n }\n\n return <>{renderRichTranslation(descriptor, { count: value }, (desc, values) => ctx.i18n.t(desc, values), components)}</>\n})\n","import { memo, useContext, type ReactNode } from 'react'\nimport { hashMessage } from '@fluenti/core'\nimport { I18nContext } from '../context'\nimport { buildICUSelectMessage, normalizeSelectForms, renderRichTranslation, serializeRichForms } from './icu-rich'\n\nexport interface SelectProps {\n /** The selector value */\n value: string\n /** Override the auto-generated synthetic ICU message id */\n id?: string\n /** Message context used for identity and translator disambiguation */\n context?: string\n /** Translator-facing note preserved in extraction catalogs */\n comment?: string\n /** Default case */\n other: ReactNode\n /** Type-safe named options. Takes precedence over direct case props. */\n options?: Record<string, ReactNode>\n /** Named cases — any string key maps to a ReactNode */\n [key: string]: ReactNode | Record<string, ReactNode> | undefined\n}\n\n/**\n * `<Select>` — ICU select for gender, role, or other categorical values.\n *\n * @example\n * ```tsx\n * <Select\n * value={gender}\n * male=\"He liked your post\"\n * female=\"She liked your post\"\n * other=\"They liked your post\"\n * />\n * ```\n */\nexport const Select = memo(function Select(props: SelectProps) {\n const ctx = useContext(I18nContext)\n if (!ctx) {\n throw new Error('[fluenti] <Select> must be used within an <I18nProvider>')\n }\n\n const { value, id, context, comment, other, options, ...cases } = props\n const forms: Record<string, ReactNode | undefined> = options === undefined\n ? {\n ...Object.fromEntries(\n Object.entries(cases).filter(([key]) => !['value', 'id', 'context', 'comment', 'options', 'other'].includes(key)),\n ),\n other,\n }\n : {\n ...options,\n other,\n }\n\n const orderedKeys = [...Object.keys(forms).filter(key => key !== 'other'), 'other'] as const\n const { messages, components } = serializeRichForms(orderedKeys, forms)\n const normalized = normalizeSelectForms(\n Object.fromEntries(\n [...orderedKeys].map((key) => [key, messages[key] ?? '']),\n ),\n )\n const icuMessage = buildICUSelectMessage(normalized.forms)\n\n const descriptor = {\n id: id ?? (context === undefined ? icuMessage : hashMessage(icuMessage, context)),\n message: icuMessage,\n ...(context !== undefined ? { context } : {}),\n ...(comment !== undefined ? { comment } : {}),\n }\n\n return <>{renderRichTranslation(\n descriptor,\n { value: normalized.valueMap[value] ?? 'other' },\n (desc, values) => ctx.i18n.t(desc, values),\n components,\n )}</>\n})\n","import { memo, useContext } from 'react'\nimport { I18nContext } from '../context'\n\nexport interface DateTimeProps {\n /** Date value to format */\n value: Date | number\n /** Named format style */\n style?: string\n}\n\n/**\n * `<DateTime>` — formatting component using Intl APIs.\n *\n * @example\n * ```tsx\n * <DateTime value={new Date()} style=\"long\" />\n * ```\n */\nexport const DateTime = memo(function DateTime({ value, style }: DateTimeProps) {\n const ctx = useContext(I18nContext)\n if (!ctx) {\n throw new Error('[fluenti] <DateTime> must be used within an <I18nProvider>')\n }\n return <>{ctx.i18n.d(value, style)}</>\n})\n","import { memo, useContext } from 'react'\nimport { I18nContext } from '../context'\n\nexport interface NumberProps {\n /** Number value to format */\n value: number\n /** Named format style */\n style?: string\n}\n\n/**\n * `<Number>` — number formatting component using Intl APIs.\n *\n * @example\n * ```tsx\n * <Number value={1234.56} style=\"currency\" />\n * ```\n */\nexport const NumberFormat = memo(function NumberFormat({ value, style }: NumberProps) {\n const ctx = useContext(I18nContext)\n if (!ctx) {\n throw new Error('[fluenti] <Number> must be used within an <I18nProvider>')\n }\n return <>{ctx.i18n.n(value, style)}</>\n})\n"],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fluenti/react",
3
- "version": "0.1.1",
3
+ "version": "0.1.3",
4
4
  "type": "module",
5
5
  "description": "React bindings for Fluenti — I18nProvider, useI18n, Trans/Plural/Select components",
6
6
  "homepage": "https://fluenti.dev",
@@ -58,7 +58,7 @@
58
58
  "react": ">=18.0.0"
59
59
  },
60
60
  "dependencies": {
61
- "@fluenti/core": "0.1.1"
61
+ "@fluenti/core": "0.1.3"
62
62
  },
63
63
  "devDependencies": {
64
64
  "typescript": "^5.9",
@@ -1,2 +0,0 @@
1
- export {};
2
- //# sourceMappingURL=DateTime.test.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"DateTime.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/DateTime.test.tsx"],"names":[],"mappings":""}
@@ -1,2 +0,0 @@
1
- export {};
2
- //# sourceMappingURL=Number.test.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"Number.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/Number.test.tsx"],"names":[],"mappings":""}
@@ -1,2 +0,0 @@
1
- export {};
2
- //# sourceMappingURL=Plural.test.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"Plural.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/Plural.test.tsx"],"names":[],"mappings":""}
@@ -1,2 +0,0 @@
1
- export {};
2
- //# sourceMappingURL=Select.test.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"Select.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/Select.test.tsx"],"names":[],"mappings":""}
@@ -1,2 +0,0 @@
1
- export {};
2
- //# sourceMappingURL=Trans.test.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"Trans.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/Trans.test.tsx"],"names":[],"mappings":""}
@@ -1,2 +0,0 @@
1
- export {};
2
- //# sourceMappingURL=locale-switch.test.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"locale-switch.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/locale-switch.test.tsx"],"names":[],"mappings":""}
@@ -1,2 +0,0 @@
1
- export {};
2
- //# sourceMappingURL=plural-core.test.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"plural-core.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/plural-core.test.ts"],"names":[],"mappings":""}
@@ -1,2 +0,0 @@
1
- export {};
2
- //# sourceMappingURL=provider.test.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"provider.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/provider.test.tsx"],"names":[],"mappings":""}
@@ -1,2 +0,0 @@
1
- export {};
2
- //# sourceMappingURL=server.test.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"server.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/server.test.ts"],"names":[],"mappings":""}
@@ -1,2 +0,0 @@
1
- export {};
2
- //# sourceMappingURL=trans-core.test.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"trans-core.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/trans-core.test.ts"],"names":[],"mappings":""}