@fluixi/core 1.0.0-alpha.83 → 1.0.0-alpha.84

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (177) hide show
  1. package/dist/cdn/core.global.js +2 -1
  2. package/dist/cli/generate.cjs +4117 -292
  3. package/dist/cli/generate.mjs +4122 -292
  4. package/dist/cli/index.cjs +4117 -292
  5. package/dist/cli/index.mjs +4122 -292
  6. package/dist/cli/run.cjs +63 -1
  7. package/dist/cli/run.mjs +39 -1
  8. package/dist/src/cdn/chunk-VNLCQBFQ.mjs +747 -0
  9. package/dist/src/cdn/core.cjs +1279 -1
  10. package/dist/src/cdn/core.d.ts +3 -3
  11. package/dist/src/cdn/core.js +3 -3
  12. package/dist/src/cdn/core.mjs +642 -1
  13. package/dist/src/cdn/router-WMN2AA7E.mjs +66 -0
  14. package/dist/src/index.cjs +1201 -1
  15. package/dist/src/index.d.ts.map +1 -1
  16. package/dist/src/index.js +1 -11
  17. package/dist/src/index.mjs +1313 -1
  18. package/dist/src/jsx-dev-runtime.cjs +26 -1
  19. package/dist/src/jsx-dev-runtime.mjs +24 -1
  20. package/dist/src/jsx-runtime.cjs +26 -1
  21. package/dist/src/jsx-runtime.js +0 -9
  22. package/dist/src/jsx-runtime.mjs +24 -1
  23. package/dist/src/lib/client/chunk-2C2KDDQV.mjs +133 -0
  24. package/dist/src/lib/client/index.cjs +870 -1
  25. package/dist/src/lib/client/index.d.ts +17 -6
  26. package/dist/src/lib/client/index.d.ts.map +1 -1
  27. package/dist/src/lib/client/index.js +26 -19
  28. package/dist/src/lib/client/index.mjs +222 -1
  29. package/dist/src/lib/client/router-X526HSWQ.mjs +548 -0
  30. package/dist/src/lib/context/context.cjs +118 -1
  31. package/dist/src/lib/context/context.d.ts +19 -37
  32. package/dist/src/lib/context/context.d.ts.map +1 -1
  33. package/dist/src/lib/context/context.js +8 -45
  34. package/dist/src/lib/context/context.mjs +99 -1
  35. package/dist/src/lib/context/index.cjs +120 -1
  36. package/dist/src/lib/context/index.mjs +99 -1
  37. package/dist/src/lib/control-flow.cjs +35 -1
  38. package/dist/src/lib/control-flow.mjs +25 -1
  39. package/dist/src/lib/core.cjs +1200 -1
  40. package/dist/src/lib/core.d.ts +0 -2
  41. package/dist/src/lib/core.d.ts.map +1 -1
  42. package/dist/src/lib/core.js +14 -48
  43. package/dist/src/lib/core.mjs +1313 -1
  44. package/dist/src/lib/env/index.cjs +60 -1
  45. package/dist/src/lib/env/index.d.ts +5 -5
  46. package/dist/src/lib/env/index.js +5 -5
  47. package/dist/src/lib/env/index.mjs +39 -1
  48. package/dist/src/lib/i18n/index.cjs +108 -1
  49. package/dist/src/lib/i18n/index.d.ts +31 -10
  50. package/dist/src/lib/i18n/index.d.ts.map +1 -1
  51. package/dist/src/lib/i18n/index.js +31 -10
  52. package/dist/src/lib/i18n/index.mjs +88 -1
  53. package/dist/src/lib/index.cjs +633 -1
  54. package/dist/src/lib/index.d.ts +0 -2
  55. package/dist/src/lib/index.d.ts.map +1 -1
  56. package/dist/src/lib/index.js +5 -11
  57. package/dist/src/lib/index.mjs +721 -1
  58. package/dist/src/lib/isomorphic.cjs +85 -1
  59. package/dist/src/lib/isomorphic.d.ts +41 -8
  60. package/dist/src/lib/isomorphic.d.ts.map +1 -1
  61. package/dist/src/lib/isomorphic.js +38 -5
  62. package/dist/src/lib/isomorphic.mjs +64 -1
  63. package/dist/src/lib/jsx-runtime/index.cjs +21 -1
  64. package/dist/src/lib/jsx-runtime/index.d.ts +1 -1
  65. package/dist/src/lib/jsx-runtime/index.js +1 -11
  66. package/dist/src/lib/jsx-runtime/index.mjs +4 -1
  67. package/dist/src/lib/jsx-runtime/jsx-dev-runtime.cjs +21 -1
  68. package/dist/src/lib/jsx-runtime/jsx-dev-runtime.mjs +4 -1
  69. package/dist/src/lib/plugins/fluixi-routes-plugin.cjs +302 -8
  70. package/dist/src/lib/plugins/fluixi-routes-plugin.d.ts +15 -1
  71. package/dist/src/lib/plugins/fluixi-routes-plugin.d.ts.map +1 -1
  72. package/dist/src/lib/plugins/fluixi-routes-plugin.js +19 -5
  73. package/dist/src/lib/plugins/fluixi-routes-plugin.mjs +271 -8
  74. package/dist/src/lib/plugins/index.cjs +311 -8
  75. package/dist/src/lib/plugins/index.mjs +279 -8
  76. package/dist/src/lib/plugins/route-codegen.cjs +73 -8
  77. package/dist/src/lib/plugins/route-codegen.d.ts +0 -1
  78. package/dist/src/lib/plugins/route-codegen.d.ts.map +1 -1
  79. package/dist/src/lib/plugins/route-codegen.js +4 -5
  80. package/dist/src/lib/plugins/route-codegen.mjs +52 -8
  81. package/dist/src/lib/plugins/route-scanner.cjs +189 -1
  82. package/dist/src/lib/plugins/route-scanner.d.ts +1 -2
  83. package/dist/src/lib/plugins/route-scanner.d.ts.map +1 -1
  84. package/dist/src/lib/plugins/route-scanner.js +7 -8
  85. package/dist/src/lib/plugins/route-scanner.mjs +158 -1
  86. package/dist/src/lib/plugins/vite.cjs +27 -1
  87. package/dist/src/lib/plugins/vite.mjs +6 -1
  88. package/dist/src/lib/render/await.cjs +38 -1
  89. package/dist/src/lib/render/await.d.ts +18 -0
  90. package/dist/src/lib/render/await.d.ts.map +1 -1
  91. package/dist/src/lib/render/await.js +20 -2
  92. package/dist/src/lib/render/await.mjs +17 -1
  93. package/dist/src/lib/render/component.cjs +221 -1
  94. package/dist/src/lib/render/component.d.ts +3 -44
  95. package/dist/src/lib/render/component.d.ts.map +1 -1
  96. package/dist/src/lib/render/component.js +23 -55
  97. package/dist/src/lib/render/component.mjs +214 -1
  98. package/dist/src/lib/render/deferred.cjs +175 -1
  99. package/dist/src/lib/render/deferred.js +5 -5
  100. package/dist/src/lib/render/deferred.mjs +158 -1
  101. package/dist/src/lib/render/index.cjs +573 -1
  102. package/dist/src/lib/render/index.d.ts +3 -17
  103. package/dist/src/lib/render/index.d.ts.map +1 -1
  104. package/dist/src/lib/render/index.js +8 -22
  105. package/dist/src/lib/render/index.mjs +590 -1
  106. package/dist/src/lib/render/lazy.cjs +67 -1
  107. package/dist/src/lib/render/lazy.d.ts +22 -1
  108. package/dist/src/lib/render/lazy.d.ts.map +1 -1
  109. package/dist/src/lib/render/lazy.js +26 -5
  110. package/dist/src/lib/render/lazy.mjs +50 -1
  111. package/dist/src/lib/render/suspense.cjs +141 -1
  112. package/dist/src/lib/render/suspense.d.ts +40 -0
  113. package/dist/src/lib/render/suspense.d.ts.map +1 -1
  114. package/dist/src/lib/render/suspense.js +46 -6
  115. package/dist/src/lib/render/suspense.mjs +136 -1
  116. package/dist/src/lib/render/versions.cjs +35 -1
  117. package/dist/src/lib/render/versions.js +6 -6
  118. package/dist/src/lib/render/versions.mjs +14 -1
  119. package/dist/src/lib/router/data.cjs +230 -1
  120. package/dist/src/lib/router/data.d.ts +1 -13
  121. package/dist/src/lib/router/data.d.ts.map +1 -1
  122. package/dist/src/lib/router/data.js +0 -12
  123. package/dist/src/lib/router/data.mjs +214 -1
  124. package/dist/src/lib/router/index.cjs +627 -1
  125. package/dist/src/lib/router/index.d.ts +62 -10
  126. package/dist/src/lib/router/index.d.ts.map +1 -1
  127. package/dist/src/lib/router/index.js +85 -33
  128. package/dist/src/lib/router/index.mjs +639 -1
  129. package/dist/src/lib/server/hydration.cjs +169 -1
  130. package/dist/src/lib/server/hydration.d.ts +15 -55
  131. package/dist/src/lib/server/hydration.d.ts.map +1 -1
  132. package/dist/src/lib/server/hydration.js +23 -62
  133. package/dist/src/lib/server/hydration.mjs +148 -1
  134. package/dist/src/lib/server/index.cjs +401 -11
  135. package/dist/src/lib/server/index.d.ts +30 -6
  136. package/dist/src/lib/server/index.d.ts.map +1 -1
  137. package/dist/src/lib/server/index.js +34 -11
  138. package/dist/src/lib/server/index.mjs +379 -11
  139. package/dist/src/lib/server/reactive.cjs +197 -1
  140. package/dist/src/lib/server/reactive.d.ts +18 -77
  141. package/dist/src/lib/server/reactive.d.ts.map +1 -1
  142. package/dist/src/lib/server/reactive.js +19 -78
  143. package/dist/src/lib/server/reactive.mjs +176 -1
  144. package/dist/src/lib/theme/index.cjs +110 -1
  145. package/dist/src/lib/theme/index.d.ts +19 -4
  146. package/dist/src/lib/theme/index.d.ts.map +1 -1
  147. package/dist/src/lib/theme/index.js +17 -2
  148. package/dist/src/lib/theme/index.mjs +89 -1
  149. package/dist/src/lib/utils/index.cjs +209 -1
  150. package/dist/src/lib/utils/index.d.ts +0 -93
  151. package/dist/src/lib/utils/index.d.ts.map +1 -1
  152. package/dist/src/lib/utils/index.js +0 -93
  153. package/dist/src/lib/utils/index.mjs +188 -1
  154. package/dist/src/routes.cjs +37 -1
  155. package/dist/src/routes.d.ts +1 -1
  156. package/dist/src/routes.js +2 -2
  157. package/dist/src/routes.mjs +17 -1
  158. package/dist/src/server.cjs +400 -11
  159. package/dist/src/server.d.ts +0 -1
  160. package/dist/src/server.d.ts.map +1 -1
  161. package/dist/src/server.js +0 -1
  162. package/dist/src/server.mjs +377 -11
  163. package/dist/src/utils.cjs +21 -1
  164. package/dist/src/utils.d.ts +1 -1
  165. package/dist/src/utils.js +1 -1
  166. package/dist/src/utils.mjs +4 -1
  167. package/dist/src/version.generated.cjs +26 -1
  168. package/dist/src/version.generated.d.ts +1 -1
  169. package/dist/src/version.generated.js +2 -2
  170. package/dist/src/version.generated.mjs +5 -1
  171. package/dist/tsconfig.lib.tsbuildinfo +1 -1
  172. package/package.json +17 -16
  173. package/src/index.ts +2 -14
  174. package/dist/src/cdn/chunk-55BT3H6E.mjs +0 -1
  175. package/dist/src/cdn/router-5JJZBK4E.mjs +0 -1
  176. package/dist/src/lib/client/chunk-SM4WHBOP.mjs +0 -1
  177. package/dist/src/lib/client/router-IBD4WPQT.mjs +0 -1
