@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,67 @@
1
- "use strict";var d=Object.defineProperty;var u=Object.getOwnPropertyDescriptor;var l=Object.getOwnPropertyNames;var y=Object.prototype.hasOwnProperty;var C=(e,n)=>{for(var r in n)d(e,r,{get:n[r],enumerable:!0})},P=(e,n,r,a)=>{if(n&&typeof n=="object"||typeof n=="function")for(let o of l(n))!y.call(e,o)&&o!==r&&d(e,o,{get:()=>n[o],enumerable:!(a=u(n,o))||a.enumerable});return e};var z=e=>P(d({},"__esModule",{value:!0}),e);var h={};C(h,{lazy:()=>T});module.exports=z(h);var m=require("@fluixi/dom"),i=require("@fluixi/reactive/signal");function c(e){if(e!=null&&(typeof e=="object"||typeof e=="function"))try{e.$lazy=!0}catch{}return e}function T(e,n){let r,a,o;function f(){return a||(a=e().then(p=>r=p.default)),a}n?.preload&&f();let s=(p=>{if(r){let t=r;return c((0,i.untrack)(()=>t(p)))}if(!o){let[t]=(0,i.createResource)(()=>f(),{transport:!1});if(o=t,t.error)throw t.error}return(0,i.createMemo)(()=>{let t=o();return t?c((0,m.createComponent)(t,p)):void 0})});return s.preload=()=>f().then(()=>{}),s.$lazy=!0,s.loader=e,s}
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/render/lazy.ts
21
+ var lazy_exports = {};
22
+ __export(lazy_exports, {
23
+ lazy: () => lazy
24
+ });
25
+ module.exports = __toCommonJS(lazy_exports);
26
+ var import_dom = require("@fluixi/dom");
27
+ var import_signal = require("@fluixi/reactive/signal");
28
+ function fromChunk(value) {
29
+ if (value != null && (typeof value === "object" || typeof value === "function")) {
30
+ try {
31
+ value["$lazy"] = true;
32
+ } catch {
33
+ }
34
+ }
35
+ return value;
36
+ }
37
+ function lazy(loader, options) {
38
+ let resolved;
39
+ let promise;
40
+ let component;
41
+ function load() {
42
+ if (!promise) {
43
+ promise = loader().then((mod) => resolved = mod.default);
44
+ }
45
+ return promise;
46
+ }
47
+ if (options?.preload) load();
48
+ const LazyWrapper = ((props) => {
49
+ if (resolved) {
50
+ const C = resolved;
51
+ return fromChunk((0, import_signal.untrack)(() => C(props)));
52
+ }
53
+ if (!component) {
54
+ const [resource] = (0, import_signal.createResource)(() => load(), { transport: false });
55
+ component = resource;
56
+ if (resource.error) throw resource.error;
57
+ }
58
+ return (0, import_signal.createMemo)(() => {
59
+ const C = component();
60
+ return C ? fromChunk((0, import_dom.createComponent)(C, props)) : void 0;
61
+ });
62
+ });
63
+ LazyWrapper.preload = () => load().then(() => void 0);
64
+ LazyWrapper.$lazy = true;
65
+ LazyWrapper.loader = loader;
66
+ return LazyWrapper;
67
+ }
@@ -5,7 +5,7 @@
5
5
  * 1. `comp` signal is shared across all instances of this lazy component (module-level).
6
6
  * 2. `createResource` at the component level registers the load promise with the
7
7
  * nearest Suspense boundary (trackPromise / resource.loading).
