@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,11 +1,10 @@
1
1
  /**
2
- * @fileoverview Fluixi adapter for the framework-agnostic @fluixi/router core.
3
2
  *
4
3
  * Renders the resolved match tree TOP-DOWN. Each layer's component is rendered
5
4
  * inside the PARENT layer's <Outlet/> scope, so a child route inherits whatever
6
5
  * context a parent layout provides. <Outlet/> is reactive but keyed on the child's
7
6
  * component reference, so it only re-renders when the child route at that depth
8
- * actually changes sibling navigation reuses the layout, deeper navigation
7
+ * actually changes: sibling navigation reuses the layout, deeper navigation
9
8
  * leaves shallower layouts untouched.
10
9
  *
11
10
  * No parentGate, no deferred content memo: a child is rendered straight from the
@@ -25,12 +24,26 @@ export interface RouterProps<C = any> {
25
24
  base?: string;
26
25
  history?: HistoryAdapter;
27
26
  /**
28
- * Rendered when the current URL matches no route a component, an element, or any renderable.
27
+ * Rendered when the current URL matches no route, a component, an element, or any renderable.
29
28
  * Defaults to a minimal built-in 404 so an unmatched URL never renders a blank page. For a 404
30
- * that keeps your layout/chrome, add a catch-all file route instead (`[...slug].tsx` `*`).
29
+ * that keeps your layout/chrome, add a catch-all file route instead (`[...slug].tsx` -> `*`).
31
30
  */
32
31
  notFound?: any;
33
32
  }
33
+ /**
34
+ * The router. Matches the current URL against `routes` and renders what matches.
35
+ *
36
+ * Supplies the router context everything below reaches through `useRouter`,
37
+ * `useNavigate` and `Link`, so those only work inside it. `history` defaults to a
38
+ * browser history; pass a memory history for tests or a server render. An unmatched URL
39
+ * renders `notFound`, which defaults to a minimal built-in page so a bad URL is never
40
+ * blank. For a 404 that keeps your layout, add a catch-all file route instead.
41
+ *
42
+ * @example
43
+ * ```ts
44
+ * html`<${Router} routes=${routes} base="/app" />`;
45
+ * ```
46
+ */
34
47
  export declare function Router<C = any>(props: RouterProps<C>): any;
35
48
  /** Renders this layout's child route, inside this layout's context. */
36
49
  export declare function Outlet(): any;
@@ -39,6 +52,14 @@ export declare function Redirect(props: {
39
52
  to: string;
40
53
  replace?: boolean;
41
54
  }): null;
55
+ /**
56
+ * The router context: the router itself, the current match, and the location.
57
+ *
58
+ * Safe to call during a server render, where a detached context yields a no-op stub
59
+ * rather than throwing, since an SSR pass has nowhere to navigate to. On the client a
60
+ * missing router is genuine misuse and throws, because the alternative is a component
61
+ * that silently never navigates.
62
+ */
42
63
  export declare function useRouter(): RouterCtxValue;
43
64
  /**
44
65
  * Reactive merged params across all matched layers, as an accessor. Deep-equal
@@ -50,7 +71,7 @@ export declare function useParams<T extends Record<string, string> = Record<stri
50
71
  export declare function useLevelParams(): Record<string, string>;
51
72
  /**
52
73
  * Reactive accessor for a single route param. Default `===` equality on the
53
- * string value, so it only re-triggers when THIS key changes not when other
74
+ * string value, so it only re-triggers when this key changes, not when other
54
75
  * params at the same level change.
55
76
  */
56
77
  export declare function useParam(key: string): () => string | undefined;