@@ -1 +1,60 @@
1
- "use strict";var r=Object.defineProperty;var c=Object.getOwnPropertyDescriptor;var a=Object.getOwnPropertyNames;var g=Object.prototype.hasOwnProperty;var s=(n,e)=>{for(var t in e)r(n,t,{get:e[t],enumerable:!0})},m=(n,e,t,i)=>{if(e&&typeof e=="object"||typeof e=="function")for(let o of a(e))!g.call(n,o)&&o!==t&&r(n,o,{get:()=>e[o],enumerable:!(i=c(e,o))||i.enumerable});return n};var p=n=>m(r({},"__esModule",{value:!0}),n);var w={};s(w,{clientOnly:()=>S,createMemoryStorage:()=>f,env:()=>y,isClient:()=>u,isServer:()=>l.isServer,storage:()=>T});module.exports=p(w);var l=require("@fluixi/dom"),d=require("@fluixi/dom");function u(){return!(0,d.isServer)()}function f(){let n=new Map;return{getItem:e=>n.has(e)?n.get(e):null,setItem:(e,t)=>{n.set(e,String(t))},removeItem:e=>{n.delete(e)},clear:()=>n.clear(),key:e=>Array.from(n.keys())[e]??null,get length(){return n.size}}}var T=typeof localStorage<"u"?localStorage:f(),y={get window(){return typeof window<"u"?window:void 0},get document(){return typeof document<"u"?document:void 0}};function S(n,e){return u()?n():e}
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+
20
+ // src/lib/env/index.ts
21
+ var index_exports = {};
22
+ __export(index_exports, {
23
+ clientOnly: () => clientOnly,
24
+ createMemoryStorage: () => createMemoryStorage,
25
+ env: () => env,
26
+ isClient: () => isClient,
27
+ isServer: () => import_dom.isServer,
28
+ storage: () => storage
29
+ });
30
+ module.exports = __toCommonJS(index_exports);
31
+ var import_dom = require("@fluixi/dom");
32
+ var import_dom2 = require("@fluixi/dom");
33
+ function isClient() {
34
+ return !(0, import_dom2.isServer)();
35
+ }
36
+ function createMemoryStorage() {
37
+ const mem = /* @__PURE__ */ new Map();
38
+ return {
39
+ getItem: (k) => mem.has(k) ? mem.get(k) : null,
40
+ setItem: (k, v) => void mem.set(k, String(v)),
41
+ removeItem: (k) => void mem.delete(k),
42
+ clear: () => mem.clear(),
43
+ key: (i) => Array.from(mem.keys())[i] ?? null,
44
+ get length() {
45
+ return mem.size;
46
+ }
47
+ };
48
+ }
49
+ var storage = typeof localStorage !== "undefined" ? localStorage : createMemoryStorage();
50
+ var env = {
51
+ get window() {
52
+ return typeof window !== "undefined" ? window : void 0;
53
+ },
54
+ get document() {
55
+ return typeof document !== "undefined" ? document : void 0;
56
+ }
57
+ };
58
+ function clientOnly(fn, fallback) {
59
+ return isClient() ? fn() : fallback;
60
+ }
@@ -1,8 +1,8 @@
1
1
  /**
2
- * Universal environment utilities the same imports work on the server and the
2
+ * Universal environment utilities, the same imports work on the server and the
3
3
  * client, so app code never reaches for raw globals (`localStorage`, `window`,
4
4
  * `document`) that don't exist under SSR and crash at module-eval time. This
5
- * replaces hand-rolled `globalThis.localStorage = …` shims and scattered
5
+ * replaces hand-rolled `globalThis.localStorage = ...` shims and scattered
6
6
  * `typeof window === 'undefined'` guards.
7
7
  */
