@fluixi/core 1.0.0-alpha.91 → 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-I66EJO2Y.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-SKXDXBGV.mjs +0 -133
|
@@ -1,4 +1,4 @@
|
|
|
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
|
|
|
3
3
|
// src/lib/router/index.ts
|
|
4
4
|
import {
|
|
@@ -6,8 +6,10 @@ import {
|
|
|
6
6
|
createMemo as createMemo2,
|
|
7
7
|
createResource as createResource3,
|
|
8
8
|
createEffect,
|
|
9
|
-
|
|
9
|
+
createRoot,
|
|
10
|
+
getOwner as getOwner2,
|
|
10
11
|
onCleanup,
|
|
12
|
+
runWithOwner,
|
|
11
13
|
untrack as untrack2,
|
|
12
14
|
flush
|
|
13
15
|
} from "@fluixi/reactive/signal";
|
|
@@ -76,92 +78,35 @@ import {
|
|
|
76
78
|
matchRoutes,
|
|
77
79
|
matchPath
|
|
78
80
|
} from "@fluixi/router";
|
|
79
|
-
import {
|
|
80
|
-
createMemoryHistory,
|
|
81
|
-
createBrowserHistory as createBrowserHistory2,
|
|
82
|
-
matchRoutes as matchRoutes2,
|
|
83
|
-
matchPath as matchPath2
|
|
84
|
-
} from "@fluixi/router";
|
|
85
81
|
|
|
86
82
|
// src/lib/router/data.ts
|
|
87
83
|
import {
|
|
88
84
|
createResource,
|
|
89
85
|
createSignal
|
|
90
86
|
} from "@fluixi/reactive/signal";
|
|
91
|
-
|
|
92
|
-
// src/lib/server/hydration.ts
|
|
93
|
-
import { isServer as domIsServer } from "@fluixi/dom";
|
|
94
|
-
var hydrating = false;
|
|
95
|
-
var hydrationDataMap = /* @__PURE__ */ new Map();
|
|
96
|
-
function isHydrating() {
|
|
97
|
-
return hydrating;
|
|
98
|
-
}
|
|
99
|
-
function setHydrationData(key, data) {
|
|
100
|
-
hydrationDataMap.set(key, data);
|
|
101
|
-
}
|
|
102
|
-
function getHydrationData(key) {
|
|
103
|
-
return hydrationDataMap.get(key);
|
|
104
|
-
}
|
|
105
|
-
function clearHydrationData() {
|
|
106
|
-
hydrationDataMap.clear();
|
|
107
|
-
}
|
|
108
|
-
function cleanupHydration() {
|
|
109
|
-
if (typeof window === "undefined") {
|
|
110
|
-
return;
|
|
111
|
-
}
|
|
112
|
-
const script = document.getElementById("__FLUIXI_HYDRATION__");
|
|
113
|
-
if (script) {
|
|
114
|
-
script.remove();
|
|
115
|
-
}
|
|
116
|
-
const walker = document.createTreeWalker(
|
|
117
|
-
document.body,
|
|
118
|
-
NodeFilter.SHOW_COMMENT,
|
|
119
|
-
null
|
|
120
|
-
);
|
|
121
|
-
const comments = [];
|
|
122
|
-
let node;
|
|
123
|
-
while (node = walker.nextNode()) {
|
|
124
|
-
const comment = node;
|
|
125
|
-
const text = comment.nodeValue || "";
|
|
126
|
-
if (text.startsWith("#") || text.startsWith("/")) {
|
|
127
|
-
comments.push(comment);
|
|
128
|
-
}
|
|
129
|
-
}
|
|
130
|
-
comments.forEach((comment) => comment.remove());
|
|
131
|
-
clearHydrationData();
|
|
132
|
-
}
|
|
133
|
-
if (typeof window !== "undefined") {
|
|
134
|
-
window.addEventListener("load", () => {
|
|
135
|
-
setTimeout(cleanupHydration, 100);
|
|
136
|
-
});
|
|
137
|
-
}
|
|
138
|
-
function isServerEnvironment() {
|
|
139
|
-
return domIsServer();
|
|
140
|
-
}
|
|
87
|
+
import { currentResourceCache } from "@fluixi/reactive/signal";
|
|
141
88
|
|
|
142
89
|
// src/lib/context/context.ts
|
|
143
90
|
import { asProvider } from "@fluixi/dom";
|
|
144
|
-
import { createContext as createReactiveContext, useContext as useReactiveContext } from "@fluixi/reactive/signal";
|
|
145
91
|
import {
|
|
146
|
-
|
|
92
|
+
createContext as createReactiveContext,
|
|
93
|
+
getOwner,
|
|
94
|
+
useContext as useReactiveContext
|
|
147
95
|
} from "@fluixi/reactive/signal";
|
|
148
96
|
function createContext(defaultValue, name) {
|
|
149
97
|
const context = createReactiveContext(defaultValue, name);
|
|
150
|
-
const Provider = (props) =>
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
98
|
+
const Provider = (props) => (
|
|
99
|
+
// Children stay a getter: the reactive Provider reads them after stamping the value on
|
|
100
|
+
// its owner. Reading `props.children` here would render them, and any <Outlet/> in them,
|
|
101
|
+
// before the context exists.
|
|
102
|
+
context.Provider({
|
|
154
103
|
value: props.value,
|
|
155
104
|
get children() {
|
|
156
105
|
return props.children;
|
|
157
106
|
},
|
|
158
107
|
debug: props.debug
|
|
159
|
-
})
|
|
160
|
-
|
|
161
|
-
if (typeof Symbol !== "undefined" && Symbol.for) {
|
|
162
|
-
Provider.$$typeof = /* @__PURE__ */ Symbol.for("react.provider");
|
|
163
|
-
}
|
|
164
|
-
Provider.$$typeof = /* @__PURE__ */ Symbol.for("react.provider");
|
|
108
|
+
})
|
|
109
|
+
);
|
|
165
110
|
return {
|
|
166
111
|
id: context.id,
|
|
167
112
|
Provider: asProvider(Provider),
|
|
@@ -170,53 +115,73 @@ function createContext(defaultValue, name) {
|
|
|
170
115
|
}
|
|
171
116
|
|
|
172
117
|
// src/lib/router/data.ts
|
|
173
|
-
var
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
return
|
|
118
|
+
var revalidationListeners = /* @__PURE__ */ new Set();
|
|
119
|
+
function onRevalidate(listener) {
|
|
120
|
+
revalidationListeners.add(listener);
|
|
121
|
+
return () => void revalidationListeners.delete(listener);
|
|
122
|
+
}
|
|
123
|
+
var reloadMounted = () => {
|
|
124
|
+
for (const listener of [...revalidationListeners]) listener();
|
|
125
|
+
};
|
|
126
|
+
function cache(fn, name, options = {}) {
|
|
127
|
+
const { ttl = Infinity, staleWhileRevalidate = true } = options;
|
|
128
|
+
return (...args) => {
|
|
129
|
+
const store = options.cache ?? currentResourceCache();
|
|
177
130
|
const key = name + ":" + JSON.stringify(args);
|
|
178
|
-
|
|
179
|
-
const
|
|
180
|
-
if (
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
const promise = Promise.resolve(fn(...args)).then(
|
|
191
|
-
(val) => {
|
|
192
|
-
globalCache.set(key, val);
|
|
193
|
-
inflightRequests.delete(key);
|
|
194
|
-
if (isServerEnvironment()) {
|
|
195
|
-
setHydrationData(key, val);
|
|
131
|
+
const fetchFresh = () => {
|
|
132
|
+
const running = store.inflight.get(key);
|
|
133
|
+
if (running) return running;
|
|
134
|
+
const promise = Promise.resolve(fn(...args)).then(
|
|
135
|
+
(value) => {
|
|
136
|
+
store.set(key, { value, timestamp: Date.now() });
|
|
137
|
+
store.inflight.delete(key);
|
|
138
|
+
return value;
|
|
139
|
+
},
|
|
140
|
+
(error) => {
|
|
141
|
+
store.inflight.delete(key);
|
|
142
|
+
throw error;
|
|
196
143
|
}
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
)
|
|
204
|
-
|
|
205
|
-
|
|
144
|
+
);
|
|
145
|
+
store.inflight.set(key, promise);
|
|
146
|
+
return promise;
|
|
147
|
+
};
|
|
148
|
+
const hit = store.get(key);
|
|
149
|
+
if (hit && (ttl === Infinity || Date.now() - hit.timestamp <= ttl)) return Promise.resolve(hit.value);
|
|
150
|
+
if (hit && staleWhileRevalidate) {
|
|
151
|
+
fetchFresh().then(reloadMounted, () => void 0);
|
|
152
|
+
return Promise.resolve(hit.value);
|
|
153
|
+
}
|
|
154
|
+
return fetchFresh();
|
|
206
155
|
};
|
|
207
156
|
}
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
157
|
+
function revalidate(key, store) {
|
|
158
|
+
const names = typeof key === "string" ? [key] : Array.isArray(key) ? key : null;
|
|
159
|
+
drop(names ?? key, store ?? currentResourceCache());
|
|
160
|
+
if (names && !store) tellOtherTabs(names);
|
|
161
|
+
}
|
|
162
|
+
function drop(what, store) {
|
|
163
|
+
const matches = Array.isArray(what) ? (k) => what.some((n) => k === n || k.startsWith(n + ":")) : what;
|
|
164
|
+
for (const k of [...store.keys()]) if (matches(k)) store.delete(k);
|
|
165
|
+
reloadMounted();
|
|
166
|
+
}
|
|
167
|
+
var TABS_KEY = "fluixi:revalidate";
|
|
168
|
+
function tellOtherTabs(names) {
|
|
169
|
+
try {
|
|
170
|
+
localStorage.setItem(TABS_KEY, JSON.stringify({ names, at: Date.now() + Math.random() }));
|
|
171
|
+
} catch {
|
|
217
172
|
}
|
|
218
|
-
setRevalidationVersion((v) => v + 1);
|
|
219
173
|
}
|
|
174
|
+
if (typeof window !== "undefined") {
|
|
175
|
+
window.addEventListener("storage", (event) => {
|
|
176
|
+
if (event.key !== TABS_KEY || !event.newValue) return;
|
|
177
|
+
try {
|
|
178
|
+
const names = JSON.parse(event.newValue).names;
|
|
179
|
+
if (Array.isArray(names) && names.every((n) => typeof n === "string")) drop(names, currentResourceCache());
|
|
180
|
+
} catch {
|
|
181
|
+
}
|
|
182
|
+
});
|
|
183
|
+
}
|
|
184
|
+
globalThis[/* @__PURE__ */ Symbol.for("fluixi.revalidate")] = (names) => revalidate(names);
|
|
220
185
|
function createAsync(fetcher, source) {
|
|
221
186
|
const [data] = createResource(source || (() => true), fetcher);
|
|
222
187
|
return data;
|
|
@@ -231,19 +196,39 @@ function getSubmissionSignal(url) {
|
|
|
231
196
|
}
|
|
232
197
|
return submissionState.get(url);
|
|
233
198
|
}
|
|
234
|
-
|
|
199
|
+
var submissionsState = /* @__PURE__ */ new Map();
|
|
200
|
+
function getSubmissionsSignal(url) {
|
|
201
|
+
if (!submissionsState.has(url)) submissionsState.set(url, createSignal([]));
|
|
202
|
+
return submissionsState.get(url);
|
|
203
|
+
}
|
|
204
|
+
function action(fn, name, options = {}) {
|
|
235
205
|
const actionUrl = name || fn.name || "action";
|
|
236
206
|
const submit = async (input) => {
|
|
237
207
|
const [, setSubmission] = getSubmissionSignal(actionUrl);
|
|
238
|
-
const
|
|
239
|
-
|
|
240
|
-
|
|
208
|
+
const [, setSubmissions] = getSubmissionsSignal(actionUrl);
|
|
209
|
+
let entry;
|
|
210
|
+
const drop2 = () => setSubmissions((list) => list.filter((s) => s !== entry));
|
|
211
|
+
const settle = (next) => {
|
|
212
|
+
setSubmissions((list) => list.map((s) => s === entry ? next : s));
|
|
213
|
+
entry = next;
|
|
214
|
+
};
|
|
215
|
+
const clear = () => {
|
|
216
|
+
setSubmission(void 0);
|
|
217
|
+
drop2();
|
|
218
|
+
};
|
|
219
|
+
const retry = () => {
|
|
220
|
+
drop2();
|
|
221
|
+
return submit(input);
|
|
222
|
+
};
|
|
223
|
+
entry = {
|
|
241
224
|
input,
|
|
242
225
|
// Approximate type for tracking
|
|
243
226
|
pending: true,
|
|
244
227
|
clear,
|
|
245
228
|
retry
|
|
246
|
-
}
|
|
229
|
+
};
|
|
230
|
+
setSubmission(entry);
|
|
231
|
+
setSubmissions((list) => [...list, entry]);
|
|
247
232
|
try {
|
|
248
233
|
const result = await fn(input);
|
|
249
234
|
setSubmission({
|
|
@@ -253,32 +238,49 @@ function action(fn, name) {
|
|
|
253
238
|
clear,
|
|
254
239
|
retry
|
|
255
240
|
});
|
|
241
|
+
drop2();
|
|
242
|
+
const stale = typeof options.invalidates === "function" ? options.invalidates(result) : options.invalidates;
|
|
243
|
+
for (const key of stale ?? []) revalidate(key);
|
|
256
244
|
return result;
|
|
257
245
|
} catch (error) {
|
|
258
|
-
|
|
246
|
+
const failed = {
|
|
259
247
|
input,
|
|
260
248
|
error,
|
|
261
249
|
pending: false,
|
|
262
250
|
clear,
|
|
263
251
|
retry
|
|
264
|
-
}
|
|
252
|
+
};
|
|
253
|
+
setSubmission(failed);
|
|
254
|
+
settle(failed);
|
|
265
255
|
throw error;
|
|
266
256
|
}
|
|
267
257
|
};
|
|
268
258
|
submit.url = actionUrl;
|
|
269
|
-
submit.with = (args) => action((...a) => fn(args, ...a), name);
|
|
259
|
+
submit.with = (args) => action((...a) => fn(args, ...a), name, options);
|
|
270
260
|
return submit;
|
|
271
261
|
}
|
|
272
262
|
function useSubmission(actionFn) {
|
|
273
263
|
const [submission] = getSubmissionSignal(actionFn.url);
|
|
274
264
|
return submission;
|
|
275
265
|
}
|
|
266
|
+
function useSubmissions(actionFn) {
|
|
267
|
+
const [submissions] = getSubmissionsSignal(actionFn.url);
|
|
268
|
+
return submissions;
|
|
269
|
+
}
|
|
276
270
|
function useAction(actionFn) {
|
|
277
271
|
return actionFn;
|
|
278
272
|
}
|
|
279
273
|
var RouteDataContext = createContext(void 0, "route-data");
|
|
280
274
|
var RouteDataProvider = RouteDataContext.Provider;
|
|
281
275
|
|
|
276
|
+
// src/lib/router/index.ts
|
|
277
|
+
import {
|
|
278
|
+
createMemoryHistory,
|
|
279
|
+
createBrowserHistory as createBrowserHistory2,
|
|
280
|
+
matchRoutes as matchRoutes2,
|
|
281
|
+
matchPath as matchPath2
|
|
282
|
+
} from "@fluixi/router";
|
|
283
|
+
|
|
282
284
|
// src/lib/render/lazy.ts
|
|
283
285
|
import { createComponent } from "@fluixi/dom";
|
|
284
286
|
import {
|
|
@@ -328,7 +330,7 @@ function lazy(loader, options) {
|
|
|
328
330
|
}
|
|
329
331
|
|
|
330
332
|
// src/lib/router/index.ts
|
|
331
|
-
import { runWithOwner } from "@fluixi/reactive/signal";
|
|
333
|
+
import { runWithOwner as runWithOwner2 } from "@fluixi/reactive/signal";
|
|
332
334
|
var RouterContext = createContext2(void 0, "router");
|
|
333
335
|
var OutletContext = createContext2(void 0, "outlet");
|
|
334
336
|
var LevelParamsContext = createContext2(void 0, "route-params");
|
|
@@ -341,11 +343,33 @@ function renderLayer(m, depth, base) {
|
|
|
341
343
|
onCleanup(() => {
|
|
342
344
|
cancelled = true;
|
|
343
345
|
});
|
|
344
|
-
const owner =
|
|
345
|
-
const
|
|
346
|
-
|
|
347
|
-
)
|
|
348
|
-
|
|
346
|
+
const owner = getOwner2();
|
|
347
|
+
const router = useContext2(RouterContext);
|
|
348
|
+
let watching = false;
|
|
349
|
+
const trackDeps = (deps) => {
|
|
350
|
+
if (watching || cancelled) return;
|
|
351
|
+
watching = true;
|
|
352
|
+
runWithOwner(owner, () => {
|
|
353
|
+
let first = true;
|
|
354
|
+
createEffect(() => {
|
|
355
|
+
deps();
|
|
356
|
+
if (first) first = false;
|
|
357
|
+
else untrack2(() => void refetch());
|
|
358
|
+
});
|
|
359
|
+
});
|
|
360
|
+
};
|
|
361
|
+
const [resource, { refetch }] = createResource3(() => {
|
|
362
|
+
const result = loader({ params: base.params, location: base.location }, owner, () => cancelled, trackDeps);
|
|
363
|
+
return router ? router.trackLoad(result) : result;
|
|
364
|
+
});
|
|
365
|
+
onCleanup(onRevalidate(() => void refetch()));
|
|
366
|
+
data = () => {
|
|
367
|
+
const error = resource.error;
|
|
368
|
+
if (error !== void 0 && error !== null) throw error;
|
|
369
|
+
return resource();
|
|
370
|
+
};
|
|
371
|
+
Object.defineProperty(data, "loading", { get: () => resource.loading });
|
|
372
|
+
Object.defineProperty(data, "state", { get: () => resource.state });
|
|
349
373
|
}
|
|
350
374
|
const buildPage = () => RouteDataContext2.Provider({
|
|
351
375
|
value: data,
|
|
@@ -363,12 +387,15 @@ function renderLayer(m, depth, base) {
|
|
|
363
387
|
});
|
|
364
388
|
}
|
|
365
389
|
});
|
|
366
|
-
if (!data) return buildPage();
|
|
390
|
+
if (!data) return { view: buildPage(), ready: () => true };
|
|
367
391
|
const res = data;
|
|
368
|
-
const isLoading = () =>
|
|
392
|
+
const isLoading = () => {
|
|
393
|
+
const state = res.state;
|
|
394
|
+
return state === void 0 ? res.loading : state === "pending" || state === "unresolved";
|
|
395
|
+
};
|
|
369
396
|
const [ready, setReady] = createSignal2(untrack2(() => !isLoading()));
|
|
370
397
|
createEffect(() => setReady(!isLoading()));
|
|
371
|
-
return createMemo2(() => ready() ? buildPage() : null);
|
|
398
|
+
return { view: createMemo2(() => ready() ? buildPage() : null), ready };
|
|
372
399
|
}
|
|
373
400
|
function renderChild(ctx) {
|
|
374
401
|
const childIdx = ctx.depth + 1;
|
|
@@ -379,17 +406,43 @@ function renderChild(ctx) {
|
|
|
379
406
|
const c = ctx.matched()[childIdx]?.component;
|
|
380
407
|
if (untrack2(childComp) !== c) setChildComp(() => c);
|
|
381
408
|
});
|
|
382
|
-
|
|
409
|
+
const owner = getOwner2();
|
|
410
|
+
let shown = null;
|
|
411
|
+
let pending = null;
|
|
412
|
+
const drop2 = (layer) => layer?.dispose();
|
|
413
|
+
onCleanup(() => {
|
|
414
|
+
drop2(shown);
|
|
415
|
+
drop2(pending);
|
|
416
|
+
shown = pending = null;
|
|
417
|
+
});
|
|
418
|
+
const incoming = createMemo2(() => {
|
|
383
419
|
const component = childComp();
|
|
384
|
-
if (!component)
|
|
420
|
+
if (!component) return null;
|
|
421
|
+
const m = untrack2(() => ctx.matched())[childIdx];
|
|
422
|
+
return runWithOwner(
|
|
423
|
+
owner,
|
|
424
|
+
() => createRoot((dispose) => ({
|
|
425
|
+
...renderLayer(m, childIdx, { matched: ctx.matched, params: ctx.params, location: ctx.location }),
|
|
426
|
+
dispose
|
|
427
|
+
}))
|
|
428
|
+
);
|
|
429
|
+
});
|
|
430
|
+
return createMemo2(() => {
|
|
431
|
+
const next = incoming();
|
|
432
|
+
if (!next) {
|
|
433
|
+
drop2(shown);
|
|
434
|
+
drop2(pending);
|
|
435
|
+
shown = pending = null;
|
|
385
436
|
return ctx.notFound ? ctx.notFound() : null;
|
|
386
437
|
}
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
438
|
+
if (next === shown) return shown.view;
|
|
439
|
+
if (pending && pending !== next) drop2(pending);
|
|
440
|
+
pending = next;
|
|
441
|
+
if (shown && !next.ready()) return shown.view;
|
|
442
|
+
drop2(shown);
|
|
443
|
+
shown = next;
|
|
444
|
+
pending = null;
|
|
445
|
+
return shown.view;
|
|
393
446
|
});
|
|
394
447
|
}
|
|
395
448
|
function renderNotFound(notFound) {
|
|
@@ -424,6 +477,8 @@ function Router(props) {
|
|
|
424
477
|
history
|
|
425
478
|
});
|
|
426
479
|
const [state, setState] = createSignal2(router.state());
|
|
480
|
+
const [navigating, setNavigating] = createSignal2(false);
|
|
481
|
+
const [loads, setLoads] = createSignal2(0);
|
|
427
482
|
let navigationId = 0;
|
|
428
483
|
const takeMode = () => {
|
|
429
484
|
const mode = pendingTransitionMode ?? (props.transition ?? "auto");
|
|
@@ -433,12 +488,15 @@ function Router(props) {
|
|
|
433
488
|
const unsub = router.subscribe((next) => {
|
|
434
489
|
const id = ++navigationId;
|
|
435
490
|
const mode = takeMode();
|
|
491
|
+
setNavigating(true);
|
|
436
492
|
const prepared = prepareComponents(
|
|
437
493
|
(next.match?.matched ?? []).map((m) => m.component).filter(Boolean)
|
|
438
494
|
);
|
|
439
495
|
const commit = () => {
|
|
440
496
|
setState(next);
|
|
441
|
-
|
|
497
|
+
const flushed = flush();
|
|
498
|
+
if (id === navigationId) setNavigating(false);
|
|
499
|
+
return flushed;
|
|
442
500
|
};
|
|
443
501
|
if (!prepared) {
|
|
444
502
|
void runTransition(mode, commit);
|
|
@@ -460,7 +518,18 @@ function Router(props) {
|
|
|
460
518
|
const ctx = {
|
|
461
519
|
router,
|
|
462
520
|
location: createMemo2(() => state().location),
|
|
463
|
-
params: createMemo2(() => state().match?.params ?? {})
|
|
521
|
+
params: createMemo2(() => state().match?.params ?? {}),
|
|
522
|
+
isRouting: () => navigating() || loads() > 0,
|
|
523
|
+
// Counted by the promise, not by an owner: a load a newer navigation superseded still
|
|
524
|
+
// settles and uncounts itself, and a resource seeded from the server never calls it.
|
|
525
|
+
trackLoad(result) {
|
|
526
|
+
if (result && typeof result.finally === "function") {
|
|
527
|
+
setLoads((n) => n + 1);
|
|
528
|
+
void result.finally(() => setLoads((n) => n - 1)).catch(() => {
|
|
529
|
+
});
|
|
530
|
+
}
|
|
531
|
+
return result;
|
|
532
|
+
}
|
|
464
533
|
};
|
|
465
534
|
const root = {
|
|
466
535
|
depth: -1,
|
|
@@ -483,6 +552,21 @@ function Outlet() {
|
|
|
483
552
|
if (!ctx) return null;
|
|
484
553
|
return renderChild(ctx);
|
|
485
554
|
}
|
|
555
|
+
function useIsRouting(options = {}) {
|
|
556
|
+
const routing = useContext2(RouterContext)?.isRouting ?? (() => false);
|
|
557
|
+
const delay = options.delay ?? 0;
|
|
558
|
+
if (delay <= 0) return routing;
|
|
559
|
+
const [late, setLate] = createSignal2(false);
|
|
560
|
+
createEffect(() => {
|
|
561
|
+
if (!routing()) {
|
|
562
|
+
setLate(false);
|
|
563
|
+
return;
|
|
564
|
+
}
|
|
565
|
+
const timer = setTimeout(() => setLate(true), delay);
|
|
566
|
+
onCleanup(() => clearTimeout(timer));
|
|
567
|
+
});
|
|
568
|
+
return () => routing() && late();
|
|
569
|
+
}
|
|
486
570
|
function Redirect(props) {
|
|
487
571
|
const ctx = useContext2(RouterContext);
|
|
488
572
|
if (ctx && typeof window !== "undefined") {
|
|
@@ -498,7 +582,9 @@ var _ssrRouterStub = {
|
|
|
498
582
|
router: { navigate: () => {
|
|
499
583
|
} },
|
|
500
584
|
location: () => ({ pathname: "", search: "", hash: "", query: {} }),
|
|
501
|
-
params: () => ({})
|
|
585
|
+
params: () => ({}),
|
|
586
|
+
isRouting: () => false,
|
|
587
|
+
trackLoad: (result) => result
|
|
502
588
|
};
|
|
503
589
|
function useRouter() {
|
|
504
590
|
const ctx = useContext2(RouterContext);
|
|
@@ -613,18 +699,31 @@ var LINK_OWN_PROPS = /* @__PURE__ */ new Set([
|
|
|
613
699
|
]);
|
|
614
700
|
function Link(props) {
|
|
615
701
|
const ctx = useContext2(RouterContext);
|
|
616
|
-
const navigate = () => ctx
|
|
702
|
+
const navigate = () => ctx.router.navigate(read(props.href) ?? "", { replace: read(props.replace) });
|
|
617
703
|
const a = createNativeElement("a");
|
|
618
704
|
setAttribute(a, "href", read(props.href) ?? "");
|
|
619
705
|
if (props.slot) setAttribute(a, "slot", read(props.slot));
|
|
620
706
|
for (const k of Object.keys(props)) {
|
|
621
707
|
if (LINK_OWN_PROPS.has(k)) continue;
|
|
622
708
|
const v = props[k];
|
|
623
|
-
if (
|
|
709
|
+
if (typeof v === "function") {
|
|
710
|
+
if (/^on[A-Z]/.test(k)) continue;
|
|
711
|
+
const read2 = v;
|
|
712
|
+
const apply = () => {
|
|
713
|
+
const value = read2();
|
|
714
|
+
if (value == null || value === false) a.removeAttribute?.(k);
|
|
715
|
+
else setAttribute(a, k, String(value));
|
|
716
|
+
};
|
|
717
|
+
if (typeof a.addEventListener === "function") createEffect(apply);
|
|
718
|
+
else apply();
|
|
719
|
+
continue;
|
|
720
|
+
}
|
|
721
|
+
if (v != null) setAttribute(a, k, String(v));
|
|
624
722
|
}
|
|
625
723
|
if (typeof a.addEventListener === "function") {
|
|
626
724
|
a.addEventListener("click", (e) => {
|
|
627
725
|
if (e.metaKey || e.ctrlKey || e.shiftKey || e.altKey) return;
|
|
726
|
+
if (!ctx) return;
|
|
628
727
|
e.preventDefault();
|
|
629
728
|
navigate();
|
|
630
729
|
});
|
|
@@ -703,10 +802,11 @@ export {
|
|
|
703
802
|
prefersReducedMotion,
|
|
704
803
|
preloadRoutes,
|
|
705
804
|
revalidate,
|
|
706
|
-
runWithOwner,
|
|
805
|
+
runWithOwner2 as runWithOwner,
|
|
707
806
|
select,
|
|
708
807
|
supportsViewTransitions,
|
|
709
808
|
useAction,
|
|
809
|
+
useIsRouting,
|
|
710
810
|
useLevelParams,
|
|
711
811
|
useLinkNavigation,
|
|
712
812
|
useLocation,
|
|
@@ -718,5 +818,6 @@ export {
|
|
|
718
818
|
useRouteData,
|
|
719
819
|
useRouter,
|
|
720
820
|
useSearchParams,
|
|
721
|
-
useSubmission
|
|
821
|
+
useSubmission,
|
|
822
|
+
useSubmissions
|
|
722
823
|
};
|
|
@@ -1,4 +1,4 @@
|
|
|
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
|
"use strict";
|
|
3
3
|
var __defProp = Object.defineProperty;
|
|
4
4
|
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
@@ -1,4 +1,4 @@
|
|
|
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
|
|
|
3
3
|
// src/lib/server/hydration.ts
|
|
4
4
|
import { isServer as domIsServer } from "@fluixi/dom";
|
|
@@ -0,0 +1,51 @@
|
|
|
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/storage/cache.ts
|
|
21
|
+
var cache_exports = {};
|
|
22
|
+
__export(cache_exports, {
|
|
23
|
+
storageCache: () => storageCache
|
|
24
|
+
});
|
|
25
|
+
module.exports = __toCommonJS(cache_exports);
|
|
26
|
+
function storageCache(storage, options = {}) {
|
|
27
|
+
const inflight = /* @__PURE__ */ new Map();
|
|
28
|
+
return {
|
|
29
|
+
get(key) {
|
|
30
|
+
try {
|
|
31
|
+
const entry = storage.getEntry(key);
|
|
32
|
+
return entry ? { value: entry.value, timestamp: entry.createdAt } : void 0;
|
|
33
|
+
} catch {
|
|
34
|
+
return void 0;
|
|
35
|
+
}
|
|
36
|
+
},
|
|
37
|
+
set(key, entry) {
|
|
38
|
+
try {
|
|
39
|
+
storage.set(key, entry.value, options.ttl !== void 0 ? { ttl: options.ttl } : void 0);
|
|
40
|
+
} catch {
|
|
41
|
+
}
|
|
42
|
+
},
|
|
43
|
+
delete: (key) => storage.remove(key),
|
|
44
|
+
keys: () => storage.keys(),
|
|
45
|
+
clear() {
|
|
46
|
+
storage.clear();
|
|
47
|
+
inflight.clear();
|
|
48
|
+
},
|
|
49
|
+
inflight
|
|
50
|
+
};
|
|
51
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import type { ResourceCache } from '@fluixi/reactive/cached-resource';
|
|
2
|
+
import type { TypedStorage } from '@fluixi/storage';
|
|
3
|
+
/**
|
|
4
|
+
* A `cachedResource` cache kept in a storage, so fetched data outlives the page: session
|
|
5
|
+
* storage for the tab, local storage across visits. Values pass through the storage's
|
|
6
|
+
* serializer, so they must be plain data. In-flight fetches stay in memory.
|
|
7
|
+
*
|
|
8
|
+
* Give it its own namespace, since `clearCachedResources()` clears that storage, and a `ttl`
|
|
9
|
+
* so entries do not pile up after the resource that wrote them is gone.
|
|
10
|
+
*
|
|
11
|
+
* @example
|
|
12
|
+
* const cache = storageCache(useStorage({ scope: 'session', namespace: 'cache' }), { ttl: 10 * 60_000 });
|
|
13
|
+
* const orgs = cachedResource(() => api.get('/orgs'), { name: 'orgs', ttl: 60_000, cache });
|
|
14
|
+
*/
|
|
15
|
+
export declare function storageCache(storage: TypedStorage<any>, options?: {
|
|
16
|
+
ttl?: number;
|
|
17
|
+
}): ResourceCache;
|
|
18
|
+
//# sourceMappingURL=cache.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cache.d.ts","sourceRoot":"","sources":["../../../../src/lib/storage/cache.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,kCAAkC,CAAC;AACtE,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAEpD;;;;;;;;;;;GAWG;AACH,wBAAgB,YAAY,CAAC,OAAO,EAAE,YAAY,CAAC,GAAG,CAAC,EAAE,OAAO,GAAE;IAAE,GAAG,CAAC,EAAE,MAAM,CAAA;CAAO,GAAG,aAAa,CA2BtG"}
|