@fluixi/core 1.0.0-alpha.100

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 (253) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +334 -0
  3. package/dist/cdn/core.global.js +2 -0
  4. package/dist/cli/generate.cjs +5639 -0
  5. package/dist/cli/generate.d.ts +7 -0
  6. package/dist/cli/generate.d.ts.map +1 -0
  7. package/dist/cli/generate.js +2580 -0
  8. package/dist/cli/generate.mjs +5644 -0
  9. package/dist/cli/index.cjs +5639 -0
  10. package/dist/cli/index.d.ts +7 -0
  11. package/dist/cli/index.d.ts.map +1 -0
  12. package/dist/cli/index.js +2580 -0
  13. package/dist/cli/index.mjs +5644 -0
  14. package/dist/cli/run.cjs +64 -0
  15. package/dist/cli/run.d.ts +3 -0
  16. package/dist/cli/run.d.ts.map +1 -0
  17. package/dist/cli/run.js +62 -0
  18. package/dist/cli/run.mjs +40 -0
  19. package/dist/fluixi.d.ts +5 -0
  20. package/dist/src/cdn/chunk-RKBFEFZP.mjs +987 -0
  21. package/dist/src/cdn/core.cjs +1592 -0
  22. package/dist/src/cdn/core.d.ts +16 -0
  23. package/dist/src/cdn/core.d.ts.map +1 -0
  24. package/dist/src/cdn/core.js +15 -0
  25. package/dist/src/cdn/core.mjs +714 -0
  26. package/dist/src/cdn/router-V2THK27H.mjs +74 -0
  27. package/dist/src/index.cjs +1711 -0
  28. package/dist/src/index.d.ts +4 -0
  29. package/dist/src/index.d.ts.map +1 -0
  30. package/dist/src/index.js +11 -0
  31. package/dist/src/index.mjs +1833 -0
  32. package/dist/src/jsx-dev-runtime.cjs +26 -0
  33. package/dist/src/jsx-dev-runtime.d.ts +2 -0
  34. package/dist/src/jsx-dev-runtime.d.ts.map +1 -0
  35. package/dist/src/jsx-dev-runtime.js +1 -0
  36. package/dist/src/jsx-dev-runtime.mjs +24 -0
  37. package/dist/src/jsx-runtime.cjs +26 -0
  38. package/dist/src/jsx-runtime.d.ts +7 -0
  39. package/dist/src/jsx-runtime.d.ts.map +1 -0
  40. package/dist/src/jsx-runtime.js +8 -0
  41. package/dist/src/jsx-runtime.mjs +24 -0
  42. package/dist/src/lib/client/chunk-FDOPDB6Z.mjs +53 -0
  43. package/dist/src/lib/client/index.cjs +1210 -0
  44. package/dist/src/lib/client/index.d.ts +51 -0
  45. package/dist/src/lib/client/index.d.ts.map +1 -0
  46. package/dist/src/lib/client/index.js +174 -0
  47. package/dist/src/lib/client/index.mjs +293 -0
  48. package/dist/src/lib/client/router-4PTBPZLQ.mjs +891 -0
  49. package/dist/src/lib/context/context.cjs +81 -0
  50. package/dist/src/lib/context/context.d.ts +73 -0
  51. package/dist/src/lib/context/context.d.ts.map +1 -0
  52. package/dist/src/lib/context/context.js +93 -0
  53. package/dist/src/lib/context/context.mjs +64 -0
  54. package/dist/src/lib/context/index.cjs +83 -0
  55. package/dist/src/lib/context/index.d.ts +3 -0
  56. package/dist/src/lib/context/index.d.ts.map +1 -0
  57. package/dist/src/lib/context/index.js +1 -0
  58. package/dist/src/lib/context/index.mjs +64 -0
  59. package/dist/src/lib/control-flow.cjs +35 -0
  60. package/dist/src/lib/control-flow.d.ts +4 -0
  61. package/dist/src/lib/control-flow.d.ts.map +1 -0
  62. package/dist/src/lib/control-flow.js +1 -0
  63. package/dist/src/lib/control-flow.mjs +25 -0
  64. package/dist/src/lib/core.cjs +1710 -0
  65. package/dist/src/lib/core.d.ts +91 -0
  66. package/dist/src/lib/core.d.ts.map +1 -0
  67. package/dist/src/lib/core.js +158 -0
  68. package/dist/src/lib/core.mjs +1833 -0
  69. package/dist/src/lib/env/index.cjs +44 -0
  70. package/dist/src/lib/env/index.d.ts +26 -0
  71. package/dist/src/lib/env/index.d.ts.map +1 -0
  72. package/dist/src/lib/env/index.js +31 -0
  73. package/dist/src/lib/env/index.mjs +23 -0
  74. package/dist/src/lib/i18n/index.cjs +123 -0
  75. package/dist/src/lib/i18n/index.d.ts +110 -0
  76. package/dist/src/lib/i18n/index.d.ts.map +1 -0
  77. package/dist/src/lib/i18n/index.js +164 -0
  78. package/dist/src/lib/i18n/index.mjs +103 -0
  79. package/dist/src/lib/index.cjs +598 -0
  80. package/dist/src/lib/index.d.ts +81 -0
  81. package/dist/src/lib/index.d.ts.map +1 -0
  82. package/dist/src/lib/index.js +130 -0
  83. package/dist/src/lib/index.mjs +688 -0
  84. package/dist/src/lib/isomorphic.cjs +90 -0
  85. package/dist/src/lib/isomorphic.d.ts +114 -0
  86. package/dist/src/lib/isomorphic.d.ts.map +1 -0
  87. package/dist/src/lib/isomorphic.js +132 -0
  88. package/dist/src/lib/isomorphic.mjs +69 -0
  89. package/dist/src/lib/jsx-runtime/index.cjs +21 -0
  90. package/dist/src/lib/jsx-runtime/index.d.ts +13 -0
  91. package/dist/src/lib/jsx-runtime/index.d.ts.map +1 -0
  92. package/dist/src/lib/jsx-runtime/index.js +13 -0
  93. package/dist/src/lib/jsx-runtime/index.mjs +4 -0
  94. package/dist/src/lib/jsx-runtime/jsx-dev-runtime.cjs +21 -0
  95. package/dist/src/lib/jsx-runtime/jsx-dev-runtime.d.ts +2 -0
  96. package/dist/src/lib/jsx-runtime/jsx-dev-runtime.d.ts.map +1 -0
  97. package/dist/src/lib/jsx-runtime/jsx-dev-runtime.js +1 -0
  98. package/dist/src/lib/jsx-runtime/jsx-dev-runtime.mjs +4 -0
  99. package/dist/src/lib/plugins/fluixi-routes-plugin.cjs +302 -0
  100. package/dist/src/lib/plugins/fluixi-routes-plugin.d.ts +35 -0
  101. package/dist/src/lib/plugins/fluixi-routes-plugin.d.ts.map +1 -0
  102. package/dist/src/lib/plugins/fluixi-routes-plugin.js +118 -0
  103. package/dist/src/lib/plugins/fluixi-routes-plugin.mjs +271 -0
  104. package/dist/src/lib/plugins/index.cjs +311 -0
  105. package/dist/src/lib/plugins/index.d.ts +6 -0
  106. package/dist/src/lib/plugins/index.d.ts.map +1 -0
  107. package/dist/src/lib/plugins/index.js +7 -0
  108. package/dist/src/lib/plugins/index.mjs +279 -0
  109. package/dist/src/lib/plugins/route-codegen.cjs +73 -0
  110. package/dist/src/lib/plugins/route-codegen.d.ts +12 -0
  111. package/dist/src/lib/plugins/route-codegen.d.ts.map +1 -0
  112. package/dist/src/lib/plugins/route-codegen.js +80 -0
  113. package/dist/src/lib/plugins/route-codegen.mjs +52 -0
  114. package/dist/src/lib/plugins/route-scanner.cjs +189 -0
  115. package/dist/src/lib/plugins/route-scanner.d.ts +38 -0
  116. package/dist/src/lib/plugins/route-scanner.d.ts.map +1 -0
  117. package/dist/src/lib/plugins/route-scanner.js +215 -0
  118. package/dist/src/lib/plugins/route-scanner.mjs +158 -0
  119. package/dist/src/lib/plugins/vite.cjs +27 -0
  120. package/dist/src/lib/plugins/vite.d.ts +3 -0
  121. package/dist/src/lib/plugins/vite.d.ts.map +1 -0
  122. package/dist/src/lib/plugins/vite.js +1 -0
  123. package/dist/src/lib/plugins/vite.mjs +6 -0
  124. package/dist/src/lib/render/await.cjs +38 -0
  125. package/dist/src/lib/render/await.d.ts +26 -0
  126. package/dist/src/lib/render/await.d.ts.map +1 -0
  127. package/dist/src/lib/render/await.js +45 -0
  128. package/dist/src/lib/render/await.mjs +17 -0
  129. package/dist/src/lib/render/component.cjs +221 -0
  130. package/dist/src/lib/render/component.d.ts +296 -0
  131. package/dist/src/lib/render/component.d.ts.map +1 -0
  132. package/dist/src/lib/render/component.js +514 -0
  133. package/dist/src/lib/render/component.mjs +214 -0
  134. package/dist/src/lib/render/deferred.cjs +175 -0
  135. package/dist/src/lib/render/deferred.d.ts +36 -0
  136. package/dist/src/lib/render/deferred.d.ts.map +1 -0
  137. package/dist/src/lib/render/deferred.js +141 -0
  138. package/dist/src/lib/render/deferred.mjs +158 -0
  139. package/dist/src/lib/render/index.cjs +573 -0
  140. package/dist/src/lib/render/index.d.ts +98 -0
  141. package/dist/src/lib/render/index.d.ts.map +1 -0
  142. package/dist/src/lib/render/index.js +180 -0
  143. package/dist/src/lib/render/index.mjs +590 -0
  144. package/dist/src/lib/render/lazy.cjs +67 -0
  145. package/dist/src/lib/render/lazy.d.ts +49 -0
  146. package/dist/src/lib/render/lazy.d.ts.map +1 -0
  147. package/dist/src/lib/render/lazy.js +105 -0
  148. package/dist/src/lib/render/lazy.mjs +50 -0
  149. package/dist/src/lib/render/suspense.cjs +141 -0
  150. package/dist/src/lib/render/suspense.d.ts +65 -0
  151. package/dist/src/lib/render/suspense.d.ts.map +1 -0
  152. package/dist/src/lib/render/suspense.js +196 -0
  153. package/dist/src/lib/render/suspense.mjs +136 -0
  154. package/dist/src/lib/render/versions.cjs +35 -0
  155. package/dist/src/lib/render/versions.d.ts +2 -0
  156. package/dist/src/lib/render/versions.d.ts.map +1 -0
  157. package/dist/src/lib/render/versions.js +21 -0
  158. package/dist/src/lib/render/versions.mjs +14 -0
  159. package/dist/src/lib/router/data.cjs +228 -0
  160. package/dist/src/lib/router/data.d.ts +142 -0
  161. package/dist/src/lib/router/data.d.ts.map +1 -0
  162. package/dist/src/lib/router/data.js +258 -0
  163. package/dist/src/lib/router/data.mjs +214 -0
  164. package/dist/src/lib/router/index.cjs +921 -0
  165. package/dist/src/lib/router/index.d.ts +274 -0
  166. package/dist/src/lib/router/index.d.ts.map +1 -0
  167. package/dist/src/lib/router/index.js +904 -0
  168. package/dist/src/lib/router/index.mjs +938 -0
  169. package/dist/src/lib/router/scroll.cjs +79 -0
  170. package/dist/src/lib/router/scroll.d.ts +19 -0
  171. package/dist/src/lib/router/scroll.d.ts.map +1 -0
  172. package/dist/src/lib/router/scroll.js +68 -0
  173. package/dist/src/lib/router/scroll.mjs +58 -0
  174. package/dist/src/lib/router/transition.cjs +75 -0
  175. package/dist/src/lib/router/transition.d.ts +81 -0
  176. package/dist/src/lib/router/transition.d.ts.map +1 -0
  177. package/dist/src/lib/router/transition.js +136 -0
  178. package/dist/src/lib/router/transition.mjs +54 -0
  179. package/dist/src/lib/server/hydration.cjs +169 -0
  180. package/dist/src/lib/server/hydration.d.ts +198 -0
  181. package/dist/src/lib/server/hydration.d.ts.map +1 -0
  182. package/dist/src/lib/server/hydration.js +345 -0
  183. package/dist/src/lib/server/hydration.mjs +148 -0
  184. package/dist/src/lib/server/index.cjs +406 -0
  185. package/dist/src/lib/server/index.d.ts +115 -0
  186. package/dist/src/lib/server/index.d.ts.map +1 -0
  187. package/dist/src/lib/server/index.js +164 -0
  188. package/dist/src/lib/server/index.mjs +384 -0
  189. package/dist/src/lib/server/reactive.cjs +197 -0
  190. package/dist/src/lib/server/reactive.d.ts +239 -0
  191. package/dist/src/lib/server/reactive.d.ts.map +1 -0
  192. package/dist/src/lib/server/reactive.js +413 -0
  193. package/dist/src/lib/server/reactive.mjs +176 -0
  194. package/dist/src/lib/storage/cache.cjs +51 -0
  195. package/dist/src/lib/storage/cache.d.ts +18 -0
  196. package/dist/src/lib/storage/cache.d.ts.map +1 -0
  197. package/dist/src/lib/storage/cache.js +42 -0
  198. package/dist/src/lib/storage/cache.mjs +30 -0
  199. package/dist/src/lib/storage/index.cjs +246 -0
  200. package/dist/src/lib/storage/index.d.ts +83 -0
  201. package/dist/src/lib/storage/index.d.ts.map +1 -0
  202. package/dist/src/lib/storage/index.js +179 -0
  203. package/dist/src/lib/storage/index.mjs +231 -0
  204. package/dist/src/lib/storage/persisted.cjs +91 -0
  205. package/dist/src/lib/storage/persisted.d.ts +53 -0
  206. package/dist/src/lib/storage/persisted.d.ts.map +1 -0
  207. package/dist/src/lib/storage/persisted.js +75 -0
  208. package/dist/src/lib/storage/persisted.mjs +70 -0
  209. package/dist/src/lib/theme/color-scheme.cjs +281 -0
  210. package/dist/src/lib/theme/color-scheme.d.ts +61 -0
  211. package/dist/src/lib/theme/color-scheme.d.ts.map +1 -0
  212. package/dist/src/lib/theme/color-scheme.js +120 -0
  213. package/dist/src/lib/theme/color-scheme.mjs +265 -0
  214. package/dist/src/lib/theme/index.cjs +267 -0
  215. package/dist/src/lib/theme/index.d.ts +78 -0
  216. package/dist/src/lib/theme/index.d.ts.map +1 -0
  217. package/dist/src/lib/theme/index.js +135 -0
  218. package/dist/src/lib/theme/index.mjs +251 -0
  219. package/dist/src/lib/theme/provider.cjs +346 -0
  220. package/dist/src/lib/theme/provider.d.ts +34 -0
  221. package/dist/src/lib/theme/provider.d.ts.map +1 -0
  222. package/dist/src/lib/theme/provider.js +60 -0
  223. package/dist/src/lib/theme/provider.mjs +332 -0
  224. package/dist/src/lib/utils/index.cjs +209 -0
  225. package/dist/src/lib/utils/index.d.ts +286 -0
  226. package/dist/src/lib/utils/index.d.ts.map +1 -0
  227. package/dist/src/lib/utils/index.js +434 -0
  228. package/dist/src/lib/utils/index.mjs +188 -0
  229. package/dist/src/routes.cjs +37 -0
  230. package/dist/src/routes.d.ts +22 -0
  231. package/dist/src/routes.d.ts.map +1 -0
  232. package/dist/src/routes.js +20 -0
  233. package/dist/src/routes.mjs +17 -0
  234. package/dist/src/server.cjs +405 -0
  235. package/dist/src/server.d.ts +63 -0
  236. package/dist/src/server.d.ts.map +1 -0
  237. package/dist/src/server.js +62 -0
  238. package/dist/src/server.mjs +382 -0
  239. package/dist/src/utils.cjs +21 -0
  240. package/dist/src/utils.d.ts +10 -0
  241. package/dist/src/utils.d.ts.map +1 -0
  242. package/dist/src/utils.js +9 -0
  243. package/dist/src/utils.mjs +4 -0
  244. package/dist/src/version.generated.cjs +26 -0
  245. package/dist/src/version.generated.d.ts +3 -0
  246. package/dist/src/version.generated.d.ts.map +1 -0
  247. package/dist/src/version.generated.js +3 -0
  248. package/dist/src/version.generated.mjs +5 -0
  249. package/dist/tsconfig.lib.tsbuildinfo +1 -0
  250. package/package.json +164 -0
  251. package/src/index.ts +19 -0
  252. package/types/fluixi.d.ts +5 -0
  253. package/types/vinxi.d.ts +50 -0