8
8
  export { isServer } from '@fluixi/dom';
@@ -12,7 +12,7 @@ export declare function isClient(): boolean;
12
12
  export declare function createMemoryStorage(): Storage;
13
13
  /**
14
14
  * Universal key/value storage with the exact `localStorage` API. On the client it
15
- * IS `localStorage`; on the server (no DOM) it is an ephemeral in-memory store, so
15
+ * is `localStorage`; on the server (no DOM) it is an ephemeral in-memory store, so
16
16
  * a module that reads `storage.getItem(...)` at import time never crashes under SSR.
17
17
  * Server reads/writes do not persist across requests (a later pass can back them with
18
18
  * the request cookie for true per-user server state).
@@ -21,8 +21,8 @@ export declare const storage: Storage;
21
21
  /**
22
22
  * Lazy, typed accessors for the browser globals. They return the real object on the
23
23
  * client and `undefined` on the server, so `env.window?.matchMedia(...)` is safe and
24
- * typed everywhere. Deliberately NOT faked on the server: a stub `location`/`innerWidth`
25
- * would return wrong values and cause hydration mismatches guard with `?.` instead.
24
+ * typed everywhere. Deliberately not faked on the server: a stub `location`/`innerWidth`
25
+ * would return wrong values and cause hydration mismatches: guard with `?.` instead.
26
26
  */
