@floegence/floe-webapp-core 0.67.1 → 0.69.0
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.
|
@@ -5,16 +5,16 @@ import { useResolvedFloeConfig as v } from "./FloeConfigContext.js";
|
|
|
5
5
|
const {
|
|
6
6
|
Provider: x,
|
|
7
7
|
use: C,
|
|
8
|
-
useOptional:
|
|
8
|
+
useOptional: A
|
|
9
9
|
} = u({
|
|
10
10
|
name: "Layout",
|
|
11
11
|
init: g
|
|
12
12
|
});
|
|
13
13
|
function g() {
|
|
14
|
-
const
|
|
14
|
+
const n = v(), i = () => n.config.layout, p = () => typeof window > "u" ? !1 : window.matchMedia(i().mobileQuery).matches, s = n.persist.load(i().storageKey, {}), h = {
|
|
15
15
|
sidebar: {
|
|
16
16
|
width: s.sidebar?.width ?? i().sidebar.defaultWidth,
|
|
17
|
-
activeTab: s.sidebar?.activeTab ?? i().sidebar.defaultActiveTab,
|
|
17
|
+
activeTab: (i().sidebar.persistActiveTab !== !1 ? s.sidebar?.activeTab : void 0) ?? i().sidebar.defaultActiveTab,
|
|
18
18
|
collapsed: s.sidebar?.collapsed ?? i().sidebar.defaultCollapsed
|
|
19
19
|
},
|
|
20
20
|
terminal: {
|
|
@@ -22,44 +22,46 @@ function g() {
|
|
|
22
22
|
height: s.terminal?.height ?? i().terminal.defaultHeight
|
|
23
23
|
},
|
|
24
24
|
isMobile: p()
|
|
25
|
-
}, [
|
|
25
|
+
}, [a, o] = c(h), [l, b] = c({
|
|
26
26
|
motion: "animated",
|
|
27
27
|
revision: 0
|
|
28
28
|
}), m = (e) => Math.max(i().sidebar.clamp.min, Math.min(i().sidebar.clamp.max, e));
|
|
29
29
|
return f(() => {
|
|
30
30
|
const e = {
|
|
31
31
|
sidebar: {
|
|
32
|
-
width:
|
|
33
|
-
|
|
34
|
-
|
|
32
|
+
width: a.sidebar.width,
|
|
33
|
+
...i().sidebar.persistActiveTab !== !1 ? {
|
|
34
|
+
activeTab: a.sidebar.activeTab
|
|
35
|
+
} : {},
|
|
36
|
+
collapsed: a.sidebar.collapsed
|
|
35
37
|
},
|
|
36
38
|
terminal: {
|
|
37
|
-
opened:
|
|
38
|
-
height:
|
|
39
|
+
opened: a.terminal.opened,
|
|
40
|
+
height: a.terminal.height
|
|
39
41
|
}
|
|
40
42
|
};
|
|
41
|
-
|
|
43
|
+
n.persist.debouncedSave(i().storageKey, e);
|
|
42
44
|
}), {
|
|
43
45
|
// Sidebar accessors
|
|
44
|
-
sidebarWidth: () =>
|
|
45
|
-
sidebarActiveTab: () =>
|
|
46
|
-
sidebarCollapsed: () =>
|
|
46
|
+
sidebarWidth: () => a.sidebar.width,
|
|
47
|
+
sidebarActiveTab: () => a.sidebar.activeTab,
|
|
48
|
+
sidebarCollapsed: () => a.sidebar.collapsed,
|
|
47
49
|
sidebarVisibilityMotion: () => l.motion,
|
|
48
50
|
sidebarVisibilityMotionRevision: () => l.revision,
|
|
49
51
|
clampSidebarWidth: m,
|
|
50
52
|
// Sidebar actions
|
|
51
|
-
setSidebarWidth: (e) => o(r((
|
|
52
|
-
|
|
53
|
+
setSidebarWidth: (e) => o(r((t) => {
|
|
54
|
+
t.sidebar.width = m(e);
|
|
53
55
|
})),
|
|
54
|
-
setSidebarActiveTab: (e,
|
|
55
|
-
o(r((
|
|
56
|
-
|
|
57
|
-
})),
|
|
58
|
-
|
|
56
|
+
setSidebarActiveTab: (e, t) => {
|
|
57
|
+
o(r((d) => {
|
|
58
|
+
d.sidebar.activeTab = e, t?.openSidebar !== !1 && (d.sidebar.collapsed = !1);
|
|
59
|
+
})), t?.visibilityMotion === "instant" && b(r((d) => {
|
|
60
|
+
d.motion = "instant", d.revision += 1;
|
|
59
61
|
}));
|
|
60
62
|
},
|
|
61
|
-
setSidebarCollapsed: (e) => o(r((
|
|
62
|
-
|
|
63
|
+
setSidebarCollapsed: (e) => o(r((t) => {
|
|
64
|
+
t.sidebar.collapsed = e;
|
|
63
65
|
})),
|
|
64
66
|
toggleSidebarCollapse: () => o(r((e) => {
|
|
65
67
|
e.sidebar.collapsed = !e.sidebar.collapsed;
|
|
@@ -68,17 +70,17 @@ function g() {
|
|
|
68
70
|
l.revision === e && b("motion", "animated");
|
|
69
71
|
},
|
|
70
72
|
// Terminal accessors
|
|
71
|
-
terminalOpened: () =>
|
|
72
|
-
terminalHeight: () =>
|
|
73
|
+
terminalOpened: () => a.terminal.opened,
|
|
74
|
+
terminalHeight: () => a.terminal.height,
|
|
73
75
|
// Terminal actions
|
|
74
76
|
toggleTerminal: () => o(r((e) => {
|
|
75
77
|
e.terminal.opened = !e.terminal.opened;
|
|
76
78
|
})),
|
|
77
|
-
setTerminalHeight: (e) => o(r((
|
|
78
|
-
|
|
79
|
+
setTerminalHeight: (e) => o(r((t) => {
|
|
80
|
+
t.terminal.height = Math.max(i().terminal.clamp.min, Math.min(i().terminal.clamp.max, e));
|
|
79
81
|
})),
|
|
80
82
|
// Mobile
|
|
81
|
-
isMobile: () =>
|
|
83
|
+
isMobile: () => a.isMobile,
|
|
82
84
|
setIsMobile: (e) => o("isMobile", e)
|
|
83
85
|
};
|
|
84
86
|
}
|
|
@@ -86,5 +88,5 @@ export {
|
|
|
86
88
|
x as LayoutProvider,
|
|
87
89
|
g as createLayoutService,
|
|
88
90
|
C as useLayout,
|
|
89
|
-
|
|
91
|
+
A as useOptionalLayout
|
|
90
92
|
};
|
package/dist/resource-cache.d.ts
CHANGED
|
@@ -12,6 +12,8 @@ export interface ResourceCacheStorage {
|
|
|
12
12
|
}
|
|
13
13
|
export interface ResourceSnapshot<T> {
|
|
14
14
|
readonly data: T | undefined;
|
|
15
|
+
/** True until storage settles, or live data/invalidation supersedes restoration. */
|
|
16
|
+
readonly restoring: boolean;
|
|
15
17
|
readonly refreshing: boolean;
|
|
16
18
|
readonly stale: boolean;
|
|
17
19
|
readonly error: unknown;
|
|
@@ -36,6 +38,8 @@ export interface CachedResourceDefinition<T> {
|
|
|
36
38
|
}
|
|
37
39
|
export interface ResourceCache {
|
|
38
40
|
resource<T>(definition: CachedResourceDefinition<T>): CachedResource<T>;
|
|
41
|
+
/** Abort pending refreshes without retiring snapshots, storage, hydration or subscribers. */
|
|
42
|
+
cancelRefreshes(scope: string): void;
|
|
39
43
|
clearScope(scope: string): Promise<void>;
|
|
40
44
|
flush(): Promise<void>;
|
|
41
45
|
dispose(): void;
|
package/dist/resource-cache.js
CHANGED
|
@@ -1,175 +1,186 @@
|
|
|
1
|
-
async function
|
|
2
|
-
const
|
|
3
|
-
let
|
|
4
|
-
const
|
|
5
|
-
for (const
|
|
6
|
-
if (
|
|
7
|
-
await
|
|
1
|
+
async function J(y, l) {
|
|
2
|
+
const m = [...await y.list()].sort((r, s) => r.lastAccessedAt - s.lastAccessedAt);
|
|
3
|
+
let i = m.reduce((r, s) => r + s.bytes, 0);
|
|
4
|
+
const a = [];
|
|
5
|
+
for (const r of m) {
|
|
6
|
+
if (i <= Math.max(0, l)) break;
|
|
7
|
+
await y.remove(r.key), a.push(r.key), i -= r.bytes;
|
|
8
8
|
}
|
|
9
|
-
return
|
|
9
|
+
return a;
|
|
10
10
|
}
|
|
11
|
-
function
|
|
12
|
-
const
|
|
13
|
-
let
|
|
14
|
-
const
|
|
15
|
-
}),
|
|
16
|
-
const
|
|
17
|
-
list: async () => (await
|
|
18
|
-
remove: (
|
|
19
|
-
},
|
|
20
|
-
for (const
|
|
21
|
-
},
|
|
22
|
-
clearTimeout(
|
|
23
|
-
const
|
|
24
|
-
|
|
25
|
-
for (const [
|
|
26
|
-
if (
|
|
11
|
+
function z(y) {
|
|
12
|
+
const l = y.storage, m = Math.max(0, y.maxBytes ?? 32 * 1024 * 1024), i = /* @__PURE__ */ new Map(), a = /* @__PURE__ */ new Map();
|
|
13
|
+
let r, s = Promise.resolve(), n = !1;
|
|
14
|
+
const d = (t) => (s = s.then(t).catch(() => {
|
|
15
|
+
}), s), f = async () => {
|
|
16
|
+
const t = await J({
|
|
17
|
+
list: async () => (await l.list()).map((e) => ({ ...e, lastAccessedAt: Math.max(e.lastAccessedAt, i.get(e.key)?.accessedAt ?? 0) })),
|
|
18
|
+
remove: (e) => l.remove(e)
|
|
19
|
+
}, m);
|
|
20
|
+
for (const e of t) i.get(e)?.evicted();
|
|
21
|
+
}, p = async () => {
|
|
22
|
+
clearTimeout(r), r = void 0;
|
|
23
|
+
const t = [...a];
|
|
24
|
+
a.clear(), t.length && d(async () => {
|
|
25
|
+
for (const [e, v] of t)
|
|
26
|
+
if (v.valid())
|
|
27
27
|
try {
|
|
28
|
-
await
|
|
28
|
+
await l.set(e, v.value), v.stored();
|
|
29
29
|
} catch {
|
|
30
30
|
}
|
|
31
|
-
await
|
|
32
|
-
}), await
|
|
33
|
-
},
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
},
|
|
31
|
+
await f();
|
|
32
|
+
}), await s;
|
|
33
|
+
}, x = (t, e, v, o) => {
|
|
34
|
+
a.set(t, { value: e, valid: v, stored: o }), r === void 0 && (r = setTimeout(() => {
|
|
35
|
+
p();
|
|
36
|
+
}, y.writeDelayMs ?? 100));
|
|
37
37
|
};
|
|
38
38
|
return {
|
|
39
|
-
resource: (
|
|
40
|
-
if (
|
|
41
|
-
if (!
|
|
42
|
-
const
|
|
43
|
-
if (
|
|
44
|
-
return
|
|
45
|
-
let
|
|
46
|
-
const
|
|
47
|
-
let
|
|
48
|
-
const
|
|
49
|
-
for (const
|
|
50
|
-
},
|
|
51
|
-
++
|
|
39
|
+
resource: (t) => {
|
|
40
|
+
if (n) throw new Error("Resource cache is disposed");
|
|
41
|
+
if (!t.scope || !t.key || !Number.isSafeInteger(t.version)) throw new Error("Invalid resource identity");
|
|
42
|
+
const e = JSON.stringify([t.scope, t.key, t.version]), v = i.get(e);
|
|
43
|
+
if (v)
|
|
44
|
+
return v.accessedAt = Date.now(), v.handle;
|
|
45
|
+
let o = { data: void 0, restoring: !0, refreshing: !1, stale: !0, error: void 0 };
|
|
46
|
+
const S = /* @__PURE__ */ new Set();
|
|
47
|
+
let D = 0, w = 0, E, R, g, h, M;
|
|
48
|
+
const b = () => {
|
|
49
|
+
for (const c of S) c();
|
|
50
|
+
}, P = (c) => {
|
|
51
|
+
++D, o = { data: c, restoring: !1, refreshing: o.refreshing, stale: !1, error: void 0 };
|
|
52
52
|
try {
|
|
53
|
-
const u = JSON.stringify({ version:
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
}) :
|
|
53
|
+
const u = JSON.stringify({ version: t.version, data: t.persist ? t.persist(c) : c });
|
|
54
|
+
E = u, u !== R ? x(e, u, () => E === u, () => {
|
|
55
|
+
R = u;
|
|
56
|
+
}) : a.delete(e);
|
|
57
57
|
} catch {
|
|
58
58
|
}
|
|
59
|
-
|
|
60
|
-
},
|
|
61
|
-
if (!(
|
|
59
|
+
b();
|
|
60
|
+
}, C = D, O = l.get(e).then((c) => {
|
|
61
|
+
if (!(n || D !== C || c === null))
|
|
62
62
|
try {
|
|
63
|
-
const u = JSON.parse(
|
|
64
|
-
if (u.version !==
|
|
65
|
-
const A =
|
|
66
|
-
|
|
63
|
+
const u = JSON.parse(c);
|
|
64
|
+
if (u.version !== t.version) throw new Error("Unsupported snapshot");
|
|
65
|
+
const A = t.decode(u.data);
|
|
66
|
+
o = { ...o, data: A, stale: !0 }, E = c, R = c;
|
|
67
67
|
} catch {
|
|
68
|
-
|
|
68
|
+
d(() => l.remove(e));
|
|
69
69
|
}
|
|
70
70
|
}).catch(() => {
|
|
71
|
-
})
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
71
|
+
}).finally(() => {
|
|
72
|
+
n || !o.restoring || (o = { ...o, restoring: !1 }, b());
|
|
73
|
+
}), q = {
|
|
74
|
+
snapshot: () => o,
|
|
75
|
+
subscribe: (c) => (S.add(c), () => {
|
|
76
|
+
S.delete(c);
|
|
75
77
|
}),
|
|
76
|
-
hydrate: () =>
|
|
77
|
-
refresh: (
|
|
78
|
-
if (
|
|
79
|
-
const u = ++
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
78
|
+
hydrate: () => O,
|
|
79
|
+
refresh: (c) => {
|
|
80
|
+
if (h) return h;
|
|
81
|
+
const u = ++w, A = new AbortController();
|
|
82
|
+
g = A, o = { ...o, refreshing: !0, error: void 0 }, b();
|
|
83
|
+
const B = new Promise((k, I) => {
|
|
84
|
+
M = () => I(new DOMException("Resource refresh cancelled", "AbortError"));
|
|
85
|
+
}), N = Promise.resolve().then(() => c(A.signal)).then((k) => (!n && u === w && !A.signal.aborted && P(k), k), (k) => {
|
|
86
|
+
throw !n && u === w && !A.signal.aborted && (o = { ...o, stale: !0, error: k }, b()), k;
|
|
87
|
+
});
|
|
88
|
+
return h = Promise.race([N, B]).finally(() => {
|
|
89
|
+
u === w && (h = void 0, g = void 0, M = void 0, o = { ...o, refreshing: !1 }, b());
|
|
90
|
+
}), h;
|
|
85
91
|
},
|
|
86
|
-
set: (
|
|
87
|
-
++
|
|
92
|
+
set: (c) => {
|
|
93
|
+
++w, g?.abort(), h = void 0, o = { ...o, refreshing: !1 }, P(c);
|
|
88
94
|
},
|
|
89
|
-
invalidate: (
|
|
90
|
-
++
|
|
95
|
+
invalidate: (c = !1) => {
|
|
96
|
+
++D, ++w, g?.abort(), g = void 0, h = void 0, E = void 0, R = void 0, a.delete(e), o = { data: c ? void 0 : o.data, restoring: !1, refreshing: !1, stale: !0, error: void 0 }, b(), d(() => l.remove(e));
|
|
91
97
|
}
|
|
92
98
|
};
|
|
93
|
-
return
|
|
94
|
-
|
|
95
|
-
}, handle:
|
|
96
|
-
++
|
|
97
|
-
}
|
|
99
|
+
return i.set(e, { scope: t.scope, accessedAt: Date.now(), evicted: () => {
|
|
100
|
+
R = void 0;
|
|
101
|
+
}, handle: q, cancelRefresh: () => {
|
|
102
|
+
h && (++w, M?.(), M = void 0, g?.abort(), g = void 0, h = void 0, o = { ...o, refreshing: !1, stale: !0 }, b());
|
|
103
|
+
}, stop: () => {
|
|
104
|
+
++w, g?.abort(), S.clear();
|
|
105
|
+
} }), q;
|
|
98
106
|
},
|
|
99
|
-
flush:
|
|
100
|
-
|
|
101
|
-
for (const
|
|
102
|
-
|
|
103
|
-
|
|
107
|
+
flush: p,
|
|
108
|
+
cancelRefreshes: (t) => {
|
|
109
|
+
for (const e of i.values()) e.scope === t && e.cancelRefresh();
|
|
110
|
+
},
|
|
111
|
+
clearScope: async (t) => {
|
|
112
|
+
for (const e of i.values()) e.scope === t && e.handle.invalidate(!0);
|
|
113
|
+
await d(async () => {
|
|
114
|
+
for (const e of await l.list())
|
|
104
115
|
try {
|
|
105
|
-
JSON.parse(
|
|
116
|
+
JSON.parse(e.key)[0] === t && await l.remove(e.key);
|
|
106
117
|
} catch {
|
|
107
118
|
}
|
|
108
119
|
});
|
|
109
120
|
},
|
|
110
121
|
dispose: () => {
|
|
111
|
-
if (!
|
|
112
|
-
|
|
113
|
-
for (const
|
|
114
|
-
|
|
122
|
+
if (!n) {
|
|
123
|
+
n = !0;
|
|
124
|
+
for (const t of i.values()) t.stop();
|
|
125
|
+
p(), i.clear();
|
|
115
126
|
}
|
|
116
127
|
}
|
|
117
128
|
};
|
|
118
129
|
}
|
|
119
|
-
function
|
|
120
|
-
let
|
|
121
|
-
const
|
|
122
|
-
const
|
|
123
|
-
|
|
124
|
-
const
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
},
|
|
128
|
-
},
|
|
129
|
-
|
|
130
|
-
},
|
|
131
|
-
|
|
130
|
+
function L(y = "floe-resource-cache") {
|
|
131
|
+
let l;
|
|
132
|
+
const m = () => l ??= new Promise((a, r) => {
|
|
133
|
+
const s = indexedDB.open(y, 1);
|
|
134
|
+
s.onupgradeneeded = () => s.result.createObjectStore("snapshots", { keyPath: "key" }), s.onsuccess = () => {
|
|
135
|
+
const n = s.result;
|
|
136
|
+
n.onversionchange = () => {
|
|
137
|
+
n.close(), l = void 0;
|
|
138
|
+
}, a(n);
|
|
139
|
+
}, s.onerror = () => {
|
|
140
|
+
l = void 0, r(s.error);
|
|
141
|
+
}, s.onblocked = () => {
|
|
142
|
+
l = void 0, r(new Error("Resource cache database is blocked"));
|
|
132
143
|
};
|
|
133
|
-
}),
|
|
134
|
-
const
|
|
135
|
-
return new Promise((
|
|
136
|
-
const
|
|
137
|
-
let
|
|
138
|
-
|
|
139
|
-
|
|
144
|
+
}), i = async (a, r) => {
|
|
145
|
+
const s = await m();
|
|
146
|
+
return new Promise((n, d) => {
|
|
147
|
+
const f = s.transaction("snapshots", a);
|
|
148
|
+
let p;
|
|
149
|
+
f.oncomplete = () => n(p), f.onerror = () => d(f.error), f.onabort = () => d(f.error ?? new Error("Resource cache transaction aborted")), r(f.objectStore("snapshots"), (x) => {
|
|
150
|
+
p = x;
|
|
140
151
|
});
|
|
141
152
|
});
|
|
142
153
|
};
|
|
143
154
|
return {
|
|
144
|
-
get: (
|
|
145
|
-
const
|
|
146
|
-
|
|
147
|
-
const
|
|
148
|
-
|
|
155
|
+
get: (a) => i("readwrite", (r, s) => {
|
|
156
|
+
const n = r.get(a);
|
|
157
|
+
n.onsuccess = () => {
|
|
158
|
+
const d = n.result;
|
|
159
|
+
d && r.put({ ...d, lastAccessedAt: Date.now() }), s(d?.value ?? null);
|
|
149
160
|
};
|
|
150
161
|
}),
|
|
151
|
-
set: (
|
|
152
|
-
|
|
162
|
+
set: (a, r) => i("readwrite", (s, n) => {
|
|
163
|
+
s.put({ key: a, value: r, bytes: new TextEncoder().encode(r).byteLength, lastAccessedAt: Date.now() }), n(void 0);
|
|
153
164
|
}),
|
|
154
|
-
remove: (
|
|
155
|
-
|
|
165
|
+
remove: (a) => i("readwrite", (r, s) => {
|
|
166
|
+
r.delete(a), s(void 0);
|
|
156
167
|
}),
|
|
157
|
-
list: () =>
|
|
158
|
-
const
|
|
159
|
-
|
|
160
|
-
const
|
|
161
|
-
if (!
|
|
162
|
-
|
|
168
|
+
list: () => i("readonly", (a, r) => {
|
|
169
|
+
const s = [], n = a.openCursor();
|
|
170
|
+
n.onsuccess = () => {
|
|
171
|
+
const d = n.result;
|
|
172
|
+
if (!d) {
|
|
173
|
+
r(s);
|
|
163
174
|
return;
|
|
164
175
|
}
|
|
165
|
-
const { key:
|
|
166
|
-
|
|
176
|
+
const { key: f, bytes: p, lastAccessedAt: x } = d.value;
|
|
177
|
+
s.push({ key: f, bytes: p, lastAccessedAt: x }), d.continue();
|
|
167
178
|
};
|
|
168
179
|
})
|
|
169
180
|
};
|
|
170
181
|
}
|
|
171
182
|
export {
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
183
|
+
L as createIndexedDBResourceCacheStorage,
|
|
184
|
+
z as createResourceCache,
|
|
185
|
+
J as enforceResourceCacheBudget
|
|
175
186
|
};
|