8
- * 3. A pure `createMemo` reads `comp()` undefined while loading (Suspense shows
8
+ * 3. A pure `createMemo` reads `comp()`: undefined while loading (Suspense shows
9
9
  * fallback), the rendered component once loaded.
10
10
  * 4. `preload()` is exposed so routes / link hover handlers can start the download
11
11
  * before the component is rendered.
@@ -20,6 +20,27 @@ export interface LazyOptions {
20
20
  /** If true, start loading immediately when lazy() is called */
21
21
  preload?: boolean;
22
22
  }
23
+ /**
24
+ * Defer a component to its own chunk, loaded the first time it renders.
25
+ *
26
+ * `loader` is a dynamic import, and its `default` export is the component. The returned
27
+ * function stands in for it and carries `preload()`, which starts the import without
28
+ * rendering anything. File routing uses that: `startClient` preloads the matched route
29
+ * before hydrating.
30
+ *
31
+ * Preloading is what keeps hydration intact. If the module has already resolved by the
32
+ * time this renders, the component renders synchronously on the first pass, so it adopts
33
+ * the server's DOM in place. On a cold client navigation it goes through a resource
34
+ * instead, suspends, and a `Suspense` boundary above it shows the fallback.
35
+ *
36
+ * @example
37
+ * ```ts
38
+ * const Settings = lazy(() => import('./Settings.js'));
39
+ *
40
+ * // somewhere that knows the route is next
41
+ * void Settings.preload();
42
+ * ```
43
+ */
23
44
  export declare function lazy<T extends (...args: any[]) => any>(loader: () => Promise<{
24
45
  default: T;
25
46
  }>, options?: LazyOptions): T & {
@@ -1 +1 @@
1
- {"version":3,"file":"lazy.d.ts","sourceRoot":"","sources":["../../../../src/lib/render/lazy.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,EAAE,SAAS,EAAE,cAAc,EAAmB,MAAM,aAAa,CAAC;AAUzE,MAAM,MAAM,aAAa,CAAC,CAAC,GAAG,cAAc,IAAI,MAAM,OAAO,CAAC;IAC5D,OAAO,EAAE,SAAS,CAAC,CAAC,CAAC,CAAC;CACvB,CAAC,CAAC;AAEH,MAAM,WAAW,WAAW;IAC1B,4CAA4C;IAC5C,QAAQ,CAAC,EAAE,GAAG,CAAC;IACf,+DAA+D;IAC/D,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB;AAmBD,wBAAgB,IAAI,CAAC,CAAC,SAAS,CAAC,GAAG,IAAI,EAAE,GAAG,EAAE,KAAK,GAAG,EACpD,MAAM,EAAE,MAAM,OAAO,CAAC;IAAE,OAAO,EAAE,CAAC,CAAA;CAAE,CAAC,EACrC,OAAO,CAAC,EAAE,WAAW,GACpB,CAAC,GAAG;IAAE,OAAO,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAA;CAAE,CA2DtC"}
1
+ {"version":3,"file":"lazy.d.ts","sourceRoot":"","sources":["../../../../src/lib/render/lazy.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,EAAE,SAAS,EAAE,cAAc,EAAmB,MAAM,aAAa,CAAC;AAUzE,MAAM,MAAM,aAAa,CAAC,CAAC,GAAG,cAAc,IAAI,MAAM,OAAO,CAAC;IAC5D,OAAO,EAAE,SAAS,CAAC,CAAC,CAAC,CAAC;CACvB,CAAC,CAAC;AAEH,MAAM,WAAW,WAAW;IAC1B,4CAA4C;IAC5C,QAAQ,CAAC,EAAE,GAAG,CAAC;IACf,+DAA+D;IAC/D,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB;AAmBD;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,wBAAgB,IAAI,CAAC,CAAC,SAAS,CAAC,GAAG,IAAI,EAAE,GAAG,EAAE,KAAK,GAAG,EACpD,MAAM,EAAE,MAAM,OAAO,CAAC;IAAE,OAAO,EAAE,CAAC,CAAA;CAAE,CAAC,EACrC,OAAO,CAAC,EAAE,WAAW,GACpB,CAAC,GAAG;IAAE,OAAO,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAA;CAAE,CA2DtC"}
@@ -5,7 +5,7 @@
5
5
  * 1. `comp` signal is shared across all instances of this lazy component (module-level).
6
6
  * 2. `createResource` at the component level registers the load promise with the
7
7
  * nearest Suspense boundary (trackPromise / resource.loading).
8
- * 3. A pure `createMemo` reads `comp()` undefined while loading (Suspense shows
8
+ * 3. A pure `createMemo` reads `comp()`: undefined while loading (Suspense shows
9
9
  * fallback), the rendered component once loaded.
10
10
  * 4. `preload()` is exposed so routes / link hover handlers can start the download
11
11
  * before the component is rendered.
@@ -28,10 +28,31 @@ function fromChunk(value) {
28
28
  return value;
29
29
  }
30
30
  // ─── Implementation ──────────────────────────────────────────────────────────
31
+ /**
32
+ * Defer a component to its own chunk, loaded the first time it renders.
33
+ *
34
+ * `loader` is a dynamic import, and its `default` export is the component. The returned
35
+ * function stands in for it and carries `preload()`, which starts the import without
36
+ * rendering anything. File routing uses that: `startClient` preloads the matched route
37
+ * before hydrating.
38
+ *
39
+ * Preloading is what keeps hydration intact. If the module has already resolved by the
40
+ * time this renders, the component renders synchronously on the first pass, so it adopts
41
+ * the server's DOM in place. On a cold client navigation it goes through a resource
42
+ * instead, suspends, and a `Suspense` boundary above it shows the fallback.
43
+ *
44
+ * @example
45
+ * ```ts
46
+ * const Settings = lazy(() => import('./Settings.js'));
47
+ *
48
+ * // somewhere that knows the route is next
49
+ * void Settings.preload();
50
+ * ```
51
+ */
31
52
  export function lazy(loader, options) {
32
53
  // The resolved component, set once the module loads. The whole hydration story turns on
33
- // this: when it's already set when LazyWrapper renders because the route was preloaded
34
- // before hydration (see startClient preloadRoutes) we render it SYNCHRONOUSLY on the
54
+ // this: when it's already set when LazyWrapper renders, because the route was preloaded
55
+ // before hydration (see startClient -> preloadRoutes): we render it SYNCHRONOUSLY on the
35
56
  // first pass. No resource, no Suspense fallback, no late re-render. So the lazy file-route
36
57
  // adopts the server DOM in place instead of resolving a tick later and building a duplicate
37
58
  // next to it. The async path below is only for a cold client navigation.
@@ -50,7 +71,7 @@ export function lazy(loader, options) {
50
71
  load();
51
72
  const LazyWrapper = ((props) => {
52
73
  // Fast path: module already loaded (eager preload, or preloaded before hydration).
53
- // Render straight through under hydration this consumes the cursor in place.
74
+ // Render straight through: under hydration this consumes the cursor in place.
54
75
  if (resolved) {
55
76
  const C = resolved;
56
77
  return fromChunk(untrack(() => C(props)));
@@ -59,7 +80,7 @@ export function lazy(loader, options) {
59
80
  // fetched). Register the import with the nearest Suspense via createResource so the
60
81
  // fallback shows while it downloads, then swap in the component once it resolves.
61
82
  if (!component) {
62
- // transport:false the value here is the component function, which never
83
+ // transport:false, the value here is the component function, which never
63
84
  // travelled to the client, and the id it used to consume made the page's own
64
85
  // resource ids depend on whether this module was already loaded in the
65
86
  // process. The client re-imports the chunk itself either way.
@@ -1 +1,50 @@
1
- import{createComponent as d}from"@fluixi/dom";import{untrack as c,createMemo as m,createResource as u}from"@fluixi/reactive/signal";function p(e){if(e!=null&&(typeof e=="object"||typeof e=="function"))try{e.$lazy=!0}catch{}return e}function T(e,f){let t,a,i;function s(){return a||(a=e().then(r=>t=r.default)),a}f?.preload&&s();let o=(r=>{if(t){let n=t;return p(c(()=>n(r)))}if(!i){let[n]=u(()=>s(),{transport:!1});if(i=n,n.error)throw n.error}return m(()=>{let n=i();return n?p(d(n,r)):void 0})});return o.preload=()=>s().then(()=>{}),o.$lazy=!0,o.loader=e,o}export{T as lazy};
1
+ // src/lib/render/lazy.ts
2
+ import { createComponent } from "@fluixi/dom";
3
+ import {
4
+ untrack,
5
+ createMemo,
6
+ createResource
7
+ } from "@fluixi/reactive/signal";
8
+ function fromChunk(value) {
9
+ if (value != null && (typeof value === "object" || typeof value === "function")) {
10
+ try {
11
+ value["$lazy"] = true;
12
+ } catch {
13
+ }
14
+ }
15
+ return value;
16
+ }
17
+ function lazy(loader, options) {
18
+ let resolved;
19
+ let promise;
20
+ let component;
21
+ function load() {
22
+ if (!promise) {
23
+ promise = loader().then((mod) => resolved = mod.default);
24
+ }
25
+ return promise;
26
+ }
27
+ if (options?.preload) load();
28
+ const LazyWrapper = ((props) => {
29
+ if (resolved) {
30
+ const C = resolved;
31
+ return fromChunk(untrack(() => C(props)));
32
+ }
33
+ if (!component) {
34
+ const [resource] = createResource(() => load(), { transport: false });
35
+ component = resource;
36
+ if (resource.error) throw resource.error;
37
+ }
38
+ return createMemo(() => {
39
+ const C = component();
40
+ return C ? fromChunk(createComponent(C, props)) : void 0;
41
+ });
42
+ });
43
+ LazyWrapper.preload = () => load().then(() => void 0);
44
+ LazyWrapper.$lazy = true;
45
+ LazyWrapper.loader = loader;
46
+ return LazyWrapper;
47
+ }
48
+ export {
49
+ lazy
50
+ };
@@ -1 +1,141 @@
1
- "use strict";var b=Object.defineProperty;var w=Object.getOwnPropertyDescriptor;var C=Object.getOwnPropertyNames;var F=Object.prototype.hasOwnProperty;var P=(e,t)=>{for(var a in t)b(e,a,{get:t[a],enumerable:!0})},g=(e,t,a,i)=>{if(t&&typeof t=="object"||typeof t=="function")for(let c of C(t))!F.call(e,c)&&c!==a&&b(e,c,{get:()=>t[c],enumerable:!(i=w(t,c))||i.enumerable});return e};var A=e=>g(b({},"__esModule",{value:!0}),e);var O={};P(O,{$SUSPENSE:()=>L,Suspense:()=>S,SuspenseList:()=>N,isJSXElement:()=>E,isLitResult:()=>R,isNode:()=>x,isPromise:()=>h});module.exports=A(O);var n=require("@fluixi/reactive/signal"),l=require("@fluixi/dom"),L=Symbol.for("suspense");function x(e){return typeof window>"u"?!1:typeof Node=="function"&&e instanceof Node?!0:!!(e&&typeof e=="object"&&typeof e.nodeType=="number")}function R(e){return!e||typeof e!="object"?!1:!!(typeof e._$litType$<"u"||typeof e._$litDirective$<"u"||Array.isArray(e.strings)&&Array.isArray(e.values))}function h(e){return!!(e&&typeof e=="object"&&typeof e.then=="function"||e instanceof Promise)}function E(e){return!!(e&&typeof e=="object"&&"type"in e&&"props"in e)}var m=(0,n.createContext)(void 0,"suspense-list");function S(e){return(0,l.createComponent)(j,e)}function j(e){let t=(0,n.createSuspenseBoundary)(),a=(0,n.useContext)(m),i=a?a.register(t.inFallback):void 0;function c(o){return o==null||typeof o=="boolean"?null:typeof o=="function"&&(0,l.isComponent)(o)&&!(0,n.isSignal)(o)?o():o}let d=(0,l.runWithoutHydration)(()=>c(e.fallback??null)),r=(0,n.provideSuspense)(t,()=>(0,n.readChildren)(()=>e.children)),s=(o,y)=>{if(!(y>8))if(Array.isArray(o))for(let k of o)s(k,y+1);else typeof o=="function"&&(0,n.isSignal)(o)&&s(o(),y+1)};(0,n.provideSuspense)(t,()=>{(0,n.createRenderEffect)(()=>s(r,0))});let[f,p]=(0,n.createSignal)(void 0),u=h(r);return u&&(t.increment(),r.then(o=>{p(()=>o),t.decrement()},()=>t.decrement())),(0,n.createMemo)(()=>(i?i.showFallback():t.inFallback())?d:u?f():r)}function N(e){return(0,l.createComponent)($,e)}function $(e){let{revealOrder:t="together",tail:a}=e,i=[];function c(){if(t==="together"){let r=i.every(s=>!s.inFallback());i.forEach(s=>{s.setShowContent(r),s.setShowFallback(!r)})}else{let r=t==="backwards"?[...i].reverse():i,s=!1;for(let f of r)s||f.inFallback()?(s=!0,f.setShowContent(!1),f.setShowFallback(a!=="hidden")):(f.setShowContent(!0),f.setShowFallback(!1))}}let d={register:r=>{let[s,f]=(0,n.createSignal)(!0),[p,u]=(0,n.createSignal)(!1);return i.push({inFallback:r,setShowContent:f,setShowFallback:u}),(0,n.createEffect)(()=>{r(),c()}),{showContent:s,showFallback:p}}};return m.Provider({value:d,children:e.children})}(0,l.asSuspense)(S);Object.defineProperty(S,"__suspense",{value:!0,enumerable:!0});
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/render/suspense.ts
21
+ var suspense_exports = {};
22
+ __export(suspense_exports, {
23
+ $SUSPENSE: () => $SUSPENSE,
24
+ Suspense: () => Suspense,
25
+ SuspenseList: () => SuspenseList,
26
+ isJSXElement: () => isJSXElement,
27
+ isLitResult: () => isLitResult,
28
+ isNode: () => isNode,
29
+ isPromise: () => isPromise
30
+ });
31
+ module.exports = __toCommonJS(suspense_exports);
32
+ var import_signal = require("@fluixi/reactive/signal");
33
+ var import_dom = require("@fluixi/dom");
34
+ var $SUSPENSE = /* @__PURE__ */ Symbol.for("suspense");
35
+ function isNode(value) {
36
+ if (typeof window === "undefined") return false;
37
+ if (typeof Node === "function" && value instanceof Node) return true;
38
+ return !!(value && typeof value === "object" && typeof value.nodeType === "number");
39
+ }
40
+ function isLitResult(value) {
41
+ if (!value || typeof value !== "object") return false;
42
+ return !!(typeof value["_$litType$"] !== "undefined" || typeof value["_$litDirective$"] !== "undefined" || Array.isArray(value.strings) && Array.isArray(value.values));
43
+ }
44
+ function isPromise(value) {
45
+ return !!(value && typeof value === "object" && typeof value.then === "function" || value instanceof Promise);
46
+ }
47
+ function isJSXElement(value) {
48
+ return !!(value && typeof value === "object" && "type" in value && "props" in value);
49
+ }
50
+ var SuspenseListContext = (0, import_signal.createContext)(void 0, "suspense-list");
51
+ function Suspense(props) {
52
+ return (0, import_dom.createComponent)(SuspenseImpl, props);
53
+ }
54
+ function SuspenseImpl(props) {
55
+ const boundary = (0, import_signal.createSuspenseBoundary)();
56
+ const listCtx = (0, import_signal.useContext)(SuspenseListContext);
57
+ const listState = listCtx ? listCtx.register(boundary.inFallback) : void 0;
58
+ function instantiateOnce(val) {
59
+ if (val == null || typeof val === "boolean") return null;
60
+ if (typeof val === "function" && (0, import_dom.isComponent)(val) && !(0, import_signal.isSignal)(val)) return val();
61
+ return val;
62
+ }
63
+ const fallback = (0, import_dom.runWithoutHydration)(() => instantiateOnce(props.fallback ?? null));
64
+ const children = (0, import_signal.provideSuspense)(boundary, () => (0, import_signal.readChildren)(() => props.children));
65
+ const track = (value, depth) => {
66
+ if (depth > 8) return;
67
+ if (Array.isArray(value)) {
68
+ for (const x of value) track(x, depth + 1);
69
+ } else if (typeof value === "function" && (0, import_signal.isSignal)(value)) {
70
+ track(value(), depth + 1);
71
+ }
72
+ };
73
+ (0, import_signal.provideSuspense)(boundary, () => {
74
+ (0, import_signal.createRenderEffect)(() => track(children, 0));
75
+ });
76
+ const [resolved, setResolved] = (0, import_signal.createSignal)(void 0);
77
+ const childIsPromise = isPromise(children);
78
+ if (childIsPromise) {
79
+ boundary.increment();
80
+ children.then(
81
+ (v) => {
82
+ setResolved(() => v);
83
+ boundary.decrement();
84
+ },
85
+ () => boundary.decrement()
86
+ );
87
+ }
88
+ return (0, import_signal.createMemo)(() => {
89
+ const showFallback = listState ? listState.showFallback() : boundary.inFallback();
90
+ if (showFallback) return fallback;
91
+ if (childIsPromise) return resolved();
92
+ return children;
93
+ });
94
+ }
95
+ function SuspenseList(props) {
96
+ return (0, import_dom.createComponent)(SuspenseListImpl, props);
97
+ }
98
+ function SuspenseListImpl(props) {
99
+ const { revealOrder = "together", tail } = props;
100
+ const registrations = [];
101
+ function coordinateReveal() {
102
+ if (revealOrder === "together") {
103
+ const allResolved = registrations.every((r) => !r.inFallback());
104
+ registrations.forEach((r) => {
105
+ r.setShowContent(allResolved);
106
+ r.setShowFallback(!allResolved);
107
+ });
108
+ } else {
109
+ const items = revealOrder === "backwards" ? [...registrations].reverse() : registrations;
110
+ let blocked = false;
111
+ for (const r of items) {
112
+ if (blocked || r.inFallback()) {
113
+ blocked = true;
114
+ r.setShowContent(false);
115
+ r.setShowFallback(tail !== "hidden");
116
+ } else {
117
+ r.setShowContent(true);
118
+ r.setShowFallback(false);
119
+ }
120
+ }
121
+ }
122
+ }
123
+ const coordinator = {
124
+ register: (inFallback) => {
125
+ const [showContent, setShowContent] = (0, import_signal.createSignal)(true);
126
+ const [showFallback, setShowFallback] = (0, import_signal.createSignal)(false);
127
+ registrations.push({ inFallback, setShowContent, setShowFallback });
128
+ (0, import_signal.createEffect)(() => {
129
+ inFallback();
130
+ coordinateReveal();
131
+ });
132
+ return { showContent, showFallback };
133
+ }
134
+ };
135
+ return SuspenseListContext.Provider({
136
+ value: coordinator,
137
+ children: props.children
138
+ });
139
+ }
140
+ (0, import_dom.asSuspense)(Suspense);
141
+ Object.defineProperty(Suspense, "__suspense", { value: true, enumerable: true });
@@ -19,7 +19,47 @@ declare function isNode(value: any): value is Node;
19
19
  declare function isLitResult(value: any): boolean;
20
20
  declare function isPromise<T = any>(value: any): value is Promise<T>;
21
21
  declare function isJSXElement(value: any): boolean;
22
+ /**
23
+ * Show `fallback` while anything below is still pending.
24
+ *
25
+ * A boundary is a counter on the owner tree. A read that suspends, which is a resource
26
+ * throwing its pending promise, bubbles to the effect that was reading, and the runtime
27
+ * hands it to the nearest boundary above. The promise settling decrements the counter,
28
+ * and the content replaces the fallback through ordinary reactivity.
29
+ *
30
+ * Nothing needs to be wired by hand. Anything that suspends reports here on its own,
31
+ * including a `lazy` component on a cold navigation and a `createResource` still loading.
32
+ *
33
+ * @example
34
+ * ```ts
35
+ * html`
36
+ * <${Suspense} fallback=${html`<p>loading...</p>`}>
37
+ * <${Profile} />
38
+ * </${Suspense}>`;
39
+ * ```
40
+ */
22
41
  export declare function Suspense(props: SuspenseProps): any;
42
+ /**
43
+ * Order how a group of sibling `Suspense` boundaries reveal themselves.
44
+ *
45
+ * Without it, each boundary swaps its fallback for content the moment its own work
46
+ * finishes, so a list of independently-loading rows appears in whatever order the
47
+ * network happened to return. `revealOrder` imposes one instead.
48
+ *
49
+ * `forwards` and `backwards` hold a boundary in its fallback until the ones before it in
50
+ * that direction have resolved. `together`, the default, holds all of them until every
51
+ * one has. `tail` decides what the unrevealed ones show: `collapsed` keeps only the next
52
+ * fallback, `hidden` shows none.
53
+ *
54
+ * @example
55
+ * ```ts
56
+ * html`
57
+ * <${SuspenseList} revealOrder="forwards" tail="collapsed">
58
+ * <${Suspense} fallback=${skeleton}><${Row} id=${1} /></${Suspense}>
59
+ * <${Suspense} fallback=${skeleton}><${Row} id=${2} /></${Suspense}>
60
+ * </${SuspenseList}>`;
61
+ * ```
62
+ */
23
63
  export declare function SuspenseList(props: SuspenseListProps): any;
24
64
  export { isNode, isLitResult, isPromise, isJSXElement };
25
65
  //# sourceMappingURL=suspense.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"suspense.d.ts","sourceRoot":"","sources":["../../../../src/lib/render/suspense.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAuBH,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,EAAE,GAAG,CAAC;IACf,QAAQ,CAAC,EAAE,GAAG,CAAC;IACf,EAAE,CAAC,EAAE,MAAM,CAAC;CACb;AAED,MAAM,WAAW,iBAAiB;IAChC,QAAQ,EAAE,GAAG,CAAC;IACd,WAAW,CAAC,EAAE,UAAU,GAAG,WAAW,GAAG,UAAU,CAAC;IACpD,IAAI,CAAC,EAAE,WAAW,GAAG,QAAQ,CAAC;CAC/B;AAED,eAAO,MAAM,SAAS,eAAyB,CAAC;AAEhD,iBAAS,MAAM,CAAC,KAAK,EAAE,GAAG,GAAG,KAAK,IAAI,IAAI,CAIzC;AAED,iBAAS,WAAW,CAAC,KAAK,EAAE,GAAG,GAAG,OAAO,CAOxC;AAED,iBAAS,SAAS,CAAC,CAAC,GAAG,GAAG,EAAE,KAAK,EAAE,GAAG,GAAG,KAAK,IAAI,OAAO,CAAC,CAAC,CAAC,CAK3D;AAED,iBAAS,YAAY,CAAC,KAAK,EAAE,GAAG,GAAG,OAAO,CAEzC;AAYD,wBAAgB,QAAQ,CAAC,KAAK,EAAE,aAAa,GAAG,GAAG,CAElD;AA+ED,wBAAgB,YAAY,CAAC,KAAK,EAAE,iBAAiB,GAAG,GAAG,CAE1D;AAwDD,OAAO,EAAE,MAAM,EAAE,WAAW,EAAE,SAAS,EAAE,YAAY,EAAE,CAAC"}
1
+ {"version":3,"file":"suspense.d.ts","sourceRoot":"","sources":["../../../../src/lib/render/suspense.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAuBH,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,EAAE,GAAG,CAAC;IACf,QAAQ,CAAC,EAAE,GAAG,CAAC;IACf,EAAE,CAAC,EAAE,MAAM,CAAC;CACb;AAED,MAAM,WAAW,iBAAiB;IAChC,QAAQ,EAAE,GAAG,CAAC;IACd,WAAW,CAAC,EAAE,UAAU,GAAG,WAAW,GAAG,UAAU,CAAC;IACpD,IAAI,CAAC,EAAE,WAAW,GAAG,QAAQ,CAAC;CAC/B;AAED,eAAO,MAAM,SAAS,eAAyB,CAAC;AAEhD,iBAAS,MAAM,CAAC,KAAK,EAAE,GAAG,GAAG,KAAK,IAAI,IAAI,CAIzC;AAED,iBAAS,WAAW,CAAC,KAAK,EAAE,GAAG,GAAG,OAAO,CAOxC;AAED,iBAAS,SAAS,CAAC,CAAC,GAAG,GAAG,EAAE,KAAK,EAAE,GAAG,GAAG,KAAK,IAAI,OAAO,CAAC,CAAC,CAAC,CAK3D;AAED,iBAAS,YAAY,CAAC,KAAK,EAAE,GAAG,GAAG,OAAO,CAEzC;AAYD;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAgB,QAAQ,CAAC,KAAK,EAAE,aAAa,GAAG,GAAG,CAElD;AA+ED;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,wBAAgB,YAAY,CAAC,KAAK,EAAE,iBAAiB,GAAG,GAAG,CAE1D;AAwDD,OAAO,EAAE,MAAM,EAAE,WAAW,EAAE,SAAS,EAAE,YAAY,EAAE,CAAC"}
@@ -29,6 +29,25 @@ function isJSXElement(value) {
29
29
  return !!(value && typeof value === 'object' && 'type' in value && 'props' in value);
30
30
  }
31
31
  const SuspenseListContext = createContext(undefined, 'suspense-list');
32
+ /**
33
+ * Show `fallback` while anything below is still pending.
34
+ *
35
+ * A boundary is a counter on the owner tree. A read that suspends, which is a resource
36
+ * throwing its pending promise, bubbles to the effect that was reading, and the runtime
37
+ * hands it to the nearest boundary above. The promise settling decrements the counter,
38
+ * and the content replaces the fallback through ordinary reactivity.
39
+ *
40
+ * Nothing needs to be wired by hand. Anything that suspends reports here on its own,
41
+ * including a `lazy` component on a cold navigation and a `createResource` still loading.
42
+ *
43
+ * @example
44
+ * ```ts
45
+ * html`
46
+ * <${Suspense} fallback=${html`<p>loading...</p>`}>
47
+ * <${Profile} />
48
+ * </${Suspense}>`;
49
+ * ```
50
+ */
32
51
  export function Suspense(props) {
33
52
  return createComponent(SuspenseImpl, props);
34
53
  }
@@ -44,30 +63,30 @@ function SuspenseImpl(props) {
44
63
  return val();
45
64
  return val;
46
65
  }
47
- // Build the fallback off the hydration cursor it isn't shown when the server
66
+ // Build the fallback off the hydration cursor, it isn't shown when the server
48
67
  // already rendered content, so it must not adopt (and duplicate) server nodes.
49
68
  const fallback = runWithoutHydration(() => instantiateOnce(props.fallback ?? null));
50
69
  // Read the children under the boundary so the memos they create capture its owner;
51
- // then a suspended resource read inside them throws to THIS boundary, not the parent.
70
+ // then a suspended resource read inside them throws to this boundary, not the parent.
52
71
  //
53
72
  // `readChildren`, not a bare `props.children` read: a component child arrives as a THUNK
54
73
  // that instantiates when called, so reading the prop alone hands back a function and the
55
74
  // component never runs here. It would then be instantiated later, downstream of the output
56
- // memo, where a suspend has no boundary that can re-run it the failure that produced an
75
+ // memo, where a suspend has no boundary that can re-run it, the failure that produced an
57
76
  // empty node on a client navigation into a not-yet-loaded lazy route: no fallback, no
58
77
  // content, no error. `readChildren` unwraps the thunks (so the lazy component runs under
59
78
  // this boundary), stops at signals so dynamic children stay reactive, and memoises the
60
79
  // result so the tracking effect below and the output render the same instantiation.
61
80
  const children = provideSuspense(boundary, () => readChildren(() => props.children));
62
81
  // Instantiate the children now, in their own effect under the boundary. A suspended
63
- // resource read inside them throws here synchronously a sibling of the output memo
64
- // below so the increment reschedules the output cleanly (matching the canary). If we
82
+ // resource read inside them throws here synchronously, a sibling of the output memo
83
+ // below, so the increment reschedules the output cleanly (matching the canary). If we
65
84
  // only rendered children through the output's return, the resource read would be nested
66
85
  // inside the output's own insert effect, which then never re-runs to show the fallback.
67
86
  //
68
87
  // Follow NESTED accessors, not just the outer one: the compiler wraps a dynamic child in
69
88
  // its own memo, and `readChildren` stops at signals on purpose so they stay reactive. Stop
70
- // at the outer read and a lazy component behind a condition is never instantiated here
89
+ // at the outer read and a lazy component behind a condition is never instantiated here
71
90
  // it runs later, downstream, where its suspend reaches no boundary. Reading a memo is
72
91
  // idempotent (it caches, and the output reads the same one), so following the chain costs
73
92
  // nothing and cannot duplicate the subtree.
@@ -104,6 +123,27 @@ function SuspenseImpl(props) {
104
123
  return children;
105
124
  });
106
125
  }
126
+ /**
127
+ * Order how a group of sibling `Suspense` boundaries reveal themselves.
128
+ *
129
+ * Without it, each boundary swaps its fallback for content the moment its own work
130
+ * finishes, so a list of independently-loading rows appears in whatever order the
131
+ * network happened to return. `revealOrder` imposes one instead.
132
+ *
133
+ * `forwards` and `backwards` hold a boundary in its fallback until the ones before it in
134
+ * that direction have resolved. `together`, the default, holds all of them until every
135
+ * one has. `tail` decides what the unrevealed ones show: `collapsed` keeps only the next
136
+ * fallback, `hidden` shows none.
137
+ *
138
+ * @example
139
+ * ```ts
140
+ * html`
141
+ * <${SuspenseList} revealOrder="forwards" tail="collapsed">
142
+ * <${Suspense} fallback=${skeleton}><${Row} id=${1} /></${Suspense}>
143
+ * <${Suspense} fallback=${skeleton}><${Row} id=${2} /></${Suspense}>
144
+ * </${SuspenseList}>`;
145
+ * ```
146
+ */
107
147
  export function SuspenseList(props) {
108
148
  return createComponent(SuspenseListImpl, props);
109
149
  }
@@ -1 +1,136 @@
1
- import{createSignal as p,createMemo as w,createEffect as C,createRenderEffect as F,isSignal as y,readChildren as P,useContext as g,createContext as A,createSuspenseBoundary as L,provideSuspense as b}from"@fluixi/reactive/signal";import{asSuspense as x,isComponent as R,createComponent as S,runWithoutHydration as E}from"@fluixi/dom";var _=Symbol.for("suspense");function B(e){return typeof window>"u"?!1:typeof Node=="function"&&e instanceof Node?!0:!!(e&&typeof e=="object"&&typeof e.nodeType=="number")}function I(e){return!e||typeof e!="object"?!1:!!(typeof e._$litType$<"u"||typeof e._$litDirective$<"u"||Array.isArray(e.strings)&&Array.isArray(e.values))}function j(e){return!!(e&&typeof e=="object"&&typeof e.then=="function"||e instanceof Promise)}function D(e){return!!(e&&typeof e=="object"&&"type"in e&&"props"in e)}var h=A(void 0,"suspense-list");function m(e){return S(N,e)}function N(e){let s=L(),a=g(h),i=a?a.register(s.inFallback):void 0;function f(n){return n==null||typeof n=="boolean"?null:typeof n=="function"&&R(n)&&!y(n)?n():n}let l=E(()=>f(e.fallback??null)),o=b(s,()=>P(()=>e.children)),t=(n,d)=>{if(!(d>8))if(Array.isArray(n))for(let k of n)t(k,d+1);else typeof n=="function"&&y(n)&&t(n(),d+1)};b(s,()=>{F(()=>t(o,0))});let[r,u]=p(void 0),c=j(o);return c&&(s.increment(),o.then(n=>{u(()=>n),s.decrement()},()=>s.decrement())),w(()=>(i?i.showFallback():s.inFallback())?l:c?r():o)}function H(e){return S($,e)}function $(e){let{revealOrder:s="together",tail:a}=e,i=[];function f(){if(s==="together"){let o=i.every(t=>!t.inFallback());i.forEach(t=>{t.setShowContent(o),t.setShowFallback(!o)})}else{let o=s==="backwards"?[...i].reverse():i,t=!1;for(let r of o)t||r.inFallback()?(t=!0,r.setShowContent(!1),r.setShowFallback(a!=="hidden")):(r.setShowContent(!0),r.setShowFallback(!1))}}let l={register:o=>{let[t,r]=p(!0),[u,c]=p(!1);return i.push({inFallback:o,setShowContent:r,setShowFallback:c}),C(()=>{o(),f()}),{showContent:t,showFallback:u}}};return h.Provider({value:l,children:e.children})}x(m);Object.defineProperty(m,"__suspense",{value:!0,enumerable:!0});export{_ as $SUSPENSE,m as Suspense,H as SuspenseList,D as isJSXElement,I as isLitResult,B as isNode,j as isPromise};
1
+ // src/lib/render/suspense.ts
2
+ import {
3
+ createSignal,
4
+ createMemo,
5
+ createEffect,
6
+ createRenderEffect,
7
+ isSignal,
8
+ readChildren,
9
+ useContext,
10
+ createContext,
11
+ createSuspenseBoundary,
12
+ provideSuspense
13
+ } from "@fluixi/reactive/signal";
14
+ import {
15
+ asSuspense,
16
+ isComponent,
17
+ createComponent,
18
+ runWithoutHydration
19
+ } from "@fluixi/dom";
20
+ var $SUSPENSE = /* @__PURE__ */ Symbol.for("suspense");
21
+ function isNode(value) {
22
+ if (typeof window === "undefined") return false;
23
+ if (typeof Node === "function" && value instanceof Node) return true;
24
+ return !!(value && typeof value === "object" && typeof value.nodeType === "number");
25
+ }
26
+ function isLitResult(value) {
27
+ if (!value || typeof value !== "object") return false;
28
+ return !!(typeof value["_$litType$"] !== "undefined" || typeof value["_$litDirective$"] !== "undefined" || Array.isArray(value.strings) && Array.isArray(value.values));
29
+ }
30
+ function isPromise(value) {
31
+ return !!(value && typeof value === "object" && typeof value.then === "function" || value instanceof Promise);
32
+ }
33
+ function isJSXElement(value) {
34
+ return !!(value && typeof value === "object" && "type" in value && "props" in value);
35
+ }
36
+ var SuspenseListContext = createContext(void 0, "suspense-list");
37
+ function Suspense(props) {
38
+ return createComponent(SuspenseImpl, props);
39
+ }
40
+ function SuspenseImpl(props) {
41
+ const boundary = createSuspenseBoundary();
42
+ const listCtx = useContext(SuspenseListContext);
43
+ const listState = listCtx ? listCtx.register(boundary.inFallback) : void 0;
44
+ function instantiateOnce(val) {
45
+ if (val == null || typeof val === "boolean") return null;
46
+ if (typeof val === "function" && isComponent(val) && !isSignal(val)) return val();
47
+ return val;
48
+ }
49
+ const fallback = runWithoutHydration(() => instantiateOnce(props.fallback ?? null));
50
+ const children = provideSuspense(boundary, () => readChildren(() => props.children));
51
+ const track = (value, depth) => {
52
+ if (depth > 8) return;
53
+ if (Array.isArray(value)) {
54
+ for (const x of value) track(x, depth + 1);
55
+ } else if (typeof value === "function" && isSignal(value)) {
56
+ track(value(), depth + 1);
57
+ }
58
+ };
59
+ provideSuspense(boundary, () => {
60
+ createRenderEffect(() => track(children, 0));
61
+ });
62
+ const [resolved, setResolved] = createSignal(void 0);
63
+ const childIsPromise = isPromise(children);
64
+ if (childIsPromise) {
65
+ boundary.increment();
66
+ children.then(
67
+ (v) => {
68
+ setResolved(() => v);
69
+ boundary.decrement();
70
+ },
71
+ () => boundary.decrement()
72
+ );
73
+ }
74
+ return createMemo(() => {
75
+ const showFallback = listState ? listState.showFallback() : boundary.inFallback();
76
+ if (showFallback) return fallback;
77
+ if (childIsPromise) return resolved();
78
+ return children;
79
+ });
80
+ }
81
+ function SuspenseList(props) {
82
+ return createComponent(SuspenseListImpl, props);
83
+ }
84
+ function SuspenseListImpl(props) {
85
+ const { revealOrder = "together", tail } = props;
86
+ const registrations = [];
87
+ function coordinateReveal() {
88
+ if (revealOrder === "together") {
89
+ const allResolved = registrations.every((r) => !r.inFallback());
90
+ registrations.forEach((r) => {
91
+ r.setShowContent(allResolved);
92
+ r.setShowFallback(!allResolved);
93
+ });
94
+ } else {
95
+ const items = revealOrder === "backwards" ? [...registrations].reverse() : registrations;
96
+ let blocked = false;
97
+ for (const r of items) {
98
+ if (blocked || r.inFallback()) {
99
+ blocked = true;
100
+ r.setShowContent(false);
101
+ r.setShowFallback(tail !== "hidden");
102
+ } else {
103
+ r.setShowContent(true);
104
+ r.setShowFallback(false);
105
+ }
106
+ }
107
+ }
108
+ }
109
+ const coordinator = {
110
+ register: (inFallback) => {
111
+ const [showContent, setShowContent] = createSignal(true);
112
+ const [showFallback, setShowFallback] = createSignal(false);
113
+ registrations.push({ inFallback, setShowContent, setShowFallback });
114
+ createEffect(() => {
115
+ inFallback();
116
+ coordinateReveal();
117
+ });
118
+ return { showContent, showFallback };
119
+ }
120
+ };
121
+ return SuspenseListContext.Provider({
122
+ value: coordinator,
123
+ children: props.children
124
+ });
125
+ }
126
+ asSuspense(Suspense);
127
+ Object.defineProperty(Suspense, "__suspense", { value: true, enumerable: true });
128
+ export {
129
+ $SUSPENSE,
130
+ Suspense,
131
+ SuspenseList,
132
+ isJSXElement,
133
+ isLitResult,
134
+ isNode,
135
+ isPromise
136
+ };