27
27
  export declare const env: {
28
28
  readonly window: (Window & typeof globalThis) | undefined;
@@ -1,8 +1,8 @@
1
1
  /**
2
- * Universal environment utilities the same imports work on the server and the
2
+ * Universal environment utilities, the same imports work on the server and the
3
3
  * client, so app code never reaches for raw globals (`localStorage`, `window`,
4
4
  * `document`) that don't exist under SSR and crash at module-eval time. This
5
- * replaces hand-rolled `globalThis.localStorage = …` shims and scattered
5
+ * replaces hand-rolled `globalThis.localStorage = ...` shims and scattered
6
6
  * `typeof window === 'undefined'` guards.
7
7
  */
8
8
  // One answer for the whole framework, from the renderer that decides it. The constant
@@ -30,7 +30,7 @@ export function createMemoryStorage() {
30
30
  }
31
31
  /**
32
32
  * Universal key/value storage with the exact `localStorage` API. On the client it
33
- * IS `localStorage`; on the server (no DOM) it is an ephemeral in-memory store, so
33
+ * is `localStorage`; on the server (no DOM) it is an ephemeral in-memory store, so
34
34
  * a module that reads `storage.getItem(...)` at import time never crashes under SSR.
35
35
  * Server reads/writes do not persist across requests (a later pass can back them with
36
36
  * the request cookie for true per-user server state).
@@ -39,8 +39,8 @@ export const storage = typeof localStorage !== 'undefined' ? localStorage : crea
39
39
  /**
40
40
  * Lazy, typed accessors for the browser globals. They return the real object on the
41
41
  * client and `undefined` on the server, so `env.window?.matchMedia(...)` is safe and
42
- * typed everywhere. Deliberately NOT faked on the server: a stub `location`/`innerWidth`
43
- * would return wrong values and cause hydration mismatches guard with `?.` instead.
42
+ * typed everywhere. Deliberately not faked on the server: a stub `location`/`innerWidth`
43
+ * would return wrong values and cause hydration mismatches: guard with `?.` instead.
44
44
  */
45
45
  export const env = {
46
46
  get window() {
@@ -1 +1,39 @@
1
- import{isServer as g}from"@fluixi/dom";import{isServer as o}from"@fluixi/dom";function r(){return!o()}function i(){let n=new Map;return{getItem:e=>n.has(e)?n.get(e):null,setItem:(e,t)=>{n.set(e,String(t))},removeItem:e=>{n.delete(e)},clear:()=>n.clear(),key:e=>Array.from(n.keys())[e]??null,get length(){return n.size}}}var u=typeof localStorage<"u"?localStorage:i(),f={get window(){return typeof window<"u"?window:void 0},get document(){return typeof document<"u"?document:void 0}};function l(n,e){return r()?n():e}export{l as clientOnly,i as createMemoryStorage,f as env,r as isClient,g as isServer,u as storage};
1
+ // src/lib/env/index.ts
2
+ import { isServer } from "@fluixi/dom";
3
+ import { isServer as onServer } from "@fluixi/dom";
4
+ function isClient() {
5
+ return !onServer();
6
+ }
7
+ function createMemoryStorage() {
8
+ const mem = /* @__PURE__ */ new Map();
9
+ return {
10
+ getItem: (k) => mem.has(k) ? mem.get(k) : null,
11
+ setItem: (k, v) => void mem.set(k, String(v)),
12
+ removeItem: (k) => void mem.delete(k),
13
+ clear: () => mem.clear(),
14
+ key: (i) => Array.from(mem.keys())[i] ?? null,
15
+ get length() {
16
+ return mem.size;
17
+ }
18
+ };
19
+ }
20
+ var storage = typeof localStorage !== "undefined" ? localStorage : createMemoryStorage();
21
+ var env = {
22
+ get window() {
23
+ return typeof window !== "undefined" ? window : void 0;
24
+ },
25
+ get document() {
26
+ return typeof document !== "undefined" ? document : void 0;
27
+ }
28
+ };
29
+ function clientOnly(fn, fallback) {
30
+ return isClient() ? fn() : fallback;
31
+ }
32
+ export {
33
+ clientOnly,
34
+ createMemoryStorage,
35
+ env,
36
+ isClient,
37
+ isServer,
38
+ storage
39
+ };
@@ -1 +1,108 @@
1
- "use strict";var L=Object.defineProperty;var K=Object.getOwnPropertyDescriptor;var I=Object.getOwnPropertyNames;var R=Object.prototype.hasOwnProperty;var k=(e,o)=>{for(var l in o)L(e,l,{get:o[l],enumerable:!0})},v=(e,o,l,i)=>{if(o&&typeof o=="object"||typeof o=="function")for(let s of I(o))!R.call(e,s)&&s!==l&&L(e,s,{get:()=>o[s],enumerable:!(i=K(o,s))||i.enumerable});return e};var C=e=>v(L({},"__esModule",{value:!0}),e);var h={};k(h,{createI18n:()=>F,detectLocale:()=>S});module.exports=C(h);var M=require("@fluixi/reactive/signal"),f=require("@fluixi/dom"),y="__i18n:locale",x=typeof document>"u";function _(){if(x)return;let e=(0,f.getServerData)();return e?e[y]:void 0}function D(e){if(!(typeof document>"u"))try{document.cookie=`locale=${e};path=/;max-age=31536000;samesite=lax`}catch{}}function F(e){let o=e.persist??D,[l,i]=(0,M.createSignal)(_()??e.locale),s=()=>x?(0,f.getRequestContext)():void 0;function a(){let n=s();return n?n.__i18nLocale??e.locale:l()}function d(n){let t=s();if(t){t.__i18nLocale=n,t.data?.set?.(y,n);return}i(()=>n),o(n)}function p(n,t){let c=e.messages[n];if(c==null)return;let r=c[t];if(r!==void 0)return r;let u=c;for(let g of t.split(".")){if(u==null||typeof u!="object")return;u=u[g]}return u}function m(n,t){return t?n.replace(/\{(\w+)\}/g,(c,r)=>r in t?String(t[r]):`{${r}}`):n}function w(n,t){let c=a(),r=p(c,n);if(r===void 0&&c!==e.locale&&(r=p(e.locale,n)),r===void 0)return n;if(typeof r!="string"){let u=Number(t?.count??0),g=new Intl.PluralRules(c).select(u),b=r[g]??r.other??Object.values(r)[0]??"";return m(b,t)}return m(r,t)}return{t:w,n:(n,t)=>new Intl.NumberFormat(a(),t).format(n),d:(n,t)=>new Intl.DateTimeFormat(a(),t).format(n),locale:a,setLocale:d,locales:e.locales}}function S(e,o){if(!e)return;let l=e.split(",").map(i=>{let[s,a]=i.trim().split(";q=");return{tag:s.toLowerCase(),q:a?parseFloat(a):1}}).sort((i,s)=>s.q-i.q);for(let{tag:i}of l){let s=i.split("-")[0],a=o.find(d=>d.toLowerCase()===i||d.toLowerCase()===s);if(a)return a}}
1
+ /*! @fluixi/core v1.0.0-alpha.84 | (c) 2026 Ibrahima Touré and Fluixi contributors | MIT */
2
+ "use strict";
3
+ var __defProp = Object.defineProperty;
4
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
+ var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
7
+ var __export = (target, all) => {
8
+ for (var name in all)
9
+ __defProp(target, name, { get: all[name], enumerable: true });
10
+ };
11
+ var __copyProps = (to, from, except, desc) => {
12
+ if (from && typeof from === "object" || typeof from === "function") {
13
+ for (let key of __getOwnPropNames(from))
14
+ if (!__hasOwnProp.call(to, key) && key !== except)
15
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
16
+ }
17
+ return to;
18
+ };
19
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
20
+
21
+ // src/lib/i18n/index.ts
22
+ var index_exports = {};
23
+ __export(index_exports, {
24
+ createI18n: () => createI18n,
25
+ detectLocale: () => detectLocale
26
+ });
27
+ module.exports = __toCommonJS(index_exports);
28
+ var import_signal = require("@fluixi/reactive/signal");
29
+ var import_dom = require("@fluixi/dom");
30
+ var SEED_KEY = "__i18n:locale";
31
+ var IS_SERVER = typeof document === "undefined";
32
+ function readSeed() {
33
+ if (IS_SERVER) return void 0;
34
+ const data = (0, import_dom.getServerData)();
35
+ return data ? data[SEED_KEY] : void 0;
36
+ }
37
+ function cookiePersist(locale) {
38
+ if (typeof document === "undefined") return;
39
+ try {
40
+ document.cookie = `locale=${locale};path=/;max-age=31536000;samesite=lax`;
41
+ } catch {
42
+ }
43
+ }
44
+ function createI18n(config) {
45
+ const persist = config.persist ?? cookiePersist;
46
+ const [clientLocale, setClientLocale] = (0, import_signal.createSignal)(readSeed() ?? config.locale);
47
+ const serverCtx = () => IS_SERVER ? (0, import_dom.getRequestContext)() : void 0;
48
+ function locale() {
49
+ const ctx = serverCtx();
50
+ if (ctx) return ctx.__i18nLocale ?? config.locale;
51
+ return clientLocale();
52
+ }
53
+ function setLocale(next) {
54
+ const ctx = serverCtx();
55
+ if (ctx) {
56
+ ctx.__i18nLocale = next;
57
+ ctx.data?.set?.(SEED_KEY, next);
58
+ return;
59
+ }
60
+ setClientLocale(() => next);
61
+ persist(next);
62
+ }
63
+ function resolve(loc, key) {
64
+ const bundle = config.messages[loc];
65
+ if (bundle == null) return void 0;
66
+ const flat = bundle[key];
67
+ if (flat !== void 0) return flat;
68
+ let node = bundle;
69
+ for (const part of key.split(".")) {
70
+ if (node == null || typeof node !== "object") return void 0;
71
+ node = node[part];
72
+ }
73
+ return node;
74
+ }
75
+ function interpolate(str, params) {
76
+ if (!params) return str;
77
+ return str.replace(/\{(\w+)\}/g, (_m, k) => k in params ? String(params[k]) : `{${k}}`);
78
+ }
79
+ function t(key, params) {
80
+ const loc = locale();
81
+ let msg = resolve(loc, key);
82
+ if (msg === void 0 && loc !== config.locale) msg = resolve(config.locale, key);
83
+ if (msg === void 0) return key;
84
+ if (typeof msg !== "string") {
85
+ const count = Number(params?.count ?? 0);
86
+ const category = new Intl.PluralRules(loc).select(count);
87
+ const branch = msg[category] ?? msg.other ?? Object.values(msg)[0] ?? "";
88
+ return interpolate(branch, params);
89
+ }
90
+ return interpolate(msg, params);
91
+ }
92
+ const n = (value, options) => new Intl.NumberFormat(locale(), options).format(value);
93
+ const d = (value, options) => new Intl.DateTimeFormat(locale(), options).format(value);
94
+ return { t, n, d, locale, setLocale, locales: config.locales };
95
+ }
96
+ function detectLocale(acceptLanguage, locales) {
97
+ if (!acceptLanguage) return void 0;
98
+ const ranked = acceptLanguage.split(",").map((part) => {
99
+ const [tag, q] = part.trim().split(";q=");
100
+ return { tag: tag.toLowerCase(), q: q ? parseFloat(q) : 1 };
101
+ }).sort((a, b) => b.q - a.q);
102
+ for (const { tag } of ranked) {
103
+ const base = tag.split("-")[0];
104
+ const hit = locales.find((l) => l.toLowerCase() === tag || l.toLowerCase() === base);
105
+ if (hit) return hit;
106
+ }
107
+ return void 0;
108
+ }
@@ -1,5 +1,5 @@
1
1
  /**
2
- * @fluixi/core/i18n built-in, reactive, SSR-correct internationalization.
2
+ * @fluixi/core/i18n: built-in, reactive, SSR-correct internationalization.
3
3
  *
4
4
  * Three things make this distinct:
5
5
  *
@@ -9,12 +9,12 @@
9
9
  * (no flash, no hydration mismatch).
10
10
  *
11
11
  * 2. **No reactive-owner-context dependency.** `t()` reads the locale from the request context /
12
- * module signal NOT `useContext` so it resolves in lazy routes, server functions, loaders,
12
+ * module signal, not `useContext`, so it resolves in lazy routes, server functions, loaders,
13
13
  * anywhere. (This is precisely why it sidesteps the classic "useLocale() is undefined under
14
- * SSR on a lazy route" failure there's no provider owner-chain to lose.)
14
+ * SSR on a lazy route" failure: there's no provider owner-chain to lose.)
15
15
  *
16
16
  * 3. **Platform-native formatting.** Pluralization via `Intl.PluralRules`, numbers/dates via
17
- * `Intl.NumberFormat`/`Intl.DateTimeFormat` correct CLDR rules, zero dependencies.
17
+ * `Intl.NumberFormat`/`Intl.DateTimeFormat`: correct CLDR rules, zero dependencies.
18
18
  *
19
19
  * const i18n = createI18n({ locale: 'en', locales: ['en', 'fr'] as const, messages: { en, fr } });
20
20
  * export const { t, n, d, locale, setLocale } = i18n;
@@ -22,10 +22,10 @@
22
22
  * t('welcome', { name: 'Ada' }) // "Welcome, Ada"
23
23
  * t('cart.items', { count: 3 }) // plural branch via Intl.PluralRules
24
24
  * n(1234.5); d(new Date()); // locale-aware number/date
25
- * setLocale('fr'); // reactive every t() re-evaluates
25
+ * setLocale('fr'); // reactive, every t() re-evaluates
26
26
  */
27
27
  import { type Accessor } from '@fluixi/reactive/signal';
28
- /** A leaf message: a plain string, or a plural map keyed by CLDR category (`one`/`other`/…). */
28
+ /** A leaf message: a plain string, or a plural map keyed by CLDR category (`one`/`other`/...). */
29
29
  export type MessageValue = string | {
30
30
  readonly [pluralCategory: string]: string;
31
31
  };
@@ -36,13 +36,13 @@ export interface Messages {
36
36
  /** CLDR plural categories. An object keyed *only* by these is a plural leaf, not a subtree. */
37
37
  type PluralCategory = 'zero' | 'one' | 'two' | 'few' | 'many' | 'other';
38
38
  /**
39
- * The union of every valid translation key in `M` `t()` autocompletes these and flags typos.
39
+ * The union of every valid translation key in `M`: `t()` autocompletes these and flags typos.
40
40
  * Flat keys (`'welcome'`, `'nav.dashboard'`), nested trees (`'cart.items'`, `'nested.deep.key'`),
41
- * and plural maps (`{ one, other }` a leaf) all work. Only *leaf* paths are emitted, never the
41
+ * and plural maps (`{ one, other }` -> a leaf) all work. Only *leaf* paths are emitted, never the
42
42
  * intermediate branch (`'nav'`, `'cart'`). Falls open to `string` when `M` is just `Messages`.
43
43
  *
44
44
  * A subtree and a plural map are both `Record<string, string>` structurally, so the plural leaf is
45
- * detected by its keys being CLDR categories not by "all children are strings" (which wrongly
45
+ * detected by its keys being CLDR categories, not by "all children are strings" (which wrongly
46
46
  * truncated `nav: { dashboard, settings }` to `'nav'`).
47
47
  */
48
48
  export type MessageKey<M> = M extends object ? {
@@ -65,13 +65,34 @@ export interface I18n<L extends string, K extends string = string> {
65
65
  n: (value: number, options?: Intl.NumberFormatOptions) => string;
66
66
  /** Format a date for the active locale (`Intl.DateTimeFormat`). */
67
67
  d: (value: Date | number, options?: Intl.DateTimeFormatOptions) => string;
68
- /** The active locale reactive on the client, per-request on the server. */
68
+ /** The active locale: reactive on the client, per-request on the server. */
69
69
  locale: Accessor<L>;
70
70
  /** Switch the active locale (client: reactive + persisted; server: this request only). */
71
71
  setLocale: (locale: L) => void;
72
72
  /** Supported locales. */
73
73
  locales: readonly L[];
74
74
  }
75
+ /**
76
+ * Translations, with the message keys inferred from the messages themselves.
77
+ *
78
+ * `t()` accepts only leaf paths that exist in the catalogue, so a typo is a type error
79
+ * rather than a string echoed back at a visitor. A missing key at runtime returns the key,
80
+ * which is visible in the page and traceable.
81
+ *
82
+ * The locale is per request on the server and reactive on the client, seeded from what the
83
+ * server resolved so hydration cannot disagree about the language. Persistence is a cookie
84
+ * by default, which is the only store a server render can read.
85
+ *
86
+ * @example
87
+ * ```ts
88
+ * const i18n = createI18n({
89
+ * locale: 'en',
90
+ * messages: { en: { hi: 'Hello' }, fr: { hi: 'Bonjour' } },
91
+ * });
92
+ * i18n.t('hi'); // 'Hello'
93
+ * i18n.setLocale('fr');
94
+ * ```
95
+ */
75
96
  export declare function createI18n<L extends string, const M extends Record<L, Messages>>(config: I18nConfig<L, M>): I18n<L, MessageKey<M[keyof M]>>;
76
97
  /** Pick the best supported locale from an `Accept-Language` header, else `undefined`. */
77
98
  export declare function detectLocale<L extends string>(acceptLanguage: string | null | undefined, locales: readonly L[]): L | undefined;
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/lib/i18n/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/lib/i18n/index.ts"],"names":[],"mappings":"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"}
@@ -1,5 +1,5 @@
1
1
  /**
2
- * @fluixi/core/i18n built-in, reactive, SSR-correct internationalization.
2
+ * @fluixi/core/i18n: built-in, reactive, SSR-correct internationalization.
3
3
  *
4
4
  * Three things make this distinct:
5
5
  *
@@ -9,12 +9,12 @@
9
9
  * (no flash, no hydration mismatch).
10
10
  *
11
11
  * 2. **No reactive-owner-context dependency.** `t()` reads the locale from the request context /
12
- * module signal NOT `useContext` so it resolves in lazy routes, server functions, loaders,
12
+ * module signal, not `useContext`, so it resolves in lazy routes, server functions, loaders,
13
13
  * anywhere. (This is precisely why it sidesteps the classic "useLocale() is undefined under
14
- * SSR on a lazy route" failure there's no provider owner-chain to lose.)
14
+ * SSR on a lazy route" failure: there's no provider owner-chain to lose.)
15
15
  *
16
16
  * 3. **Platform-native formatting.** Pluralization via `Intl.PluralRules`, numbers/dates via
17
- * `Intl.NumberFormat`/`Intl.DateTimeFormat` correct CLDR rules, zero dependencies.
17
+ * `Intl.NumberFormat`/`Intl.DateTimeFormat`: correct CLDR rules, zero dependencies.
18
18
  *
19
19
  * const i18n = createI18n({ locale: 'en', locales: ['en', 'fr'] as const, messages: { en, fr } });
20
20
  * export const { t, n, d, locale, setLocale } = i18n;
@@ -22,7 +22,7 @@
22
22
  * t('welcome', { name: 'Ada' }) // "Welcome, Ada"
23
23
  * t('cart.items', { count: 3 }) // plural branch via Intl.PluralRules
24
24
  * n(1234.5); d(new Date()); // locale-aware number/date
25
- * setLocale('fr'); // reactive every t() re-evaluates
25
+ * setLocale('fr'); // reactive, every t() re-evaluates
26
26
  */
27
27
  import { createSignal } from '@fluixi/reactive/signal';
28
28
  import { getRequestContext, getServerData } from '@fluixi/dom';
@@ -41,9 +41,30 @@ function cookiePersist(locale) {
41
41
  document.cookie = `locale=${locale};path=/;max-age=31536000;samesite=lax`;
42
42
  }
43
43
  catch {
44
- /* private mode / disabled best effort */
44
+ /* private mode / disabled: best effort */
45
45
  }
46
46
  }
47
+ /**
48
+ * Translations, with the message keys inferred from the messages themselves.
49
+ *
50
+ * `t()` accepts only leaf paths that exist in the catalogue, so a typo is a type error
51
+ * rather than a string echoed back at a visitor. A missing key at runtime returns the key,
52
+ * which is visible in the page and traceable.
53
+ *
54
+ * The locale is per request on the server and reactive on the client, seeded from what the
55
+ * server resolved so hydration cannot disagree about the language. Persistence is a cookie
56
+ * by default, which is the only store a server render can read.
57
+ *
58
+ * @example
59
+ * ```ts
60
+ * const i18n = createI18n({
61
+ * locale: 'en',
62
+ * messages: { en: { hi: 'Hello' }, fr: { hi: 'Bonjour' } },
63
+ * });
64
+ * i18n.t('hi'); // 'Hello'
65
+ * i18n.setLocale('fr');
66
+ * ```
67
+ */
47
68
  export function createI18n(config) {
48
69
  const persist = config.persist ?? cookiePersist;
49
70
  // Client: a reactive signal seeded from the server-resolved locale (so hydration matches).
@@ -52,14 +73,14 @@ export function createI18n(config) {
52
73
  function locale() {
53
74
  const ctx = serverCtx();
54
75
  if (ctx)
55
- return ctx.__i18nLocale ?? config.locale; // server: per-request, no shared signal no leak
76
+ return ctx.__i18nLocale ?? config.locale; // server: per-request, no shared signal -> no leak
56
77
  return clientLocale(); // client: reactive
57
78
  }
58
79
  function setLocale(next) {
59
80
  const ctx = serverCtx();
60
81
  if (ctx) {
61
82
  ctx.__i18nLocale = next;
62
- ctx.data?.set?.(SEED_KEY, next); // serialize client hydrates in the same language
83
+ ctx.data?.set?.(SEED_KEY, next); // serialize -> client hydrates in the same language
63
84
  return;
64
85
  }
65
86
  setClientLocale(() => next);
@@ -69,7 +90,7 @@ export function createI18n(config) {
69
90
  const bundle = config.messages[loc];
70
91
  if (bundle == null)
71
92
  return undefined;
72
- // Flat key first supports dotted flat keys like `nav.dashboard` (not just nested trees).
93
+ // Flat key first: supports dotted flat keys like `nav.dashboard` (not just nested trees).
73
94
  const flat = bundle[key];
74
95
  if (flat !== undefined)
75
96
  return flat;
@@ -93,7 +114,7 @@ export function createI18n(config) {
93
114
  if (msg === undefined && loc !== config.locale)
94
115
  msg = resolve(config.locale, key); // fallback locale
95
116
  if (msg === undefined)
96
- return key; // missing echo the key (visible, debuggable)
117
+ return key; // missing -> echo the key (visible, debuggable)
97
118
  if (typeof msg !== 'string') {
98
119
  const count = Number(params?.count ?? 0);
99
120
  const category = new Intl.PluralRules(loc).select(count);
@@ -1 +1,88 @@
1
- import{createSignal as x}from"@fluixi/reactive/signal";import{getRequestContext as w,getServerData as b}from"@fluixi/dom";var p="__i18n:locale",m=typeof document>"u";function K(){if(m)return;let t=b();return t?t[p]:void 0}function I(t){if(!(typeof document>"u"))try{document.cookie=`locale=${t};path=/;max-age=31536000;samesite=lax`}catch{}}function _(t){let u=t.persist??I,[d,o]=x(K()??t.locale),i=()=>m?w():void 0;function s(){let e=i();return e?e.__i18nLocale??t.locale:d()}function c(e){let n=i();if(n){n.__i18nLocale=e,n.data?.set?.(p,e);return}o(()=>e),u(e)}function g(e,n){let a=t.messages[e];if(a==null)return;let r=a[n];if(r!==void 0)return r;let l=a;for(let f of n.split(".")){if(l==null||typeof l!="object")return;l=l[f]}return l}function L(e,n){return n?e.replace(/\{(\w+)\}/g,(a,r)=>r in n?String(n[r]):`{${r}}`):e}function M(e,n){let a=s(),r=g(a,e);if(r===void 0&&a!==t.locale&&(r=g(t.locale,e)),r===void 0)return e;if(typeof r!="string"){let l=Number(n?.count??0),f=new Intl.PluralRules(a).select(l),y=r[f]??r.other??Object.values(r)[0]??"";return L(y,n)}return L(r,n)}return{t:M,n:(e,n)=>new Intl.NumberFormat(s(),n).format(e),d:(e,n)=>new Intl.DateTimeFormat(s(),n).format(e),locale:s,setLocale:c,locales:t.locales}}function D(t,u){if(!t)return;let d=t.split(",").map(o=>{let[i,s]=o.trim().split(";q=");return{tag:i.toLowerCase(),q:s?parseFloat(s):1}}).sort((o,i)=>i.q-o.q);for(let{tag:o}of d){let i=o.split("-")[0],s=u.find(c=>c.toLowerCase()===o||c.toLowerCase()===i);if(s)return s}}export{_ as createI18n,D as detectLocale};
1
+ /*! @fluixi/core v1.0.0-alpha.84 | (c) 2026 Ibrahima Touré and Fluixi contributors | MIT */
2
+
3
+ // src/lib/i18n/index.ts
4
+ import { createSignal } from "@fluixi/reactive/signal";
5
+ import { getRequestContext, getServerData } from "@fluixi/dom";
6
+ var SEED_KEY = "__i18n:locale";
7
+ var IS_SERVER = typeof document === "undefined";
8
+ function readSeed() {
9
+ if (IS_SERVER) return void 0;
10
+ const data = getServerData();
11
+ return data ? data[SEED_KEY] : void 0;
12
+ }
13
+ function cookiePersist(locale) {
14
+ if (typeof document === "undefined") return;
15
+ try {
16
+ document.cookie = `locale=${locale};path=/;max-age=31536000;samesite=lax`;
17
+ } catch {
18
+ }
19
+ }
20
+ function createI18n(config) {
21
+ const persist = config.persist ?? cookiePersist;
22
+ const [clientLocale, setClientLocale] = createSignal(readSeed() ?? config.locale);
23
+ const serverCtx = () => IS_SERVER ? getRequestContext() : void 0;
24
+ function locale() {
25
+ const ctx = serverCtx();
26
+ if (ctx) return ctx.__i18nLocale ?? config.locale;
27
+ return clientLocale();
28
+ }
29
+ function setLocale(next) {
30
+ const ctx = serverCtx();
31
+ if (ctx) {
32
+ ctx.__i18nLocale = next;
33
+ ctx.data?.set?.(SEED_KEY, next);
34
+ return;
35
+ }
36
+ setClientLocale(() => next);
37
+ persist(next);
38
+ }
39
+ function resolve(loc, key) {
40
+ const bundle = config.messages[loc];
41
+ if (bundle == null) return void 0;
42
+ const flat = bundle[key];
43
+ if (flat !== void 0) return flat;
44
+ let node = bundle;
45
+ for (const part of key.split(".")) {
46
+ if (node == null || typeof node !== "object") return void 0;
47
+ node = node[part];
48
+ }
49
+ return node;
50
+ }
51
+ function interpolate(str, params) {
52
+ if (!params) return str;
53
+ return str.replace(/\{(\w+)\}/g, (_m, k) => k in params ? String(params[k]) : `{${k}}`);
54
+ }
55
+ function t(key, params) {
56
+ const loc = locale();
57
+ let msg = resolve(loc, key);
58
+ if (msg === void 0 && loc !== config.locale) msg = resolve(config.locale, key);
59
+ if (msg === void 0) return key;
60
+ if (typeof msg !== "string") {
61
+ const count = Number(params?.count ?? 0);
62
+ const category = new Intl.PluralRules(loc).select(count);
63
+ const branch = msg[category] ?? msg.other ?? Object.values(msg)[0] ?? "";
64
+ return interpolate(branch, params);
65
+ }
66
+ return interpolate(msg, params);
67
+ }
68
+ const n = (value, options) => new Intl.NumberFormat(locale(), options).format(value);
69
+ const d = (value, options) => new Intl.DateTimeFormat(locale(), options).format(value);
70
+ return { t, n, d, locale, setLocale, locales: config.locales };
71
+ }
72
+ function detectLocale(acceptLanguage, locales) {
73
+ if (!acceptLanguage) return void 0;
74
+ const ranked = acceptLanguage.split(",").map((part) => {
75
+ const [tag, q] = part.trim().split(";q=");
76
+ return { tag: tag.toLowerCase(), q: q ? parseFloat(q) : 1 };
77
+ }).sort((a, b) => b.q - a.q);
78
+ for (const { tag } of ranked) {
79
+ const base = tag.split("-")[0];
80
+ const hit = locales.find((l) => l.toLowerCase() === tag || l.toLowerCase() === base);
81
+ if (hit) return hit;
82
+ }
83
+ return void 0;
84
+ }
85
+ export {
86
+ createI18n,
87
+ detectLocale
88
+ };