@@ -0,0 +1,51 @@
1
+ /**
2
+ * @module @fluixi/core/client
3
+ *
4
+ * Implements client-side mounting and hydration logic using @fluixi/dom runtime.
5
+ * Supports both JSX and Lit HTML.
6
+ */
7
+ import '../render/versions.js';
8
+ /**
9
+ * Mount application to DOM (Client-side Rendering)
10
+ *
11
+ * @example
12
+ * ```typescript
13
+ * import { mount } from '@fluixi/core/client';
14
+ * import App from './App';
15
+ *
16
+ * mount(() => App(), document.getElementById('root'));
17
+ * ```
18
+ */
19
+ export declare function mount(App: () => any, container: HTMLElement | null): void;
20
+ export { hydrate } from '@fluixi/dom';
21
+ export interface StartClientOptions {
22
+ /** CSS selector or HTMLElement for the app root. Default: '#app' */
23
+ root?: string | HTMLElement;
24
+ /** Force hydration mode. Default: auto-detect from __FLUIXI_HYDRATION__ marker */
25
+ hydrate?: boolean;
26
+ /**
27
+ * The app's route tree (the same array passed to <Router routes={...}/>). When provided,
28
+ * the lazy chunk(s) for the route matching the current URL are downloaded and awaited
29
+ * before hydration, so each lazy file-route resolves synchronously and adopts the server
30
+ * DOM in place (no fallback, no duplicate). Passing this also enables auto-hydration of a
31
+ * server-rendered (non-empty) root, giving flash-free hydration with zero extra config.
32
+ */
33
+ routes?: any[];
34
+ }
35
+ /**
36
+ * Mount or hydrate an app in the browser.
37
+ *
38
+ * Hydration is detected from the marker the server render leaves behind, so the same
39
+ * call works for a server-rendered page and a plain SPA. Pass `hydrate` to force it.
40
+ *
41
+ * Pass `routes` for a file-routed app. The chunks for the route matching the current URL
42
+ * are downloaded and awaited before hydrating, which is what lets each lazy route resolve
43
+ * synchronously and adopt the server's DOM rather than building a second copy beside it.
44
+ *
45
+ * @example
46
+ * ```ts
47
+ * await startClient(App, { root: '#app', routes });
48
+ * ```
49
+ */
50
+ export declare function startClient(App: (props?: any) => any, options?: StartClientOptions): Promise<void>;
51
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/lib/client/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAaH,OAAO,uBAAuB,CAAC;AAgB/B;;;;;;;;;;GAUG;AACH,wBAAgB,KAAK,CAAC,GAAG,EAAE,MAAM,GAAG,EAAE,SAAS,EAAE,WAAW,GAAG,IAAI,QAOlE;AAED,OAAO,EAAE,OAAO,EAAE,MAAM,aAAa,CAAC;AAEtC,MAAM,WAAW,kBAAkB;IACjC,oEAAoE;IACpE,IAAI,CAAC,EAAE,MAAM,GAAG,WAAW,CAAC;IAC5B,kFAAkF;IAClF,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB;;;;;;OAMG;IACH,MAAM,CAAC,EAAE,GAAG,EAAE,CAAC;CAChB;AAoBD;;;;;;;;;;;;;;GAcG;AACH,wBAAsB,WAAW,CAC/B,GAAG,EAAE,CAAC,KAAK,CAAC,EAAE,GAAG,KAAK,GAAG,EACzB,OAAO,GAAE,kBAAuB,iBAiFjC"}
@@ -0,0 +1,174 @@
1
+ /**
2
+ * @module @fluixi/core/client
3
+ *
4
+ * Implements client-side mounting and hydration logic using @fluixi/dom runtime.
5
+ * Supports both JSX and Lit HTML.
6
+ */
7
+ import { render as domRender, hydrate as domHydrate, beginAppHydration, endAppHydration, removeUnclaimedKeyed, clearHydrationKeys, } from '@fluixi/dom';
8
+ // Registers core's version with the DOM runtime, which does the stamping. This entry is a
9
+ // separate subpath, so it does not otherwise load core's render, and without this the
10
+ // hydrate path stamped `fx-dom`/`fx-reactive` but never `fluixi`.
11
+ import '../render/versions.js';
12
+ import { deserializeHydrationData, setHydrating, cleanupHydration, } from '../server/hydration.js';
13
+ import { render } from '../render/index.js';
14
+ import { createComponent } from '../render/component.js';
15
+ import { createMemo } from '@fluixi/reactive/signal';
16
+ import { createHead, setActiveHead, mountHead, stripHeadMarker } from '@fluixi/head';
17
+ // Connect the reactive system (signals, effects, batch) to the DOM runtime.
18
+ // Without this, createRenderEffect in @fluixi/dom is a one-shot call that never
19
+ // re-runs when signals change: breaking all JSX reactive updates.
20
+ // ensureIntegration();
21
+ /**
22
+ * Mount application to DOM (Client-side Rendering)
23
+ *
24
+ * @example
25
+ * ```typescript
26
+ * import { mount } from '@fluixi/core/client';
27
+ * import App from './App';
28
+ *
29
+ * mount(() => App(), document.getElementById('root'));
30
+ * ```
31
+ */
32
+ export function mount(App, container) {
33
+ if (!container) {
34
+ throw new Error('Container element not found for mount()');
35
+ }
36
+ // Use @fluixi/dom render which handles reactivity and supports Lit via registration
37
+ domRender(() => App(), container);
38
+ }
39
+ export { hydrate } from '@fluixi/dom';
40
+ /**
41
+ * Standard entry point for client-side rendering or hydration.
42
+ *
43
+ * Auto-detects whether to hydrate (if server-rendered HTML is present)
44
+ * or do a full client render.
45
+ *
46
+ * @example
47
+ * ```ts
48
+ * // entry-client.ts
49
+ * import { startClient } from '@fluixi/core/client';
50
+ * import App from './app';
51
+ *
52
+ * startClient(App);
53
+ * ```
54
+ */
55
+ /** The root, entered the way the compiler enters every other component. */
56
+ const rootOf = (App) => createMemo(() => createComponent(App));
57
+ /**
58
+ * Mount or hydrate an app in the browser.
59
+ *
60
+ * Hydration is detected from the marker the server render leaves behind, so the same
61
+ * call works for a server-rendered page and a plain SPA. Pass `hydrate` to force it.
62
+ *
63
+ * Pass `routes` for a file-routed app. The chunks for the route matching the current URL
64
+ * are downloaded and awaited before hydrating, which is what lets each lazy route resolve
65
+ * synchronously and adopt the server's DOM rather than building a second copy beside it.
66
+ *
67
+ * @example
68
+ * ```ts
69
+ * await startClient(App, { root: '#app', routes });
70
+ * ```
71
+ */
72
+ export async function startClient(App, options = {}) {
73
+ const container = typeof options.root === 'string'
74
+ ? document.querySelector(options.root)
75
+ : options.root ?? document.querySelector('#app');
76
+ if (!container) {
77
+ throw new Error(`[Fluixi] Mount container not found: ${options.root ?? '#app'}`);
78
+ }
79
+ // Hydrate when explicitly requested (`{ hydrate: true }`), when the server emits the
80
+ // `__FLUIXI_HYDRATION__` marker, or, with a route tree in hand, when the mount root already
81
+ // holds server-rendered content. A non-empty root means SSR/SSG ran, so reuse that DOM instead
82
+ // of clearing and re-rendering (which flashes). Auto-hydration is gated on `routes` because
83
+ // hydrating an app with async lazy file-routes is only safe once those chunks are preloaded
84
+ // (below): without the route tree we can't preload, so we fall back to the render() path. A
85
+ // client-only app mounts into an empty `<div id="root">` (firstElementChild null) -> client render.
86
+ const hasServerDom = !!document.getElementById('__FLUIXI_HYDRATION__') ||
87
+ (!!options.routes && container.firstElementChild != null);
88
+ const shouldHydrate = options.hydrate ?? hasServerDom;
89
+ // Active head registry for this document: seo()/useHead() during the app render register here;
90
+ // mountHead reconciles it into <head> after mount (reusing server tags by key) and keeps it live.
91
+ const head = createHead();
92
+ setActiveHead(head);
93
+ // Drop a stray `<!--fh:...-->` head-transport comment if the server left one in the mount root
94
+ // (streaming / custom servers that don't lift it into <head>). It would otherwise be the cursor's
95
+ // first node and strand hydration: rebuilding the whole tree as a duplicate. Harmless no-op when
96
+ // the server already extracted it (the supported adapter/prerender/dev paths do).
97
+ stripHeadMarker(container);
98
+ if (shouldHydrate) {
99
+ // Before the first await: custom elements the server rendered upgrade while the route
100
+ // chunks load, and wait for this hydration to hand them their owner.
101
+ beginAppHydration();
102
+ try {
103
+ // Preload the lazy chunk(s) for the current route so they resolve synchronously during the
104
+ // hydration render, the lazy boundary then adopts the server DOM in place instead of
105
+ // resolving a tick later and rebuilding a duplicate. Dynamic import keeps the router out of
106
+ // client-only bundles that never pass `routes`.
107
+ if (options.routes && options.routes.length) {
108
+ const { preloadRoutes } = await import('../router/index.js');
109
+ await preloadRoutes(options.routes, window.location.pathname);
110
+ }
111
+ deserializeHydrationData();
112
+ setHydrating(true);
113
+ // A memo around createComponent, which is what compiled JSX emits for every other
114
+ // component. Called directly, the root is the one component the runtime never hears
115
+ // about: nothing holds its return value, so no node is made and a graph of the
116
+ // application starts at whatever the root happened to render.
117
+ // Built inside hydrate, not as its argument: a memo runs when it is made, and made out
118
+ // here the root would render before hydration is on, without the key scope the server
119
+ // opened for it. Every key below would then be one level off and nothing adopted by key.
120
+ domHydrate(() => rootOf(App), container);
121
+ // Handlers are now wired (delegated $$listeners attach during the hydration
122
+ // render): replay any events the user fired before hydration.
123
+ replayEvents();
124
+ }
125
+ finally {
126
+ endAppHydration();
127
+ }
128
+ setTimeout(() => {
129
+ setHydrating(false);
130
+ // Late route chunks have had their chance to claim their markup: what nothing claimed
131
+ // is server output the client did not render, or rendered differently.
132
+ const removed = removeUnclaimedKeyed(container);
133
+ if (removed && typeof process !== 'undefined' && process.env?.NODE_ENV !== 'production') {
134
+ console.warn(`[fluixi] hydration: removed ${removed} server element(s) the client did not render. Check for markup that depends on client-only state.`);
135
+ }
136
+ clearHydrationKeys();
137
+ cleanupHydration();
138
+ }, 100);
139
+ }
140
+ else {
141
+ render(rootOf(App), container);
142
+ }
143
+ mountHead(head);
144
+ }
145
+ /**
146
+ * Replay events captured before hydration by the server's eventCaptureScript
147
+ * (window.__FX_REPLAY__). Hydration REUSES the server DOM, so each recorded target
148
+ * is still live: re-dispatch a synthetic event on it so the app's delegated
149
+ * handlers fire. Discrete events only (click/input/change/submit/keydown). No-op
150
+ * when the capture script wasn't emitted (no queue).
151
+ */
152
+ function replayEvents() {
153
+ if (typeof window === 'undefined')
154
+ return;
155
+ const w = window;
156
+ if (typeof w.__FX_REPLAY_STOP__ === 'function')
157
+ w.__FX_REPLAY_STOP__();
158
+ const queue = w.__FX_REPLAY__;
159
+ w.__FX_REPLAY__ = undefined;
160
+ w.__FX_REPLAY_STOP__ = undefined;
161
+ if (!Array.isArray(queue) || queue.length === 0)
162
+ return;
163
+ for (const rec of queue) {
164
+ const target = rec && rec.target;
165
+ // Skip targets dropped by a hydration mismatch (recreated, not reconnected).
166
+ if (!target || target.isConnected === false || typeof target.dispatchEvent !== 'function')
167
+ continue;
168
+ const type = rec.type;
169
+ const ev = type === 'click'
170
+ ? new MouseEvent(type, { bubbles: true, cancelable: true })
171
+ : new Event(type, { bubbles: true, cancelable: true });
172
+ target.dispatchEvent(ev);
173
+ }
174
+ }
@@ -0,0 +1,293 @@
1
+ /*! @fluixi/core v1.0.0-alpha.100 | (c) 2026 Ibrahima Touré and Fluixi contributors | MIT */
2
+ import "./chunk-FDOPDB6Z.mjs";
3
+
4
+ // src/lib/client/index.ts
5
+ import {
6
+ render as domRender,
7
+ hydrate as domHydrate,
8
+ beginAppHydration,
9
+ endAppHydration,
10
+ removeUnclaimedKeyed,
11
+ clearHydrationKeys
12
+ } from "@fluixi/dom";
13
+
14
+ // src/lib/render/versions.ts
15
+ import { registerCoreVersion } from "@fluixi/dom";
16
+
17
+ // src/version.generated.ts
18
+ var VERSION = "1.0.0-alpha.100";
19
+
20
+ // src/lib/render/versions.ts
21
+ import { stampVersions, warnOnVersionSkew, versions } from "@fluixi/dom";
22
+ registerCoreVersion(VERSION);
23
+
24
+ // src/lib/server/hydration.ts
25
+ import { isServer as domIsServer } from "@fluixi/dom";
26
+ var hydrating = false;
27
+ var hydrationDataMap = /* @__PURE__ */ new Map();
28
+ function setHydrating(state) {
29
+ hydrating = state;
30
+ }
31
+ function clearHydrationData() {
32
+ hydrationDataMap.clear();
33
+ }
34
+ function deserializeHydrationData() {
35
+ if (typeof window === "undefined") {
36
+ return false;
37
+ }
38
+ const script = document.getElementById("__FLUIXI_HYDRATION__");
39
+ if (!script || script.getAttribute("type") !== "application/json") {
40
+ return false;
41
+ }
42
+ try {
43
+ const json = script.textContent || "{}";
44
+ const data = JSON.parse(json);
45
+ for (const [key, value] of Object.entries(data)) {
46
+ hydrationDataMap.set(key, value);
47
+ }
48
+ return true;
49
+ } catch (error) {
50
+ console.error("Failed to deserialize hydration data:", error);
51
+ return false;
52
+ }
53
+ }
54
+ function cleanupHydration() {
55
+ if (typeof window === "undefined") {
56
+ return;
57
+ }
58
+ const script = document.getElementById("__FLUIXI_HYDRATION__");
59
+ if (script) {
60
+ script.remove();
61
+ }
62
+ const walker = document.createTreeWalker(
63
+ document.body,
64
+ NodeFilter.SHOW_COMMENT,
65
+ null
66
+ );
67
+ const comments = [];
68
+ let node;
69
+ while (node = walker.nextNode()) {
70
+ const comment = node;
71
+ const text = comment.nodeValue || "";
72
+ if (text.startsWith("#") || text.startsWith("/")) {
73
+ comments.push(comment);
74
+ }
75
+ }
76
+ comments.forEach((comment) => comment.remove());
77
+ clearHydrationData();
78
+ }
79
+ if (typeof window !== "undefined") {
80
+ window.addEventListener("load", () => {
81
+ setTimeout(cleanupHydration, 100);
82
+ });
83
+ }
84
+
85
+ // src/lib/render/index.ts
86
+ import { isServer as isServer3 } from "@fluixi/dom";
87
+ import { createRoot as createRoot2 } from "@fluixi/reactive/signal";
88
+ import {
89
+ isDOMNode,
90
+ delegateEvents,
91
+ insert
92
+ } from "@fluixi/dom";
93
+
94
+ // src/lib/render/component.ts
95
+ import { isServer } from "@fluixi/dom";
96
+ import {
97
+ createComponent as domCreateComponent,
98
+ asComponent
99
+ } from "@fluixi/dom";
100
+ import {
101
+ untrack,
102
+ onCleanup,
103
+ getOwner,
104
+ createEffect,
105
+ createMemo,
106
+ createSignal,
107
+ isSignal,
108
+ batch,
109
+ runWithOwner,
110
+ isOwnerDisposed
111
+ } from "@fluixi/reactive/signal";
112
+ function createComponent(Comp, props) {
113
+ return domCreateComponent(Comp, props);
114
+ }
115
+
116
+ // src/lib/render/suspense.ts
117
+ import {
118
+ createSignal as createSignal2,
119
+ createMemo as createMemo2,
120
+ createEffect as createEffect2,
121
+ createRenderEffect as createRenderEffect2,
122
+ isSignal as isSignal2,
123
+ readChildren,
124
+ useContext as useContext2,
125
+ createContext as createContext2,
126
+ createSuspenseBoundary,
127
+ provideSuspense
128
+ } from "@fluixi/reactive/signal";
129
+ import {
130
+ asSuspense,
131
+ isComponent,
132
+ createComponent as createComponent2,
133
+ runWithoutHydration
134
+ } from "@fluixi/dom";
135
+ function isPromise(value) {
136
+ return !!(value && typeof value === "object" && typeof value.then === "function" || value instanceof Promise);
137
+ }
138
+ var SuspenseListContext = createContext2(void 0, "suspense-list");
139
+ function Suspense(props) {
140
+ return createComponent2(SuspenseImpl, props);
141
+ }
142
+ function SuspenseImpl(props) {
143
+ const boundary = createSuspenseBoundary();
144
+ const listCtx = useContext2(SuspenseListContext);
145
+ const listState = listCtx ? listCtx.register(boundary.inFallback) : void 0;
146
+ function instantiateOnce(val) {
147
+ if (val == null || typeof val === "boolean") return null;
148
+ if (typeof val === "function" && isComponent(val) && !isSignal2(val)) return val();
149
+ return val;
150
+ }
151
+ const fallback = runWithoutHydration(() => instantiateOnce(props.fallback ?? null));
152
+ const children = provideSuspense(boundary, () => readChildren(() => props.children));
153
+ const track = (value, depth) => {
154
+ if (depth > 8) return;
155
+ if (Array.isArray(value)) {
156
+ for (const x of value) track(x, depth + 1);
157
+ } else if (typeof value === "function" && isSignal2(value)) {
158
+ track(value(), depth + 1);
159
+ }
160
+ };
161
+ provideSuspense(boundary, () => {
162
+ createRenderEffect2(() => track(children, 0));
163
+ });
164
+ const [resolved, setResolved] = createSignal2(void 0);
165
+ const childIsPromise = isPromise(children);
166
+ if (childIsPromise) {
167
+ boundary.increment();
168
+ children.then(
169
+ (v) => {
170
+ setResolved(() => v);
171
+ boundary.decrement();
172
+ },
173
+ () => boundary.decrement()
174
+ );
175
+ }
176
+ return createMemo2(() => {
177
+ const showFallback = listState ? listState.showFallback() : boundary.inFallback();
178
+ if (showFallback) return fallback;
179
+ if (childIsPromise) return resolved();
180
+ return children;
181
+ });
182
+ }
183
+ asSuspense(Suspense);
184
+ Object.defineProperty(Suspense, "__suspense", { value: true, enumerable: true });
185
+
186
+ // src/lib/render/deferred.ts
187
+ import { isServer as isServer2 } from "@fluixi/dom";
188
+ import { createMemo as createMemo3, createSignal as createSignal3 } from "@fluixi/reactive/signal";
189
+ import { observeIntersection } from "@fluixi/dom/utils";
190
+
191
+ // src/lib/render/await.ts
192
+ import { createResource as createResource2 } from "@fluixi/reactive/signal";
193
+
194
+ // src/lib/render/index.ts
195
+ function render(code, container, options = {}) {
196
+ delegateEvents(["click", "input", "change", "submit"]);
197
+ if (isServer3()) {
198
+ throw new Error(
199
+ "render() is for client-side only. Use renderToString() on server."
200
+ );
201
+ }
202
+ if (!container) {
203
+ throw new Error("Container element is required");
204
+ }
205
+ let disposer;
206
+ createRoot2((dispose) => {
207
+ disposer = dispose;
208
+ const result = typeof code === "function" ? code() : code;
209
+ container.textContent = "";
210
+ stampVersions(container);
211
+ warnOnVersionSkew();
212
+ insert(container, () => result);
213
+ });
214
+ return () => {
215
+ if (disposer) {
216
+ disposer();
217
+ disposer = void 0;
218
+ }
219
+ };
220
+ }
221
+
222
+ // src/lib/client/index.ts
223
+ import { createMemo as createMemo4 } from "@fluixi/reactive/signal";
224
+ import { createHead, setActiveHead, mountHead, stripHeadMarker } from "@fluixi/head";
225
+ import { hydrate } from "@fluixi/dom";
226
+ function mount(App, container) {
227
+ if (!container) {
228
+ throw new Error("Container element not found for mount()");
229
+ }
230
+ domRender(() => App(), container);
231
+ }
232
+ var rootOf = (App) => createMemo4(() => createComponent(App));
233
+ async function startClient(App, options = {}) {
234
+ const container = typeof options.root === "string" ? document.querySelector(options.root) : options.root ?? document.querySelector("#app");
235
+ if (!container) {
236
+ throw new Error(
237
+ `[Fluixi] Mount container not found: ${options.root ?? "#app"}`
238
+ );
239
+ }
240
+ const hasServerDom = !!document.getElementById("__FLUIXI_HYDRATION__") || !!options.routes && container.firstElementChild != null;
241
+ const shouldHydrate = options.hydrate ?? hasServerDom;
242
+ const head = createHead();
243
+ setActiveHead(head);
244
+ stripHeadMarker(container);
245
+ if (shouldHydrate) {
246
+ beginAppHydration();
247
+ try {
248
+ if (options.routes && options.routes.length) {
249
+ const { preloadRoutes } = await import("./router-4PTBPZLQ.mjs");
250
+ await preloadRoutes(options.routes, window.location.pathname);
251
+ }
252
+ deserializeHydrationData();
253
+ setHydrating(true);
254
+ domHydrate(() => rootOf(App), container);
255
+ replayEvents();
256
+ } finally {
257
+ endAppHydration();
258
+ }
259
+ setTimeout(() => {
260
+ setHydrating(false);
261
+ const removed = removeUnclaimedKeyed(container);
262
+ if (removed && typeof process !== "undefined" && false) {
263
+ console.warn(`[fluixi] hydration: removed ${removed} server element(s) the client did not render. Check for markup that depends on client-only state.`);
264
+ }
265
+ clearHydrationKeys();
266
+ cleanupHydration();
267
+ }, 100);
268
+ } else {
269
+ render(rootOf(App), container);
270
+ }
271
+ mountHead(head);
272
+ }
273
+ function replayEvents() {
274
+ if (typeof window === "undefined") return;
275
+ const w = window;
276
+ if (typeof w.__FX_REPLAY_STOP__ === "function") w.__FX_REPLAY_STOP__();
277
+ const queue = w.__FX_REPLAY__;
278
+ w.__FX_REPLAY__ = void 0;
279
+ w.__FX_REPLAY_STOP__ = void 0;
280
+ if (!Array.isArray(queue) || queue.length === 0) return;
281
+ for (const rec of queue) {
282
+ const target = rec && rec.target;
283
+ if (!target || target.isConnected === false || typeof target.dispatchEvent !== "function") continue;
284
+ const type = rec.type;
285
+ const ev = type === "click" ? new MouseEvent(type, { bubbles: true, cancelable: true }) : new Event(type, { bubbles: true, cancelable: true });
286
+ target.dispatchEvent(ev);
287
+ }
288
+ }
289
+ export {
290
+ hydrate,
291
+ mount,
292
+ startClient
293
+ };