@fluixi/core 1.0.0-alpha.92 → 1.0.0-alpha.93
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.
- package/dist/cdn/core.global.js +2 -2
- package/dist/src/cdn/{chunk-MDJLC3PE.mjs → chunk-7XM7Q5VR.mjs} +271 -229
- package/dist/src/cdn/core.cjs +360 -253
- package/dist/src/cdn/core.mjs +92 -20
- package/dist/src/cdn/{router-JYFZP3EZ.mjs → router-VOY43YNM.mjs} +7 -3
- package/dist/src/index.cjs +547 -232
- package/dist/src/index.mjs +547 -223
- package/dist/src/lib/client/chunk-QT3RFKH6.mjs +53 -0
- package/dist/src/lib/client/index.cjs +310 -176
- package/dist/src/lib/client/index.d.ts.map +1 -1
- package/dist/src/lib/client/index.js +33 -18
- package/dist/src/lib/client/index.mjs +86 -15
- package/dist/src/lib/client/{router-PHLUYVQU.mjs → router-ADTS55OP.mjs} +244 -99
- package/dist/src/lib/context/context.cjs +35 -72
- package/dist/src/lib/context/context.d.ts +45 -291
- package/dist/src/lib/context/context.d.ts.map +1 -1
- package/dist/src/lib/context/context.js +65 -397
- package/dist/src/lib/context/context.mjs +38 -73
- package/dist/src/lib/context/index.cjs +35 -72
- package/dist/src/lib/context/index.d.ts +2 -2
- package/dist/src/lib/context/index.d.ts.map +1 -1
- package/dist/src/lib/context/index.js +1 -5
- package/dist/src/lib/context/index.mjs +38 -73
- package/dist/src/lib/core.cjs +546 -231
- package/dist/src/lib/core.d.ts +3 -1
- package/dist/src/lib/core.d.ts.map +1 -1
- package/dist/src/lib/core.js +5 -3
- package/dist/src/lib/core.mjs +546 -222
- package/dist/src/lib/env/index.cjs +1 -17
- package/dist/src/lib/env/index.d.ts +2 -14
- package/dist/src/lib/env/index.d.ts.map +1 -1
- package/dist/src/lib/env/index.js +2 -26
- package/dist/src/lib/env/index.mjs +1 -17
- package/dist/src/lib/i18n/index.cjs +17 -2
- package/dist/src/lib/i18n/index.d.ts +10 -0
- package/dist/src/lib/i18n/index.d.ts.map +1 -1
- package/dist/src/lib/i18n/index.js +17 -1
- package/dist/src/lib/i18n/index.mjs +17 -2
- package/dist/src/lib/index.cjs +64 -99
- package/dist/src/lib/index.mjs +43 -76
- package/dist/src/lib/isomorphic.cjs +9 -4
- package/dist/src/lib/isomorphic.d.ts +9 -2
- package/dist/src/lib/isomorphic.d.ts.map +1 -1
- package/dist/src/lib/isomorphic.js +11 -4
- package/dist/src/lib/isomorphic.mjs +9 -4
- package/dist/src/lib/jsx-runtime/index.cjs +1 -1
- package/dist/src/lib/jsx-runtime/index.mjs +1 -1
- package/dist/src/lib/jsx-runtime/jsx-dev-runtime.cjs +1 -1
- package/dist/src/lib/jsx-runtime/jsx-dev-runtime.mjs +1 -1
- package/dist/src/lib/plugins/fluixi-routes-plugin.cjs +2 -2
- package/dist/src/lib/plugins/fluixi-routes-plugin.mjs +2 -2
- package/dist/src/lib/plugins/index.cjs +3 -3
- package/dist/src/lib/plugins/index.mjs +3 -3
- package/dist/src/lib/plugins/route-codegen.cjs +2 -2
- package/dist/src/lib/plugins/route-codegen.js +1 -1
- package/dist/src/lib/plugins/route-codegen.mjs +2 -2
- package/dist/src/lib/render/index.cjs +1 -1
- package/dist/src/lib/render/index.mjs +1 -1
- package/dist/src/lib/render/versions.cjs +1 -1
- package/dist/src/lib/render/versions.mjs +1 -1
- package/dist/src/lib/router/data.cjs +113 -115
- package/dist/src/lib/router/data.d.ts +63 -10
- package/dist/src/lib/router/data.d.ts.map +1 -1
- package/dist/src/lib/router/data.js +158 -68
- package/dist/src/lib/router/data.mjs +112 -112
- package/dist/src/lib/router/index.cjs +260 -163
- package/dist/src/lib/router/index.d.ts +22 -2
- package/dist/src/lib/router/index.d.ts.map +1 -1
- package/dist/src/lib/router/index.js +165 -22
- package/dist/src/lib/router/index.mjs +244 -143
- package/dist/src/lib/server/index.cjs +1 -1
- package/dist/src/lib/server/index.mjs +1 -1
- package/dist/src/lib/storage/cache.cjs +51 -0
- package/dist/src/lib/storage/cache.d.ts +18 -0
- package/dist/src/lib/storage/cache.d.ts.map +1 -0
- package/dist/src/lib/storage/cache.js +42 -0
- package/dist/src/lib/storage/cache.mjs +30 -0
- package/dist/src/lib/storage/index.cjs +246 -0
- package/dist/src/lib/storage/index.d.ts +83 -0
- package/dist/src/lib/storage/index.d.ts.map +1 -0
- package/dist/src/lib/storage/index.js +179 -0
- package/dist/src/lib/storage/index.mjs +231 -0
- package/dist/src/lib/storage/persisted.cjs +91 -0
- package/dist/src/lib/storage/persisted.d.ts +53 -0
- package/dist/src/lib/storage/persisted.d.ts.map +1 -0
- package/dist/src/lib/storage/persisted.js +75 -0
- package/dist/src/lib/storage/persisted.mjs +70 -0
- package/dist/src/lib/theme/color-scheme.cjs +281 -0
- package/dist/src/lib/theme/color-scheme.d.ts +61 -0
- package/dist/src/lib/theme/color-scheme.d.ts.map +1 -0
- package/dist/src/lib/theme/color-scheme.js +120 -0
- package/dist/src/lib/theme/color-scheme.mjs +265 -0
- package/dist/src/lib/theme/index.cjs +194 -37
- package/dist/src/lib/theme/index.d.ts +23 -11
- package/dist/src/lib/theme/index.d.ts.map +1 -1
- package/dist/src/lib/theme/index.js +73 -32
- package/dist/src/lib/theme/index.mjs +197 -35
- package/dist/src/lib/theme/provider.cjs +346 -0
- package/dist/src/lib/theme/provider.d.ts +34 -0
- package/dist/src/lib/theme/provider.d.ts.map +1 -0
- package/dist/src/lib/theme/provider.js +60 -0
- package/dist/src/lib/theme/provider.mjs +332 -0
- package/dist/src/routes.cjs +1 -1
- package/dist/src/routes.mjs +1 -1
- package/dist/src/utils.cjs +1 -1
- package/dist/src/utils.mjs +1 -1
- package/dist/src/version.generated.cjs +1 -1
- package/dist/src/version.generated.d.ts +1 -1
- package/dist/src/version.generated.js +1 -1
- package/dist/src/version.generated.mjs +1 -1
- package/dist/tsconfig.lib.tsbuildinfo +1 -1
- package/package.json +18 -11
- package/dist/src/lib/client/chunk-VB567ABU.mjs +0 -133
|
@@ -1,11 +1,7 @@
|
|
|
1
|
-
/*! @fluixi/core v1.0.0-alpha.
|
|
1
|
+
/*! @fluixi/core v1.0.0-alpha.93 | (c) 2026 Ibrahima Touré and Fluixi contributors | MIT */
|
|
2
2
|
import {
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
isServerEnvironment,
|
|
6
|
-
lazy,
|
|
7
|
-
setHydrationData
|
|
8
|
-
} from "./chunk-VB567ABU.mjs";
|
|
3
|
+
lazy
|
|
4
|
+
} from "./chunk-QT3RFKH6.mjs";
|
|
9
5
|
|
|
10
6
|
// src/lib/router/index.ts
|
|
11
7
|
import {
|
|
@@ -13,8 +9,10 @@ import {
|
|
|
13
9
|
createMemo,
|
|
14
10
|
createResource as createResource2,
|
|
15
11
|
createEffect,
|
|
16
|
-
|
|
12
|
+
createRoot,
|
|
13
|
+
getOwner as getOwner2,
|
|
17
14
|
onCleanup,
|
|
15
|
+
runWithOwner,
|
|
18
16
|
untrack,
|
|
19
17
|
flush
|
|
20
18
|
} from "@fluixi/reactive/signal";
|
|
@@ -83,42 +81,35 @@ import {
|
|
|
83
81
|
matchRoutes,
|
|
84
82
|
matchPath
|
|
85
83
|
} from "@fluixi/router";
|
|
86
|
-
import {
|
|
87
|
-
createMemoryHistory,
|
|
88
|
-
createBrowserHistory as createBrowserHistory2,
|
|
89
|
-
matchRoutes as matchRoutes2,
|
|
90
|
-
matchPath as matchPath2
|
|
91
|
-
} from "@fluixi/router";
|
|
92
84
|
|
|
93
85
|
// src/lib/router/data.ts
|
|
94
86
|
import {
|
|
95
87
|
createResource,
|
|
96
88
|
createSignal
|
|
97
89
|
} from "@fluixi/reactive/signal";
|
|
90
|
+
import { currentResourceCache } from "@fluixi/reactive/signal";
|
|
98
91
|
|
|
99
92
|
// src/lib/context/context.ts
|
|
100
93
|
import { asProvider } from "@fluixi/dom";
|
|
101
|
-
import { createContext as createReactiveContext, useContext as useReactiveContext } from "@fluixi/reactive/signal";
|
|
102
94
|
import {
|
|
103
|
-
|
|
95
|
+
createContext as createReactiveContext,
|
|
96
|
+
getOwner,
|
|
97
|
+
useContext as useReactiveContext
|
|
104
98
|
} from "@fluixi/reactive/signal";
|
|
105
99
|
function createContext(defaultValue, name) {
|
|
106
100
|
const context = createReactiveContext(defaultValue, name);
|
|
107
|
-
const Provider = (props) =>
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
101
|
+
const Provider = (props) => (
|
|
102
|
+
// Children stay a getter: the reactive Provider reads them after stamping the value on
|
|
103
|
+
// its owner. Reading `props.children` here would render them, and any <Outlet/> in them,
|
|
104
|
+
// before the context exists.
|
|
105
|
+
context.Provider({
|
|
111
106
|
value: props.value,
|
|
112
107
|
get children() {
|
|
113
108
|
return props.children;
|
|
114
109
|
},
|
|
115
110
|
debug: props.debug
|
|
116
|
-
})
|
|
117
|
-
|
|
118
|
-
if (typeof Symbol !== "undefined" && Symbol.for) {
|
|
119
|
-
Provider.$$typeof = /* @__PURE__ */ Symbol.for("react.provider");
|
|
120
|
-
}
|
|
121
|
-
Provider.$$typeof = /* @__PURE__ */ Symbol.for("react.provider");
|
|
111
|
+
})
|
|
112
|
+
);
|
|
122
113
|
return {
|
|
123
114
|
id: context.id,
|
|
124
115
|
Provider: asProvider(Provider),
|
|
@@ -127,53 +118,73 @@ function createContext(defaultValue, name) {
|
|
|
127
118
|
}
|
|
128
119
|
|
|
129
120
|
// src/lib/router/data.ts
|
|
130
|
-
var
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
return
|
|
121
|
+
var revalidationListeners = /* @__PURE__ */ new Set();
|
|
122
|
+
function onRevalidate(listener) {
|
|
123
|
+
revalidationListeners.add(listener);
|
|
124
|
+
return () => void revalidationListeners.delete(listener);
|
|
125
|
+
}
|
|
126
|
+
var reloadMounted = () => {
|
|
127
|
+
for (const listener of [...revalidationListeners]) listener();
|
|
128
|
+
};
|
|
129
|
+
function cache(fn, name, options = {}) {
|
|
130
|
+
const { ttl = Infinity, staleWhileRevalidate = true } = options;
|
|
131
|
+
return (...args) => {
|
|
132
|
+
const store = options.cache ?? currentResourceCache();
|
|
134
133
|
const key = name + ":" + JSON.stringify(args);
|
|
135
|
-
|
|
136
|
-
const
|
|
137
|
-
if (
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
const promise = Promise.resolve(fn(...args)).then(
|
|
148
|
-
(val) => {
|
|
149
|
-
globalCache.set(key, val);
|
|
150
|
-
inflightRequests.delete(key);
|
|
151
|
-
if (isServerEnvironment()) {
|
|
152
|
-
setHydrationData(key, val);
|
|
134
|
+
const fetchFresh = () => {
|
|
135
|
+
const running = store.inflight.get(key);
|
|
136
|
+
if (running) return running;
|
|
137
|
+
const promise = Promise.resolve(fn(...args)).then(
|
|
138
|
+
(value) => {
|
|
139
|
+
store.set(key, { value, timestamp: Date.now() });
|
|
140
|
+
store.inflight.delete(key);
|
|
141
|
+
return value;
|
|
142
|
+
},
|
|
143
|
+
(error) => {
|
|
144
|
+
store.inflight.delete(key);
|
|
145
|
+
throw error;
|
|
153
146
|
}
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
)
|
|
161
|
-
|
|
162
|
-
|
|
147
|
+
);
|
|
148
|
+
store.inflight.set(key, promise);
|
|
149
|
+
return promise;
|
|
150
|
+
};
|
|
151
|
+
const hit = store.get(key);
|
|
152
|
+
if (hit && (ttl === Infinity || Date.now() - hit.timestamp <= ttl)) return Promise.resolve(hit.value);
|
|
153
|
+
if (hit && staleWhileRevalidate) {
|
|
154
|
+
fetchFresh().then(reloadMounted, () => void 0);
|
|
155
|
+
return Promise.resolve(hit.value);
|
|
156
|
+
}
|
|
157
|
+
return fetchFresh();
|
|
163
158
|
};
|
|
164
159
|
}
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
160
|
+
function revalidate(key, store) {
|
|
161
|
+
const names = typeof key === "string" ? [key] : Array.isArray(key) ? key : null;
|
|
162
|
+
drop(names ?? key, store ?? currentResourceCache());
|
|
163
|
+
if (names && !store) tellOtherTabs(names);
|
|
164
|
+
}
|
|
165
|
+
function drop(what, store) {
|
|
166
|
+
const matches = Array.isArray(what) ? (k) => what.some((n) => k === n || k.startsWith(n + ":")) : what;
|
|
167
|
+
for (const k of [...store.keys()]) if (matches(k)) store.delete(k);
|
|
168
|
+
reloadMounted();
|
|
169
|
+
}
|
|
170
|
+
var TABS_KEY = "fluixi:revalidate";
|
|
171
|
+
function tellOtherTabs(names) {
|
|
172
|
+
try {
|
|
173
|
+
localStorage.setItem(TABS_KEY, JSON.stringify({ names, at: Date.now() + Math.random() }));
|
|
174
|
+
} catch {
|
|
174
175
|
}
|
|
175
|
-
setRevalidationVersion((v) => v + 1);
|
|
176
176
|
}
|
|
177
|
+
if (typeof window !== "undefined") {
|
|
178
|
+
window.addEventListener("storage", (event) => {
|
|
179
|
+
if (event.key !== TABS_KEY || !event.newValue) return;
|
|
180
|
+
try {
|
|
181
|
+
const names = JSON.parse(event.newValue).names;
|
|
182
|
+
if (Array.isArray(names) && names.every((n) => typeof n === "string")) drop(names, currentResourceCache());
|
|
183
|
+
} catch {
|
|
184
|
+
}
|
|
185
|
+
});
|
|
186
|
+
}
|
|
187
|
+
globalThis[/* @__PURE__ */ Symbol.for("fluixi.revalidate")] = (names) => revalidate(names);
|
|
177
188
|
function createAsync(fetcher, source) {
|
|
178
189
|
const [data] = createResource(source || (() => true), fetcher);
|
|
179
190
|
return data;
|
|
@@ -188,19 +199,39 @@ function getSubmissionSignal(url) {
|
|
|
188
199
|
}
|
|
189
200
|
return submissionState.get(url);
|
|
190
201
|
}
|
|
191
|
-
|
|
202
|
+
var submissionsState = /* @__PURE__ */ new Map();
|
|
203
|
+
function getSubmissionsSignal(url) {
|
|
204
|
+
if (!submissionsState.has(url)) submissionsState.set(url, createSignal([]));
|
|
205
|
+
return submissionsState.get(url);
|
|
206
|
+
}
|
|
207
|
+
function action(fn, name, options = {}) {
|
|
192
208
|
const actionUrl = name || fn.name || "action";
|
|
193
209
|
const submit = async (input) => {
|
|
194
210
|
const [, setSubmission] = getSubmissionSignal(actionUrl);
|
|
195
|
-
const
|
|
196
|
-
|
|
197
|
-
|
|
211
|
+
const [, setSubmissions] = getSubmissionsSignal(actionUrl);
|
|
212
|
+
let entry;
|
|
213
|
+
const drop2 = () => setSubmissions((list) => list.filter((s) => s !== entry));
|
|
214
|
+
const settle = (next) => {
|
|
215
|
+
setSubmissions((list) => list.map((s) => s === entry ? next : s));
|
|
216
|
+
entry = next;
|
|
217
|
+
};
|
|
218
|
+
const clear = () => {
|
|
219
|
+
setSubmission(void 0);
|
|
220
|
+
drop2();
|
|
221
|
+
};
|
|
222
|
+
const retry = () => {
|
|
223
|
+
drop2();
|
|
224
|
+
return submit(input);
|
|
225
|
+
};
|
|
226
|
+
entry = {
|
|
198
227
|
input,
|
|
199
228
|
// Approximate type for tracking
|
|
200
229
|
pending: true,
|
|
201
230
|
clear,
|
|
202
231
|
retry
|
|
203
|
-
}
|
|
232
|
+
};
|
|
233
|
+
setSubmission(entry);
|
|
234
|
+
setSubmissions((list) => [...list, entry]);
|
|
204
235
|
try {
|
|
205
236
|
const result = await fn(input);
|
|
206
237
|
setSubmission({
|
|
@@ -210,26 +241,35 @@ function action(fn, name) {
|
|
|
210
241
|
clear,
|
|
211
242
|
retry
|
|
212
243
|
});
|
|
244
|
+
drop2();
|
|
245
|
+
const stale = typeof options.invalidates === "function" ? options.invalidates(result) : options.invalidates;
|
|
246
|
+
for (const key of stale ?? []) revalidate(key);
|
|
213
247
|
return result;
|
|
214
248
|
} catch (error) {
|
|
215
|
-
|
|
249
|
+
const failed = {
|
|
216
250
|
input,
|
|
217
251
|
error,
|
|
218
252
|
pending: false,
|
|
219
253
|
clear,
|
|
220
254
|
retry
|
|
221
|
-
}
|
|
255
|
+
};
|
|
256
|
+
setSubmission(failed);
|
|
257
|
+
settle(failed);
|
|
222
258
|
throw error;
|
|
223
259
|
}
|
|
224
260
|
};
|
|
225
261
|
submit.url = actionUrl;
|
|
226
|
-
submit.with = (args) => action((...a) => fn(args, ...a), name);
|
|
262
|
+
submit.with = (args) => action((...a) => fn(args, ...a), name, options);
|
|
227
263
|
return submit;
|
|
228
264
|
}
|
|
229
265
|
function useSubmission(actionFn) {
|
|
230
266
|
const [submission] = getSubmissionSignal(actionFn.url);
|
|
231
267
|
return submission;
|
|
232
268
|
}
|
|
269
|
+
function useSubmissions(actionFn) {
|
|
270
|
+
const [submissions] = getSubmissionsSignal(actionFn.url);
|
|
271
|
+
return submissions;
|
|
272
|
+
}
|
|
233
273
|
function useAction(actionFn) {
|
|
234
274
|
return actionFn;
|
|
235
275
|
}
|
|
@@ -237,7 +277,13 @@ var RouteDataContext = createContext(void 0, "route-data");
|
|
|
237
277
|
var RouteDataProvider = RouteDataContext.Provider;
|
|
238
278
|
|
|
239
279
|
// src/lib/router/index.ts
|
|
240
|
-
import {
|
|
280
|
+
import {
|
|
281
|
+
createMemoryHistory,
|
|
282
|
+
createBrowserHistory as createBrowserHistory2,
|
|
283
|
+
matchRoutes as matchRoutes2,
|
|
284
|
+
matchPath as matchPath2
|
|
285
|
+
} from "@fluixi/router";
|
|
286
|
+
import { runWithOwner as runWithOwner2 } from "@fluixi/reactive/signal";
|
|
241
287
|
var RouterContext = createContext2(void 0, "router");
|
|
242
288
|
var OutletContext = createContext2(void 0, "outlet");
|
|
243
289
|
var LevelParamsContext = createContext2(void 0, "route-params");
|
|
@@ -250,11 +296,33 @@ function renderLayer(m, depth, base) {
|
|
|
250
296
|
onCleanup(() => {
|
|
251
297
|
cancelled = true;
|
|
252
298
|
});
|
|
253
|
-
const owner =
|
|
254
|
-
const
|
|
255
|
-
|
|
256
|
-
)
|
|
257
|
-
|
|
299
|
+
const owner = getOwner2();
|
|
300
|
+
const router = useContext2(RouterContext);
|
|
301
|
+
let watching = false;
|
|
302
|
+
const trackDeps = (deps) => {
|
|
303
|
+
if (watching || cancelled) return;
|
|
304
|
+
watching = true;
|
|
305
|
+
runWithOwner(owner, () => {
|
|
306
|
+
let first = true;
|
|
307
|
+
createEffect(() => {
|
|
308
|
+
deps();
|
|
309
|
+
if (first) first = false;
|
|
310
|
+
else untrack(() => void refetch());
|
|
311
|
+
});
|
|
312
|
+
});
|
|
313
|
+
};
|
|
314
|
+
const [resource, { refetch }] = createResource2(() => {
|
|
315
|
+
const result = loader({ params: base.params, location: base.location }, owner, () => cancelled, trackDeps);
|
|
316
|
+
return router ? router.trackLoad(result) : result;
|
|
317
|
+
});
|
|
318
|
+
onCleanup(onRevalidate(() => void refetch()));
|
|
319
|
+
data = () => {
|
|
320
|
+
const error = resource.error;
|
|
321
|
+
if (error !== void 0 && error !== null) throw error;
|
|
322
|
+
return resource();
|
|
323
|
+
};
|
|
324
|
+
Object.defineProperty(data, "loading", { get: () => resource.loading });
|
|
325
|
+
Object.defineProperty(data, "state", { get: () => resource.state });
|
|
258
326
|
}
|
|
259
327
|
const buildPage = () => RouteDataContext2.Provider({
|
|
260
328
|
value: data,
|
|
@@ -272,12 +340,15 @@ function renderLayer(m, depth, base) {
|
|
|
272
340
|
});
|
|
273
341
|
}
|
|
274
342
|
});
|
|
275
|
-
if (!data) return buildPage();
|
|
343
|
+
if (!data) return { view: buildPage(), ready: () => true };
|
|
276
344
|
const res = data;
|
|
277
|
-
const isLoading = () =>
|
|
345
|
+
const isLoading = () => {
|
|
346
|
+
const state = res.state;
|
|
347
|
+
return state === void 0 ? res.loading : state === "pending" || state === "unresolved";
|
|
348
|
+
};
|
|
278
349
|
const [ready, setReady] = createSignal2(untrack(() => !isLoading()));
|
|
279
350
|
createEffect(() => setReady(!isLoading()));
|
|
280
|
-
return createMemo(() => ready() ? buildPage() : null);
|
|
351
|
+
return { view: createMemo(() => ready() ? buildPage() : null), ready };
|
|
281
352
|
}
|
|
282
353
|
function renderChild(ctx) {
|
|
283
354
|
const childIdx = ctx.depth + 1;
|
|
@@ -288,17 +359,43 @@ function renderChild(ctx) {
|
|
|
288
359
|
const c = ctx.matched()[childIdx]?.component;
|
|
289
360
|
if (untrack(childComp) !== c) setChildComp(() => c);
|
|
290
361
|
});
|
|
291
|
-
|
|
362
|
+
const owner = getOwner2();
|
|
363
|
+
let shown = null;
|
|
364
|
+
let pending = null;
|
|
365
|
+
const drop2 = (layer) => layer?.dispose();
|
|
366
|
+
onCleanup(() => {
|
|
367
|
+
drop2(shown);
|
|
368
|
+
drop2(pending);
|
|
369
|
+
shown = pending = null;
|
|
370
|
+
});
|
|
371
|
+
const incoming = createMemo(() => {
|
|
292
372
|
const component = childComp();
|
|
293
|
-
if (!component)
|
|
373
|
+
if (!component) return null;
|
|
374
|
+
const m = untrack(() => ctx.matched())[childIdx];
|
|
375
|
+
return runWithOwner(
|
|
376
|
+
owner,
|
|
377
|
+
() => createRoot((dispose) => ({
|
|
378
|
+
...renderLayer(m, childIdx, { matched: ctx.matched, params: ctx.params, location: ctx.location }),
|
|
379
|
+
dispose
|
|
380
|
+
}))
|
|
381
|
+
);
|
|
382
|
+
});
|
|
383
|
+
return createMemo(() => {
|
|
384
|
+
const next = incoming();
|
|
385
|
+
if (!next) {
|
|
386
|
+
drop2(shown);
|
|
387
|
+
drop2(pending);
|
|
388
|
+
shown = pending = null;
|
|
294
389
|
return ctx.notFound ? ctx.notFound() : null;
|
|
295
390
|
}
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
391
|
+
if (next === shown) return shown.view;
|
|
392
|
+
if (pending && pending !== next) drop2(pending);
|
|
393
|
+
pending = next;
|
|
394
|
+
if (shown && !next.ready()) return shown.view;
|
|
395
|
+
drop2(shown);
|
|
396
|
+
shown = next;
|
|
397
|
+
pending = null;
|
|
398
|
+
return shown.view;
|
|
302
399
|
});
|
|
303
400
|
}
|
|
304
401
|
function renderNotFound(notFound) {
|
|
@@ -333,6 +430,8 @@ function Router(props) {
|
|
|
333
430
|
history
|
|
334
431
|
});
|
|
335
432
|
const [state, setState] = createSignal2(router.state());
|
|
433
|
+
const [navigating, setNavigating] = createSignal2(false);
|
|
434
|
+
const [loads, setLoads] = createSignal2(0);
|
|
336
435
|
let navigationId = 0;
|
|
337
436
|
const takeMode = () => {
|
|
338
437
|
const mode = pendingTransitionMode ?? (props.transition ?? "auto");
|
|
@@ -342,12 +441,15 @@ function Router(props) {
|
|
|
342
441
|
const unsub = router.subscribe((next) => {
|
|
343
442
|
const id = ++navigationId;
|
|
344
443
|
const mode = takeMode();
|
|
444
|
+
setNavigating(true);
|
|
345
445
|
const prepared = prepareComponents(
|
|
346
446
|
(next.match?.matched ?? []).map((m) => m.component).filter(Boolean)
|
|
347
447
|
);
|
|
348
448
|
const commit = () => {
|
|
349
449
|
setState(next);
|
|
350
|
-
|
|
450
|
+
const flushed = flush();
|
|
451
|
+
if (id === navigationId) setNavigating(false);
|
|
452
|
+
return flushed;
|
|
351
453
|
};
|
|
352
454
|
if (!prepared) {
|
|
353
455
|
void runTransition(mode, commit);
|
|
@@ -369,7 +471,18 @@ function Router(props) {
|
|
|
369
471
|
const ctx = {
|
|
370
472
|
router,
|
|
371
473
|
location: createMemo(() => state().location),
|
|
372
|
-
params: createMemo(() => state().match?.params ?? {})
|
|
474
|
+
params: createMemo(() => state().match?.params ?? {}),
|
|
475
|
+
isRouting: () => navigating() || loads() > 0,
|
|
476
|
+
// Counted by the promise, not by an owner: a load a newer navigation superseded still
|
|
477
|
+
// settles and uncounts itself, and a resource seeded from the server never calls it.
|
|
478
|
+
trackLoad(result) {
|
|
479
|
+
if (result && typeof result.finally === "function") {
|
|
480
|
+
setLoads((n) => n + 1);
|
|
481
|
+
void result.finally(() => setLoads((n) => n - 1)).catch(() => {
|
|
482
|
+
});
|
|
483
|
+
}
|
|
484
|
+
return result;
|
|
485
|
+
}
|
|
373
486
|
};
|
|
374
487
|
const root = {
|
|
375
488
|
depth: -1,
|
|
@@ -392,6 +505,21 @@ function Outlet() {
|
|
|
392
505
|
if (!ctx) return null;
|
|
393
506
|
return renderChild(ctx);
|
|
394
507
|
}
|
|
508
|
+
function useIsRouting(options = {}) {
|
|
509
|
+
const routing = useContext2(RouterContext)?.isRouting ?? (() => false);
|
|
510
|
+
const delay = options.delay ?? 0;
|
|
511
|
+
if (delay <= 0) return routing;
|
|
512
|
+
const [late, setLate] = createSignal2(false);
|
|
513
|
+
createEffect(() => {
|
|
514
|
+
if (!routing()) {
|
|
515
|
+
setLate(false);
|
|
516
|
+
return;
|
|
517
|
+
}
|
|
518
|
+
const timer = setTimeout(() => setLate(true), delay);
|
|
519
|
+
onCleanup(() => clearTimeout(timer));
|
|
520
|
+
});
|
|
521
|
+
return () => routing() && late();
|
|
522
|
+
}
|
|
395
523
|
function Redirect(props) {
|
|
396
524
|
const ctx = useContext2(RouterContext);
|
|
397
525
|
if (ctx && typeof window !== "undefined") {
|
|
@@ -407,7 +535,9 @@ var _ssrRouterStub = {
|
|
|
407
535
|
router: { navigate: () => {
|
|
408
536
|
} },
|
|
409
537
|
location: () => ({ pathname: "", search: "", hash: "", query: {} }),
|
|
410
|
-
params: () => ({})
|
|
538
|
+
params: () => ({}),
|
|
539
|
+
isRouting: () => false,
|
|
540
|
+
trackLoad: (result) => result
|
|
411
541
|
};
|
|
412
542
|
function useRouter() {
|
|
413
543
|
const ctx = useContext2(RouterContext);
|
|
@@ -522,18 +652,31 @@ var LINK_OWN_PROPS = /* @__PURE__ */ new Set([
|
|
|
522
652
|
]);
|
|
523
653
|
function Link(props) {
|
|
524
654
|
const ctx = useContext2(RouterContext);
|
|
525
|
-
const navigate = () => ctx
|
|
655
|
+
const navigate = () => ctx.router.navigate(read(props.href) ?? "", { replace: read(props.replace) });
|
|
526
656
|
const a = createNativeElement("a");
|
|
527
657
|
setAttribute(a, "href", read(props.href) ?? "");
|
|
528
658
|
if (props.slot) setAttribute(a, "slot", read(props.slot));
|
|
529
659
|
for (const k of Object.keys(props)) {
|
|
530
660
|
if (LINK_OWN_PROPS.has(k)) continue;
|
|
531
661
|
const v = props[k];
|
|
532
|
-
if (
|
|
662
|
+
if (typeof v === "function") {
|
|
663
|
+
if (/^on[A-Z]/.test(k)) continue;
|
|
664
|
+
const read2 = v;
|
|
665
|
+
const apply = () => {
|
|
666
|
+
const value = read2();
|
|
667
|
+
if (value == null || value === false) a.removeAttribute?.(k);
|
|
668
|
+
else setAttribute(a, k, String(value));
|
|
669
|
+
};
|
|
670
|
+
if (typeof a.addEventListener === "function") createEffect(apply);
|
|
671
|
+
else apply();
|
|
672
|
+
continue;
|
|
673
|
+
}
|
|
674
|
+
if (v != null) setAttribute(a, k, String(v));
|
|
533
675
|
}
|
|
534
676
|
if (typeof a.addEventListener === "function") {
|
|
535
677
|
a.addEventListener("click", (e) => {
|
|
536
678
|
if (e.metaKey || e.ctrlKey || e.shiftKey || e.altKey) return;
|
|
679
|
+
if (!ctx) return;
|
|
537
680
|
e.preventDefault();
|
|
538
681
|
navigate();
|
|
539
682
|
});
|
|
@@ -612,10 +755,11 @@ export {
|
|
|
612
755
|
prefersReducedMotion,
|
|
613
756
|
preloadRoutes,
|
|
614
757
|
revalidate,
|
|
615
|
-
runWithOwner,
|
|
758
|
+
runWithOwner2 as runWithOwner,
|
|
616
759
|
select,
|
|
617
760
|
supportsViewTransitions,
|
|
618
761
|
useAction,
|
|
762
|
+
useIsRouting,
|
|
619
763
|
useLevelParams,
|
|
620
764
|
useLinkNavigation,
|
|
621
765
|
useLocation,
|
|
@@ -627,5 +771,6 @@ export {
|
|
|
627
771
|
useRouteData,
|
|
628
772
|
useRouter,
|
|
629
773
|
useSearchParams,
|
|
630
|
-
useSubmission
|
|
774
|
+
useSubmission,
|
|
775
|
+
useSubmissions
|
|
631
776
|
};
|
|
@@ -21,91 +21,28 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
|
|
|
21
21
|
var context_exports = {};
|
|
22
22
|
__export(context_exports, {
|
|
23
23
|
composeProviders: () => composeProviders,
|
|
24
|
-
createConsumer: () => createConsumer,
|
|
25
24
|
createContext: () => createContext,
|
|
26
|
-
createContextWithProvider: () => createContextWithProvider,
|
|
27
25
|
createProvider: () => createProvider,
|
|
28
|
-
|
|
29
|
-
|
|
26
|
+
requireContext: () => requireContext,
|
|
27
|
+
useContext: () => useContext
|
|
30
28
|
});
|
|
31
29
|
module.exports = __toCommonJS(context_exports);
|
|
32
30
|
var import_dom = require("@fluixi/dom");
|
|
33
31
|
var import_signal = require("@fluixi/reactive/signal");
|
|
34
|
-
var import_signal2 = require("@fluixi/reactive/signal");
|
|
35
|
-
var _warnedEagerProvider = false;
|
|
36
|
-
function warnEagerProvider() {
|
|
37
|
-
if (_warnedEagerProvider) return;
|
|
38
|
-
_warnedEagerProvider = true;
|
|
39
|
-
if (typeof process !== "undefined" && true) return;
|
|
40
|
-
console.warn(
|
|
41
|
-
"[fluixi] createProvider({ context, value, children }) reads `children` eagerly: the object literal materialises `children` BEFORE the context is stamped, so a routed <Outlet/> that has siblings inside the provider renders detached and its descendants see no context under SSR. Use the lazy form instead:\n createProvider(Context, value, props) // children stays a getter\n // or JSX: <Context.Provider value={...}>{props.children}</Context.Provider>"
|
|
42
|
-
);
|
|
43
|
-
}
|
|
44
|
-
function createProvider(a, value, childProps) {
|
|
45
|
-
const isLazyForm = !!a?.Provider;
|
|
46
|
-
const context = isLazyForm ? a : a.context;
|
|
47
|
-
const rawValue = isLazyForm ? value : a.value;
|
|
48
|
-
const debug = isLazyForm ? false : a.debug ?? false;
|
|
49
|
-
if (!isLazyForm) warnEagerProvider();
|
|
50
|
-
const resolvedValue = typeof rawValue === "function" ? rawValue() : rawValue;
|
|
51
|
-
const sourceProps = isLazyForm ? childProps : a;
|
|
52
|
-
return context.Provider({
|
|
53
|
-
value: resolvedValue,
|
|
54
|
-
get children() {
|
|
55
|
-
return sourceProps?.children;
|
|
56
|
-
},
|
|
57
|
-
debug
|
|
58
|
-
});
|
|
59
|
-
}
|
|
60
|
-
function createContextWithProvider(defaultValue) {
|
|
61
|
-
const context = createContext(defaultValue);
|
|
62
|
-
const provider = (props) => {
|
|
63
|
-
return createProvider(context, props.value, props);
|
|
64
|
-
};
|
|
65
|
-
return [context, provider];
|
|
66
|
-
}
|
|
67
|
-
function composeProviders(contexts, children) {
|
|
68
|
-
if (contexts.length === 0) {
|
|
69
|
-
return (0, import_signal2.readChildren)(() => children);
|
|
70
|
-
}
|
|
71
|
-
const [context, value] = contexts[0];
|
|
72
|
-
const remaining = contexts.slice(1);
|
|
73
|
-
return createProvider(context, value, {
|
|
74
|
-
get children() {
|
|
75
|
-
return composeProviders(remaining, children);
|
|
76
|
-
}
|
|
77
|
-
});
|
|
78
|
-
}
|
|
79
|
-
function createConsumer(context) {
|
|
80
|
-
return (props) => {
|
|
81
|
-
const value = useContext(context);
|
|
82
|
-
return props.children(value);
|
|
83
|
-
};
|
|
84
|
-
}
|
|
85
|
-
function useProvide(context, factory) {
|
|
86
|
-
const existing = useContext(context);
|
|
87
|
-
if (existing === context.defaultValue) {
|
|
88
|
-
return factory();
|
|
89
|
-
}
|
|
90
|
-
return existing;
|
|
91
|
-
}
|
|
92
32
|
function createContext(defaultValue, name) {
|
|
93
33
|
const context = (0, import_signal.createContext)(defaultValue, name);
|
|
94
|
-
const Provider = (props) =>
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
34
|
+
const Provider = (props) => (
|
|
35
|
+
// Children stay a getter: the reactive Provider reads them after stamping the value on
|
|
36
|
+
// its owner. Reading `props.children` here would render them, and any <Outlet/> in them,
|
|
37
|
+
// before the context exists.
|
|
38
|
+
context.Provider({
|
|
98
39
|
value: props.value,
|
|
99
40
|
get children() {
|
|
100
41
|
return props.children;
|
|
101
42
|
},
|
|
102
43
|
debug: props.debug
|
|
103
|
-
})
|
|
104
|
-
|
|
105
|
-
if (typeof Symbol !== "undefined" && Symbol.for) {
|
|
106
|
-
Provider.$$typeof = /* @__PURE__ */ Symbol.for("react.provider");
|
|
107
|
-
}
|
|
108
|
-
Provider.$$typeof = /* @__PURE__ */ Symbol.for("react.provider");
|
|
44
|
+
})
|
|
45
|
+
);
|
|
109
46
|
return {
|
|
110
47
|
id: context.id,
|
|
111
48
|
Provider: (0, import_dom.asProvider)(Provider),
|
|
@@ -116,3 +53,29 @@ function useContext(context) {
|
|
|
116
53
|
const value = (0, import_signal.useContext)(context);
|
|
117
54
|
return value !== void 0 ? value : context.defaultValue;
|
|
118
55
|
}
|
|
56
|
+
function createProvider(context, value, props) {
|
|
57
|
+
const resolved = typeof value === "function" ? value() : value;
|
|
58
|
+
return context.Provider({
|
|
59
|
+
value: resolved,
|
|
60
|
+
get children() {
|
|
61
|
+
return props.children;
|
|
62
|
+
}
|
|
63
|
+
});
|
|
64
|
+
}
|
|
65
|
+
function composeProviders(providers, props) {
|
|
66
|
+
const outermost = providers.reduceRight(
|
|
67
|
+
(inner, [context, value]) => ({
|
|
68
|
+
get children() {
|
|
69
|
+
return createProvider(context, value, inner);
|
|
70
|
+
}
|
|
71
|
+
}),
|
|
72
|
+
props
|
|
73
|
+
);
|
|
74
|
+
return outermost.children;
|
|
75
|
+
}
|
|
76
|
+
function requireContext(context, message) {
|
|
77
|
+
for (let owner = (0, import_signal.getOwner)(); owner; owner = owner.parent) {
|
|
78
|
+
if (owner.contexts?.has(context.id)) return useContext(context);
|
|
79
|
+
}
|
|
80
|
+
throw new Error(message ?? `[fluixi] No Provider for ${context.id.description ?? "this context"} above this component.`);
|
|
81
|
+
}
|