@@ -99,7 +120,7 @@ export interface LinkNavigationOptions {
99
120
  replace?: boolean;
100
121
  /**
101
122
  * Called with the resolved URL before navigating. Return false to leave the click
102
- * alone for a section of the app that must load as a document (a different
123
+ * alone, for a section of the app that must load as a document (a different
103
124
  * bundle, a server-rendered admin area, a file route).
104
125
  */
105
126
  shouldNavigate?: (url: URL, anchor: HTMLAnchorElement) => boolean;
@@ -117,16 +138,32 @@ export interface LinkNavigationOptions {
117
138
  * <article onClick={onClick} innerHTML={doc.html} />
118
139
  * ```
119
140
  *
120
- * The anchors stay real anchors middle-click, right-click open in new tab, "copy
141
+ * The anchors stay real anchors: middle-click, right-click -> open in new tab, "copy
121
142
  * link address" and crawlers all keep working, because the element is untouched and only
122
143
  * a plain left-click is intercepted.
123
144
  *
124
145
  * Left alone: modified clicks, anything but the primary button, an already-prevented
125
146
  * event, `target`, `download`, `rel="external"`, a non-http scheme (`mailto:`, `tel:`),
126
- * another origin, and a hash pointing inside the current page that last one is the
147
+ * another origin, and a hash pointing inside the current page, that last one is the
127
148
  * browser's scroll, and hijacking it breaks in-page anchors.
128
149
  */
129
150
  export declare function useLinkNavigation(options?: LinkNavigationOptions): (event: MouseEvent) => void;
151
+ /**
152
+ * A function that navigates, for use outside a `Link`.
153
+ *
154
+ * Reach for it after an action rather than for a plain link: a form that redirects on
155
+ * success, a guard that bounces an unauthenticated visitor. Prefer `Link` for anything a
156
+ * visitor clicks, since an anchor is what middle-click, copy-link and a crawler expect.
157
+ *
158
+ * Navigation is a no-op during a server render, for the reason `useRouter` explains.
159
+ *
160
+ * @example
161
+ * ```ts
162
+ * const navigate = useNavigate();
163
+ * await save(form);
164
+ * navigate(`/posts/${id}`, { replace: true });
165
+ * ```
166
+ */
130
167
  export declare function useNavigate(): (to: string, options?: NavigateOptions) => void;
131
168
  /**
132
169
  * The resolved data for the nearest route that declared a `data` loader. Always
@@ -147,13 +184,28 @@ export interface LinkProps {
147
184
  slot?: string;
148
185
  children?: any;
149
186
  /**
150
- * Everything else is forwarded onto the `<a>` id, style, title, aria-*,
187
+ * Everything else is forwarded onto the `<a>`: id, style, title, aria-*,
151
188
  * data-*, event handlers. Typed openly because the forwarding is
152
189
  * allow-by-default: a prop this interface forgot still reaches the DOM, and
153
190
  * refusing it here would only mean the type disagreeing with the runtime.
154
191
  */
155
192
  [key: string]: unknown;
156
193
  }
194
+ /**
195
+ * An anchor that navigates without a full page load.
196
+ *
197
+ * Renders a real `<a href>`, so middle-click, copy-link, and a crawler all behave. A
198
+ * plain left click is intercepted and routed instead.
199
+ *
200
+ * Active state defaults to the current pathname matching `href`, and `activeClass` is
201
+ * added while it holds. Override `active` when a section link should stay lit for its
202
+ * children.
203
+ *
204
+ * @example
205
+ * ```ts
206
+ * html`<${Link} href="/about" activeClass="current">About</${Link}>`;
207
+ * ```
208
+ */
157
209
  export declare function Link(props: LinkProps): any;
158
210
  /** Alias for {@link Link}. */
159
211
  export declare const A: typeof Link;
@@ -180,7 +232,7 @@ export interface FormProps {
180
232
  export declare function Form(props: FormProps): any;
181
233
  /**
182
234
  * Download the lazy component chunks for the route(s) matching `pathname` and resolve when
183
- * they're all loaded. Await this BEFORE hydrating: once each matched lazy file-route is
235
+ * they're all loaded. Await this before hydrating: once each matched lazy file-route is
184
236
  * resolved it renders synchronously on the first pass (no Suspense fallback, no late
185
237
  * re-render), so hydration adopts the server DOM in place instead of building a duplicate
186
238
  * subtree next to it. No-op for routes with no lazy components. Safe to call when the URL
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/lib/router/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/lib/router/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAqBH,OAAO,EAAO,KAAK,SAAS,EAAE,MAAM,sBAAsB,CAAC;AAC3D,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAC;AAG3D,OAAO,EAKL,KAAK,eAAe,EAEpB,KAAK,MAAM,IAAI,UAAU,EACzB,KAAK,cAAc,EACnB,KAAK,cAAc,EACnB,KAAK,eAAe,EACrB,MAAM,gBAAgB,CAAC;AAIxB,UAAU,cAAc;IACtB,MAAM,EAAE,UAAU,CAAC,GAAG,CAAC,CAAC;IACxB,QAAQ,EAAE,MAAM,cAAc,CAAC;IAC/B,MAAM,EAAE,MAAM,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CACtC;AA8JD,MAAM,WAAW,WAAW,CAAC,CAAC,GAAG,GAAG;IAClC,MAAM,EAAE,eAAe,CAAC,CAAC,CAAC,EAAE,CAAC;IAC7B,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,OAAO,CAAC,EAAE,cAAc,CAAC;IACzB;;;;OAIG;IACH,QAAQ,CAAC,EAAE,GAAG,CAAC;CAChB;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,MAAM,CAAC,CAAC,GAAG,GAAG,EAAE,KAAK,EAAE,WAAW,CAAC,CAAC,CAAC,OAgDpD;AAID,uEAAuE;AACvE,wBAAgB,MAAM,QAIrB;AAED,uEAAuE;AACvE,wBAAgB,QAAQ,CAAC,KAAK,EAAE;IAAE,EAAE,EAAE,MAAM,CAAC;IAAC,OAAO,CAAC,EAAE,OAAO,CAAA;CAAE,QAchE;AAkBD;;;;;;;GAOG;AACH,wBAAgB,SAAS,IAAI,cAAc,CAO1C;AAED;;;;GAIG;AACH,wBAAgB,SAAS,CACvB,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,KACtD,MAAM,CAAC,CAKX;AAED,sDAAsD;AACtD,wBAAgB,cAAc,IAAI,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAEvD;AAED;;;;GAIG;AACH,wBAAgB,QAAQ,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,MAAM,GAAG,SAAS,CAG9D;AAED;;;;;;GAMG;AACH,wBAAgB,gBAAgB,CAAC,CAAC,EAChC,QAAQ,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,KAAK,CAAC,EAC/C,MAAM,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,KAAK,OAAO,GAC/B,MAAM,CAAC,CAOT;AAED;;;GAGG;AACH,wBAAgB,QAAQ,CACtB,IAAI,EAAE,CAAC,MAAM,MAAM,CAAC,GAAG,MAAM,GAC5B,MAAM;IAAE,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,GAAG,IAAI,CAK/D;AAED;;;;GAIG;AACH,wBAAgB,eAAe,IAAI,SAAS;IAC1C,MAAM,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC;IAC5B,CAAC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC,EAAE,OAAO,CAAC,EAAE,eAAe,KAAK,IAAI;CACzE,CAmBA;AAED;;;;;;;;GAQG;AACH,wBAAgB,MAAM,CAAC,CAAC,EAAE,CAAC,SAAS,MAAM,GAAG,KAAK,EAChD,MAAM,EAAE,MAAM,CAAC,EACf,GAAG,CAAC,EAAE,CAAC,GACN,MAAM,WAAW,CAAC,CAAC,CAAC,SAAS,IAAI,GAAG,CAAC,GAAG,SAAS,CAAC,CAAC,EAAE,CAAC,CAAC,CAUzD;AAED;;;GAGG;AACH,wBAAgB,WAAW,IAAI,cAAc,CAS5C;AAED,MAAM,WAAW,qBAAqB;IACpC,sEAAsE;IACtE,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB;;;;OAIG;IACH,cAAc,CAAC,EAAE,CAAC,GAAG,EAAE,GAAG,EAAE,MAAM,EAAE,iBAAiB,KAAK,OAAO,CAAC;CACnE;AAED;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,wBAAgB,iBAAiB,CAC/B,OAAO,GAAE,qBAA0B,GAClC,CAAC,KAAK,EAAE,UAAU,KAAK,IAAI,CAyB7B;AAED;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,WAAW,IAAI,CAAC,EAAE,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,eAAe,KAAK,IAAI,CAM7E;AAED;;;;GAIG;AACH,wBAAgB,YAAY,CAAC,CAAC,GAAG,GAAG,KAAK,MAAM,CAAC,GAAG,SAAS,CAG3D;AAID,KAAK,aAAa,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC;AAItC,MAAM,WAAW,SAAS;IACxB,IAAI,EAAE,aAAa,CAAC,MAAM,CAAC,CAAC;IAC5B,OAAO,CAAC,EAAE,aAAa,CAAC,OAAO,CAAC,CAAC;IACjC,oEAAoE;IACpE,MAAM,CAAC,EAAE,aAAa,CAAC,OAAO,CAAC,CAAC;IAChC,KAAK,CAAC,EAAE,aAAa,CAAC,MAAM,CAAC,CAAC;IAC9B,SAAS,CAAC,EAAE,aAAa,CAAC,MAAM,CAAC,CAAC;IAClC,4CAA4C;IAC5C,WAAW,CAAC,EAAE,aAAa,CAAC,MAAM,CAAC,CAAC;IACpC,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,QAAQ,CAAC,EAAE,GAAG,CAAC;IACf;;;;;OAKG;IACH,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACxB;AAcD;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,IAAI,CAAC,KAAK,EAAE,SAAS,OA6DpC;AAED,8BAA8B;AAC9B,eAAO,MAAM,CAAC,aAAO,CAAC;AAEtB,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,WAAW,CAAC;AAExC,MAAM,WAAW,SAAS;IACxB,kFAAkF;IAClF,MAAM,EAAE,MAAM,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC;IACzB,iCAAiC;IACjC,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,GAAG,CAAC;IACf,CAAC,GAAG,EAAE,MAAM,GAAG,GAAG,CAAC;CACpB;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,IAAI,CAAC,KAAK,EAAE,SAAS,OA0CpC;AAID;;;;;;;GAOG;AACH,wBAAsB,aAAa,CAAC,CAAC,GAAG,GAAG,EACzC,MAAM,EAAE,eAAe,CAAC,CAAC,CAAC,EAAE,EAC5B,QAAQ,EAAE,MAAM,GACf,OAAO,CAAC,IAAI,CAAC,CASf;AAID,OAAO,EACL,mBAAmB,EACnB,oBAAoB,EACpB,WAAW,EACX,SAAS,GACV,MAAM,gBAAgB,CAAC;AACxB,YAAY,EACV,eAAe,EACf,UAAU,EACV,YAAY,EACZ,cAAc,EACd,eAAe,EACf,cAAc,GACf,MAAM,gBAAgB,CAAC;AAIxB,OAAO,EACL,KAAK,EACL,MAAM,EACN,UAAU,EACV,WAAW,EACX,aAAa,EACb,SAAS,GACV,MAAM,WAAW,CAAC;AACnB,YAAY,EACV,aAAa,EACb,aAAa,EACb,MAAM,EACN,UAAU,EACV,OAAO,GACR,MAAM,WAAW,CAAC;AACnB,OAAO,EAAE,IAAI,EAAE,MAAM,mBAAmB,CAAC;AAEzC,OAAO,EAAE,YAAY,EAAE,MAAM,yBAAyB,CAAC"}
@@ -1,11 +1,10 @@
1
1
  /**
2
- * @fileoverview Fluixi adapter for the framework-agnostic @fluixi/router core.
3
2
  *
4
3
  * Renders the resolved match tree TOP-DOWN. Each layer's component is rendered
5
4
  * inside the PARENT layer's <Outlet/> scope, so a child route inherits whatever
6
5
  * context a parent layout provides. <Outlet/> is reactive but keyed on the child's
7
6
  * component reference, so it only re-renders when the child route at that depth
8
- * actually changes sibling navigation reuses the layout, deeper navigation
7
+ * actually changes: sibling navigation reuses the layout, deeper navigation
9
8
  * leaves shallower layouts untouched.
10
9
  *
11
10
  * No parentGate, no deferred content memo: a child is rendered straight from the
@@ -15,7 +14,7 @@
15
14
  import { createSignal, createMemo, createResource, createEffect, getOwner, onCleanup, untrack, } from '@fluixi/reactive/signal';
16
15
  import { insert, createComponent, createNativeElement, setAttribute, } from '@fluixi/dom';
17
16
  // Reactive context (not fluixi createProvider, which destructures children
18
- // eagerly) so a `get children()` getter renders AFTER the context is stamped.
17
+ // eagerly) so a `get children()` getter renders after the context is stamped.
19
18
  import { createContext, useContext } from '@fluixi/reactive/signal';
20
19
  import { get } from '@fluixi/utils/object';
21
20
  import { deepEqual } from '@fluixi/utils/compare';
@@ -59,14 +58,14 @@ function renderLayer(m, depth, base) {
59
58
  });
60
59
  if (!data)
61
60
  return buildPage();
62
- // Gate on the data being resolved like the old router so the page reads
61
+ // Gate on the data being resolved, like the old router, so the page reads
63
62
  // ready data (rd() returns the value, not a thrown promise) and works without a
64
63
  // Suspense boundary. Signal-gated (`ready` only flips when loading actually
65
64
  // changes) so navigation re-renders don't re-run this and rebuild the page.
66
65
  const res = data;
67
66
  const isLoading = () => res.loading;
68
67
  // untrack the initial read so the enclosing render memo doesn't subscribe to the
69
- // resource state (that would re-run renderLayer and recreate the resource a loop).
68
+ // resource state (that would re-run renderLayer and recreate the resource, a loop).
70
69
  const [ready, setReady] = createSignal(untrack(() => !isLoading()));
71
70
  createEffect(() => setReady(!isLoading()));
72
71
  return createMemo(() => (ready() ? buildPage() : null));
@@ -83,7 +82,7 @@ function renderChild(ctx) {
83
82
  // signal write (no value check), so a memo that read `matched` would re-run on
84
83
  // every navigation and re-render the child. A signal only notifies when its value
85
84
  // actually changes, so the render memo below re-runs only when the route at this
86
- // depth changes sibling navigation reuses the layout, deeper navigation leaves
85
+ // depth changes: sibling navigation reuses the layout, deeper navigation leaves
87
86
  // this level untouched. The child is rendered INLINE (no detached createRoot), so
88
87
  // it stays connected to the Suspense / context owner chain.
89
88
  const [childComp, setChildComp] = createSignal(untrack(() => ctx.matched()[childIdx]?.component));
@@ -94,8 +93,8 @@ function renderChild(ctx) {
94
93
  return createMemo(() => {
95
94
  const component = childComp();
96
95
  if (!component) {
97
- // No route at this depth. At the ROOT (the only ctx carrying `notFound`) that means the
98
- // URL matched nothing render the not-found fallback instead of a blank page. Nested
96
+ // No route at this depth. At the root (the only ctx carrying `notFound`) that means the
97
+ // URL matched nothing: render the not-found fallback instead of a blank page. Nested
99
98
  // Outlets have no `notFound`, so they stay null (a missing child is just an empty Outlet).
100
99
  return ctx.notFound ? ctx.notFound() : null;
101
100
  }
@@ -110,8 +109,8 @@ function renderChild(ctx) {
110
109
  /**
111
110
  * Resolve the Router's `notFound` prop to a renderable view. A component is instantiated; an
112
111
  * element/value is returned as-is; when omitted, a minimal built-in 404 keeps the page from
113
- * rendering blank. Prefer a catch-all file route (`[...slug].tsx` `*`) when the 404 should sit
114
- * inside your layout this prop is the app-level fallback for an otherwise unmatched URL.
112
+ * rendering blank. Prefer a catch-all file route (`[...slug].tsx` -> `*`) when the 404 should sit
113
+ * inside your layout, this prop is the app-level fallback for an otherwise unmatched URL.
115
114
  */
116
115
  function renderNotFound(notFound) {
117
116
  if (notFound == null)
@@ -135,6 +134,20 @@ function buildDefaultNotFound() {
135
134
  el.appendChild(p);
136
135
  return el;
137
136
  }
137
+ /**
138
+ * The router. Matches the current URL against `routes` and renders what matches.
139
+ *
140
+ * Supplies the router context everything below reaches through `useRouter`,
141
+ * `useNavigate` and `Link`, so those only work inside it. `history` defaults to a
142
+ * browser history; pass a memory history for tests or a server render. An unmatched URL
143
+ * renders `notFound`, which defaults to a minimal built-in page so a bad URL is never
144
+ * blank. For a 404 that keeps your layout, add a catch-all file route instead.
145
+ *
146
+ * @example
147
+ * ```ts
148
+ * html`<${Router} routes=${routes} base="/app" />`;
149
+ * ```
150
+ */
138
151
  export function Router(props) {
139
152
  const history = props.history ?? createBrowserHistory();
140
153
  const router = createCoreRouter({
@@ -148,7 +161,7 @@ export function Router(props) {
148
161
  unsub();
149
162
  router.destroy();
150
163
  });
151
- // Drop pathless layers (no component) their params still appear in the merged
164
+ // Drop pathless layers (no component), their params still appear in the merged
152
165
  // params exposed by RouterContext.
153
166
  const matched = createMemo(() => (state().match?.matched ?? []).filter((m) => m.component));
154
167
  const ctx = {
@@ -162,12 +175,12 @@ export function Router(props) {
162
175
  matched,
163
176
  params: ctx.params,
164
177
  location: ctx.location,
165
- // Only the root carries this renderChild shows it when the URL matched nothing.
178
+ // Only the root carries this: renderChild shows it when the URL matched nothing.
166
179
  notFound: () => renderNotFound(props.notFound),
167
180
  };
168
181
  // Build the root view once, lazily, inside the provider's children getter: the
169
182
  // getter must run in the provider scope (so components can useRouter), but the
170
- // reactive provider re-invokes it whenever content changes caching keeps the
183
+ // reactive provider re-invokes it whenever content changes: caching keeps the
171
184
  // root chain from being rebuilt on every navigation.
172
185
  let rootView;
173
186
  return RouterContext.Provider({
@@ -190,7 +203,7 @@ export function Redirect(props) {
190
203
  const ctx = useContext(RouterContext);
191
204
  // Nothing to do without a router, and nothing to navigate on the server.
192
205
  if (ctx && typeof window !== 'undefined') {
193
- // Navigate AFTER the current render commits. Navigating during render (an effect
206
+ // Navigate after the current render commits. Navigating during render (an effect
194
207
  // running mid-render) updated the location but the route never re-matched, so the
195
208
  // target never showed. Guard against firing if this Redirect is torn down first.
196
209
  let cancelled = false;
@@ -204,9 +217,9 @@ export function Redirect(props) {
204
217
  }
205
218
  // ─── Hooks ──────────────────────────────────────────────────────────────────
206
219
  // Safe stub returned by useRouter on the SERVER when no RouterContext is on the owner
207
- // chain. That happens during a late/detached re-render e.g. a slow data resource
208
- // settling AFTER renderToStringAsync already serialized the response and disposed the
209
- // root whose output is discarded. Returning this (instead of throwing) prevents a
220
+ // chain. That happens during a late/detached re-render: e.g. a slow data resource
221
+ // settling after renderToStringAsync already serialized the response and disposed the
222
+ // root: whose output is discarded. Returning this (instead of throwing) prevents a
210
223
  // floating rejection that crashes the dev server / shows an error overlay seconds
211
224
  // after the page already rendered.
212
225
  const _ssrRouterStub = {
@@ -214,12 +227,20 @@ const _ssrRouterStub = {
214
227
  location: () => ({ pathname: '', search: '', hash: '', query: {} }),
215
228
  params: () => ({}),
216
229
  };
230
+ /**
231
+ * The router context: the router itself, the current match, and the location.
232
+ *
233
+ * Safe to call during a server render, where a detached context yields a no-op stub
234
+ * rather than throwing, since an SSR pass has nowhere to navigate to. On the client a
235
+ * missing router is genuine misuse and throws, because the alternative is a component
236
+ * that silently never navigates.
237
+ */
217
238
  export function useRouter() {
218
239
  const ctx = useContext(RouterContext);
219
240
  if (ctx)
220
241
  return ctx;
221
242
  // On the server, degrade to a no-op stub (see above). On the client, a missing
222
- // router is genuine misuse throw.
243
+ // router is genuine misuse: throw.
223
244
  if (typeof window === 'undefined')
224
245
  return _ssrRouterStub;
225
246
  throw new Error('[router] useRouter must be used within <Router>');
@@ -241,7 +262,7 @@ export function useLevelParams() {
241
262
  }
242
263
  /**
243
264
  * Reactive accessor for a single route param. Default `===` equality on the
244
- * string value, so it only re-triggers when THIS key changes not when other
265
+ * string value, so it only re-triggers when this key changes, not when other
245
266
  * params at the same level change.
246
267
  */
247
268
  export function useParam(key) {
@@ -331,13 +352,13 @@ export function useLocation() {
331
352
  * <article onClick={onClick} innerHTML={doc.html} />
332
353
  * ```
333
354
  *
334
- * The anchors stay real anchors middle-click, right-click open in new tab, "copy
355
+ * The anchors stay real anchors: middle-click, right-click -> open in new tab, "copy
335
356
  * link address" and crawlers all keep working, because the element is untouched and only
336
357
  * a plain left-click is intercepted.
337
358
  *
338
359
  * Left alone: modified clicks, anything but the primary button, an already-prevented
339
360
  * event, `target`, `download`, `rel="external"`, a non-http scheme (`mailto:`, `tel:`),
340
- * another origin, and a hash pointing inside the current page that last one is the
361
+ * another origin, and a hash pointing inside the current page, that last one is the
341
362
  * browser's scroll, and hijacking it breaks in-page anchors.
342
363
  */
343
364
  export function useLinkNavigation(options = {}) {
@@ -372,6 +393,22 @@ export function useLinkNavigation(options = {}) {
372
393
  ctx.router.navigate(url.pathname + url.search + url.hash, { replace: options.replace });
373
394
  };
374
395
  }
396
+ /**
397
+ * A function that navigates, for use outside a `Link`.
398
+ *
399
+ * Reach for it after an action rather than for a plain link: a form that redirects on
400
+ * success, a guard that bounces an unauthenticated visitor. Prefer `Link` for anything a
401
+ * visitor clicks, since an anchor is what middle-click, copy-link and a crawler expect.
402
+ *
403
+ * Navigation is a no-op during a server render, for the reason `useRouter` explains.
404
+ *
405
+ * @example
406
+ * ```ts
407
+ * const navigate = useNavigate();
408
+ * await save(form);
409
+ * navigate(`/posts/${id}`, { replace: true });
410
+ * ```
411
+ */
375
412
  export function useNavigate() {
376
413
  // useRouter is SSR-safe (returns a no-op stub on the server when the context is
377
414
  // detached), so navigation degrades to a no-op during SSR and only throws on
@@ -400,18 +437,33 @@ const LINK_OWN_PROPS = new Set([
400
437
  'replace',
401
438
  'children',
402
439
  ]);
440
+ /**
441
+ * An anchor that navigates without a full page load.
442
+ *
443
+ * Renders a real `<a href>`, so middle-click, copy-link, and a crawler all behave. A
444
+ * plain left click is intercepted and routed instead.
445
+ *
446
+ * Active state defaults to the current pathname matching `href`, and `activeClass` is
447
+ * added while it holds. Override `active` when a section link should stay lit for its
448
+ * children.
449
+ *
450
+ * @example
451
+ * ```ts
452
+ * html`<${Link} href="/about" activeClass="current">About</${Link}>`;
453
+ * ```
454
+ */
403
455
  export function Link(props) {
404
456
  const ctx = useContext(RouterContext);
405
457
  const navigate = () => ctx?.router.navigate(read(props.href) ?? '', { replace: read(props.replace) });
406
- // createNativeElement branches on isServer() a real ServerNode <a> (serialized as a true
458
+ // createNativeElement branches on isServer() -> a real ServerNode <a> (serialized as a true
407
459
  // element, not an escaped string) on the server, a real DOM <a> on the client.
408
460
  const a = createNativeElement('a');
409
461
  setAttribute(a, 'href', read(props.href) ?? '');
410
462
  if (props.slot)
411
463
  setAttribute(a, 'slot', read(props.slot));
412
- // Forward any other author attributes (data-*, aria-*, style, id, title, role, )
464
+ // Forward any other author attributes (data-*, aria-*, style, id, title, role, ...)
413
465
  // onto the <a>, the way <Form> does. Without this a component composed via
414
- // `as={Link}` (polymorphic) silently loses its styling hooks e.g. @fluixi-ui
466
+ // `as={Link}` (polymorphic) silently loses its styling hooks: e.g. @fluixi-ui
415
467
  // parts carry `data-*` slots + inline styles that would otherwise be dropped, so
416
468
  // the element renders unstyled. Own-props handled elsewhere are skipped:
417
469
  // href/slot above, class/className/active/activeClass in the effect, and
@@ -419,7 +471,7 @@ export function Link(props) {
419
471
  // Keys, not entries: `Object.entries` reads every prop, and `children` is a getter
420
472
  // that builds fresh nodes per access. Under hydration that discarded first build
421
473
  // consumes the server's nodes, so the real read below produced a second copy of
422
- // them a duplicated logo and pager on every prerendered page.
474
+ // them, a duplicated logo and pager on every prerendered page.
423
475
  for (const k of Object.keys(props)) {
424
476
  if (LINK_OWN_PROPS.has(k))
425
477
  continue;
@@ -444,7 +496,7 @@ export function Link(props) {
444
496
  setAttribute(a, 'class', base);
445
497
  }
446
498
  // Client only: keep href + active class in sync with reactive props / location.
447
- // (Skipped on the server `a` is a ServerNode without these DOM setters; the static
499
+ // (Skipped on the server: `a` is a ServerNode without these DOM setters; the static
448
500
  // href/class were set above.)
449
501
  if (typeof a.addEventListener === 'function') {
450
502
  createEffect(() => {
@@ -476,18 +528,18 @@ export const A = Link;
476
528
  */
477
529
  export function Form(props) {
478
530
  const action = props.action;
479
- const cls = (props.className ?? props.class); // compiler passes classclassName
531
+ const cls = (props.className ?? props.class); // compiler passes class -> className
480
532
  const url = action.url ?? '';
481
533
  // createNativeElement/setAttribute branch on isServer(), so this builds a real ServerNode
482
- // <form> on the server (serialized as a true element, NOT an escaped string) and a real
483
- // DOM <form> on the client hydration reuses the same element.
534
+ // <form> on the server (serialized as a true element, not an escaped string) and a real
535
+ // DOM <form> on the client: hydration reuses the same element.
484
536
  const form = createNativeElement('form');
485
537
  setAttribute(form, 'method', 'post');
486
538
  if (url)
487
539
  setAttribute(form, 'action', url);
488
540
  if (cls)
489
541
  setAttribute(form, 'class', cls);
490
- // Keys, not entries same reason as Link: reading `children` here would build its
542
+ // Keys, not entries, same reason as Link: reading `children` here would build its
491
543
  // nodes once and throw them away.
492
544
  for (const k of Object.keys(props)) {
493
545
  if (k === 'action' || k === 'children' || k === 'class' || k === 'className')
@@ -513,7 +565,7 @@ export function Form(props) {
513
565
  }
514
566
  // Read children ONCE: the compiler emits `get children()` as a getter that builds fresh
515
567
  // nodes on every access, so reading it twice (here + the null check) created a duplicate
516
- // set under hydration that meant two <input>s in the form.
568
+ // set: under hydration that meant two <input>s in the form.
517
569
  const children = props.children;
518
570
  if (children != null)
519
571
  insert(form, children);
@@ -522,7 +574,7 @@ export function Form(props) {
522
574
  // ─── Hydration preload ───────────────────────────────────────────────────────────
523
575
  /**
524
576
  * Download the lazy component chunks for the route(s) matching `pathname` and resolve when
525
- * they're all loaded. Await this BEFORE hydrating: once each matched lazy file-route is
577
+ * they're all loaded. Await this before hydrating: once each matched lazy file-route is
526
578
  * resolved it renders synchronously on the first pass (no Suspense fallback, no late
527
579
  * re-render), so hydration adopts the server DOM in place instead of building a duplicate
528
580
  * subtree next to it. No-op for routes with no lazy components. Safe to call when the URL
@@ -542,7 +594,7 @@ export async function preloadRoutes(routes, pathname) {
542
594
  }
543
595
  // ─── Re-exports ────────────────────────────────────────────────────────────────
544
596
  export { createMemoryHistory, createBrowserHistory, matchRoutes, matchPath, } from '@fluixi/router';
545
- // Action/cache/lazy layer is orthogonal to routing re-export so a route file can
597
+ // Action/cache/lazy layer is orthogonal to routing: re-export so a route file can
546
598
  // swap its import path wholesale. (Routing hooks above are the router ones.)
547
599
  export { cache, action, revalidate, createAsync, useSubmission, useAction, } from './data.js';
548
600
  export { lazy } from '../render/lazy.js';