@owlmeans/client 0.1.18-rc.4 → 0.1.18-rc.41
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/README.md +231 -54
- package/agent-meta/manifest.json +2 -2
- package/agent-meta/skills/client/SKILL.md +282 -19
- package/build/consts.d.ts +8 -0
- package/build/consts.d.ts.map +1 -1
- package/build/consts.js +8 -0
- package/build/consts.js.map +1 -1
- package/build/context.d.ts.map +1 -1
- package/build/context.js +1 -3
- package/build/context.js.map +1 -1
- package/build/entrypoint.d.ts +3 -0
- package/build/entrypoint.d.ts.map +1 -0
- package/build/entrypoint.js +4 -0
- package/build/entrypoint.js.map +1 -0
- package/build/helper.js +3 -3
- package/build/helper.js.map +1 -1
- package/build/index.d.ts +3 -1
- package/build/index.d.ts.map +1 -1
- package/build/index.js +3 -1
- package/build/index.js.map +1 -1
- package/build/lazy-retry.d.ts +47 -0
- package/build/lazy-retry.d.ts.map +1 -0
- package/build/lazy-retry.js +128 -0
- package/build/lazy-retry.js.map +1 -0
- package/build/lazy.d.ts +32 -0
- package/build/lazy.d.ts.map +1 -0
- package/build/lazy.js +114 -0
- package/build/lazy.js.map +1 -0
- package/build/navigate.d.ts.map +1 -1
- package/build/navigate.js +15 -18
- package/build/navigate.js.map +1 -1
- package/build/router.d.ts.map +1 -1
- package/build/router.js +12 -6
- package/build/router.js.map +1 -1
- package/build/services/debug.js.map +1 -1
- package/build/store.d.ts +19 -3
- package/build/store.d.ts.map +1 -1
- package/build/store.js +57 -50
- package/build/store.js.map +1 -1
- package/build/types.d.ts +85 -7
- package/build/types.d.ts.map +1 -1
- package/build/utils/entrypoint.d.ts +3 -0
- package/build/utils/entrypoint.d.ts.map +1 -0
- package/build/utils/{module.js → entrypoint.js} +2 -2
- package/build/utils/entrypoint.js.map +1 -0
- package/build/utils/index.d.ts +1 -1
- package/build/utils/index.d.ts.map +1 -1
- package/build/utils/index.js +1 -1
- package/build/utils/index.js.map +1 -1
- package/build/utils/route.d.ts.map +1 -1
- package/build/utils/route.js +12 -6
- package/build/utils/route.js.map +1 -1
- package/build/utils/router.d.ts +4 -4
- package/build/utils/router.d.ts.map +1 -1
- package/build/utils/router.js +8 -8
- package/build/utils/router.js.map +1 -1
- package/package.json +21 -14
- package/src/consts.ts +10 -0
- package/src/context.ts +1 -4
- package/src/entrypoint.ts +6 -0
- package/src/helper.tsx +6 -6
- package/src/index.ts +3 -1
- package/src/lazy-retry.ts +141 -0
- package/src/lazy.tsx +161 -0
- package/src/navigate.ts +16 -19
- package/src/router.ts +14 -10
- package/src/services/debug.ts +2 -2
- package/src/store.ts +71 -54
- package/src/types.ts +95 -7
- package/src/utils/{module.ts → entrypoint.ts} +2 -2
- package/src/utils/index.ts +1 -1
- package/src/utils/route.tsx +15 -8
- package/src/utils/router.ts +11 -11
- package/tests/context.ts +33 -0
- package/tests/harness/index.html +11 -0
- package/tests/harness/mount.tsx +86 -0
- package/tests/harness/piece.tsx +4 -0
- package/tests/lazy-retry.spec.ts +199 -0
- package/tests/lazy.spec.ts +145 -0
- package/tsconfig.json +1 -1
- package/build/module.d.ts +0 -3
- package/build/module.d.ts.map +0 -1
- package/build/module.js +0 -4
- package/build/module.js.map +0 -1
- package/build/utils/module.d.ts +0 -3
- package/build/utils/module.d.ts.map +0 -1
- package/build/utils/module.js.map +0 -1
- package/src/module.ts +0 -6
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
import { CHUNK_RELOAD_KEY, CHUNK_RELOAD_WINDOW_MS, DEF_IMPORT_RETRY_ATTEMPTS, DEF_IMPORT_RETRY_DELAYS_MS } from './consts.js';
|
|
2
|
+
/**
|
|
3
|
+
* What a browser says when a dynamic `import()` could not fetch its module — Chromium, Safari and
|
|
4
|
+
* Firefox, in that order — and what Vite's preload helper says when a chunk's stylesheet could not.
|
|
5
|
+
*/
|
|
6
|
+
const CHUNK_FAILURE = /failed to fetch dynamically imported module|importing a module script failed|error loading dynamically imported module|unable to preload css/i;
|
|
7
|
+
/**
|
|
8
|
+
* Whether `error` is a chunk that could not be FETCHED: a browser's failed dynamic import, Vite's
|
|
9
|
+
* stylesheet preload failure, webpack's `ChunkLoadError`, Vite's `vite:preloadError` event, or
|
|
10
|
+
* the `error` event of the element a loader fetched through. A module that was fetched and then
|
|
11
|
+
* failed — a missing export, a throw while it evaluated — is not one: loading it again changes
|
|
12
|
+
* nothing.
|
|
13
|
+
*/
|
|
14
|
+
export const isChunkLoadError = (error) => {
|
|
15
|
+
if (error == null || typeof error !== 'object') {
|
|
16
|
+
return false;
|
|
17
|
+
}
|
|
18
|
+
if (typeof Event !== 'undefined' && error instanceof Event) {
|
|
19
|
+
return error.type === 'vite:preloadError' || error.type === 'error';
|
|
20
|
+
}
|
|
21
|
+
const { name, message } = error;
|
|
22
|
+
return name === 'ChunkLoadError' || (typeof message === 'string' && CHUNK_FAILURE.test(message));
|
|
23
|
+
};
|
|
24
|
+
const pause = (ms) => new Promise(resolve => setTimeout(resolve, ms));
|
|
25
|
+
/** The module URL a Chromium or Firefox import failure names; Safari's message names none. */
|
|
26
|
+
const FAILED_URL = /dynamically imported module:?\s+(\S+)/i;
|
|
27
|
+
/**
|
|
28
|
+
* The URL of the chunk a failed dynamic import tried to fetch, when the browser's error names it
|
|
29
|
+
* and it is an http(s) URL of this page's origin — never an arbitrary URL out of a message. `null`
|
|
30
|
+
* otherwise (Safari, a non-browser platform, another origin).
|
|
31
|
+
*/
|
|
32
|
+
export const chunkUrlOf = (error) => {
|
|
33
|
+
const message = error?.message;
|
|
34
|
+
const found = typeof message === 'string' ? FAILED_URL.exec(message)?.[1] : undefined;
|
|
35
|
+
if (found == null) {
|
|
36
|
+
return null;
|
|
37
|
+
}
|
|
38
|
+
try {
|
|
39
|
+
const url = new URL(found);
|
|
40
|
+
const origin = typeof location !== 'undefined' ? location.origin : undefined;
|
|
41
|
+
if ((url.protocol !== 'https:' && url.protocol !== 'http:') || (origin != null && url.origin !== origin)) {
|
|
42
|
+
return null;
|
|
43
|
+
}
|
|
44
|
+
return url.href;
|
|
45
|
+
}
|
|
46
|
+
catch {
|
|
47
|
+
return null;
|
|
48
|
+
}
|
|
49
|
+
};
|
|
50
|
+
/**
|
|
51
|
+
* `href` with a fresh `t` parameter: a URL the browser has not seen, so it fetches the module
|
|
52
|
+
* again. `t` is the parameter Vite's dev server already gives module URLs; a static host ignores it.
|
|
53
|
+
*/
|
|
54
|
+
export const cacheBustedUrl = (href, now = Date.now()) => {
|
|
55
|
+
const url = new URL(href);
|
|
56
|
+
url.searchParams.set('t', String(now));
|
|
57
|
+
return url.href;
|
|
58
|
+
};
|
|
59
|
+
const importUrl = (url) => import(/* @vite-ignore */ /* webpackIgnore: true */ url);
|
|
60
|
+
/**
|
|
61
|
+
* Run `load` — a dynamic `import()` — and, while it rejects with a chunk-load failure, run it again
|
|
62
|
+
* after a pause, `attempts` more times at most. Any other rejection is rethrown at once.
|
|
63
|
+
*
|
|
64
|
+
* This covers a TRANSIENT failure — a network blip, an edge answering 404 or 5xx for a moment.
|
|
65
|
+
* A browser remembers a failed module fetch for the document's lifetime (Chromium does) and
|
|
66
|
+
* rejects every later `import()` of that URL at once, so a retry imports the URL the error names
|
|
67
|
+
* with a cache-busting parameter instead (`bustCache`, default on): a new URL, fetched again. Where
|
|
68
|
+
* the error names no URL (Safari), `load` runs again as is; what always recovers is a new
|
|
69
|
+
* document, which `recoverFromChunkError` starts, once and guarded.
|
|
70
|
+
*/
|
|
71
|
+
export const retryImport = async (load, opts) => {
|
|
72
|
+
const attempts = Math.max(0, opts?.attempts ?? DEF_IMPORT_RETRY_ATTEMPTS);
|
|
73
|
+
const delays = opts?.delaysMs ?? DEF_IMPORT_RETRY_DELAYS_MS;
|
|
74
|
+
const shouldRetry = opts?.shouldRetry ?? isChunkLoadError;
|
|
75
|
+
const bust = opts?.bustCache !== false;
|
|
76
|
+
const importBusted = opts?.importUrl ?? importUrl;
|
|
77
|
+
let next = load;
|
|
78
|
+
for (let attempt = 0;; attempt++) {
|
|
79
|
+
try {
|
|
80
|
+
return await next();
|
|
81
|
+
}
|
|
82
|
+
catch (error) {
|
|
83
|
+
if (attempt >= attempts || !shouldRetry(error)) {
|
|
84
|
+
throw error;
|
|
85
|
+
}
|
|
86
|
+
const url = bust ? chunkUrlOf(error) : null;
|
|
87
|
+
if (url != null) {
|
|
88
|
+
next = async () => await importBusted(cacheBustedUrl(url));
|
|
89
|
+
}
|
|
90
|
+
await pause(delays[Math.min(attempt, delays.length - 1)] ?? 0);
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
};
|
|
94
|
+
/**
|
|
95
|
+
* Reload the page, at most once per `windowMs` in this tab — the time of the last reload is kept
|
|
96
|
+
* in `sessionStorage` under `key`. Never while offline (the reload would land on the browser's own
|
|
97
|
+
* error page), and never without storage: with nowhere to keep the guard, a failure that survives
|
|
98
|
+
* the reload would reload forever. A platform with no page to reload does nothing. Answers whether
|
|
99
|
+
* a reload was started.
|
|
100
|
+
*/
|
|
101
|
+
export const reloadOnce = (key, windowMs) => {
|
|
102
|
+
const location = typeof window !== 'undefined' ? window.location : undefined;
|
|
103
|
+
if (typeof location?.reload !== 'function') {
|
|
104
|
+
return false;
|
|
105
|
+
}
|
|
106
|
+
if (typeof navigator !== 'undefined' && navigator.onLine === false) {
|
|
107
|
+
return false;
|
|
108
|
+
}
|
|
109
|
+
try {
|
|
110
|
+
const now = Date.now();
|
|
111
|
+
if (now - Number(window.sessionStorage.getItem(key) ?? 0) < windowMs) {
|
|
112
|
+
return false;
|
|
113
|
+
}
|
|
114
|
+
window.sessionStorage.setItem(key, String(now));
|
|
115
|
+
}
|
|
116
|
+
catch {
|
|
117
|
+
return false;
|
|
118
|
+
}
|
|
119
|
+
location.reload();
|
|
120
|
+
return true;
|
|
121
|
+
};
|
|
122
|
+
/**
|
|
123
|
+
* The guarded reload a chunk that failed for good ends in: `reloadOnce` under one key every caller
|
|
124
|
+
* in the tab shares, so a lazy boundary and an application's own `vite:preloadError` listener
|
|
125
|
+
* never reload twice for one failure.
|
|
126
|
+
*/
|
|
127
|
+
export const recoverFromChunkError = () => reloadOnce(CHUNK_RELOAD_KEY, CHUNK_RELOAD_WINDOW_MS);
|
|
128
|
+
//# sourceMappingURL=lazy-retry.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"lazy-retry.js","sourceRoot":"","sources":["../src/lazy-retry.ts"],"names":[],"mappings":"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"}
|
package/build/lazy.d.ts
ADDED
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import type { ComponentExport, ExportProps, LazyComponent, LazyComponentOptions, LazyHandler } from './types.js';
|
|
2
|
+
/**
|
|
3
|
+
* Wrap an async module import as a stable lazily-loaded component with a `.preload()`.
|
|
4
|
+
*
|
|
5
|
+
* MUST be called at module scope, never inside a render, a hook body or an entrypoint handler
|
|
6
|
+
* factory — the OwlMeans route renderer (`utils/route.tsx`) remounts the whole route subtree on
|
|
7
|
+
* every navigation (a fresh component identity per render), so a lazy object created during
|
|
8
|
+
* render would re-suspend on every navigation instead of rendering instantly once loaded.
|
|
9
|
+
*
|
|
10
|
+
* The `Suspense` boundary sits inside the returned component, so the fallback replaces only this
|
|
11
|
+
* component — the layout around it stays mounted while the chunk loads.
|
|
12
|
+
*
|
|
13
|
+
* Once loaded, later renders resolve synchronously (no re-suspend), so a component whose chunk
|
|
14
|
+
* was already preloaded never shows its fallback. A load that fails to fetch is retried in place
|
|
15
|
+
* (`retryImport`, tuned or turned off by `opts.retry`); one that still fails is never cached: the
|
|
16
|
+
* internal `React.lazy` is recreated, so the next mount, `retry()` or `preload()` loads for real.
|
|
17
|
+
*
|
|
18
|
+
* The component always carries its own error boundary, so a chunk that failed for good never
|
|
19
|
+
* unmounts what is around it: `opts.error` renders in its place, or — without one — the guarded
|
|
20
|
+
* reload (`recoverFromChunkError`) starts and the fallback stays. Any other error without
|
|
21
|
+
* `opts.error` goes on to the nearest boundary above, as if there were none.
|
|
22
|
+
*/
|
|
23
|
+
export declare const lazyComponent: <M, K extends ComponentExport<M>>(load: () => Promise<M>, exportName: K, opts?: LazyComponentOptions) => LazyComponent<ExportProps<M, K>>;
|
|
24
|
+
/**
|
|
25
|
+
* `handler(lazyComponent(...))`, carrying `.preload()` through — bind it to a screen exactly like
|
|
26
|
+
* `handler(Component)`. The same module-scope rule applies: call it where the entrypoints are
|
|
27
|
+
* declared, never inside a render. A screen whose chunk still fails after its retries starts the
|
|
28
|
+
* guarded reload before showing its `error` (`reload` defaults to `true` here): a whole screen has
|
|
29
|
+
* nothing to degrade to, and in a dev-served app only a new document can load it again.
|
|
30
|
+
*/
|
|
31
|
+
export declare const lazyHandler: <M, K extends ComponentExport<M>>(load: () => Promise<M>, exportName: K, opts?: LazyComponentOptions) => LazyHandler<ExportProps<M, K>>;
|
|
32
|
+
//# sourceMappingURL=lazy.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"lazy.d.ts","sourceRoot":"","sources":["../src/lazy.tsx"],"names":[],"mappings":"AAKA,OAAO,KAAK,EACV,eAAe,EAAE,WAAW,EAAE,aAAa,EAAE,oBAAoB,EAAE,WAAW,EAC/E,MAAM,YAAY,CAAA;AAKnB;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,eAAO,MAAM,aAAa,GAAI,CAAC,EAAE,CAAC,SAAS,eAAe,CAAC,CAAC,CAAC,QACrD,MAAM,OAAO,CAAC,CAAC,CAAC,cAAc,CAAC,SAAS,oBAAoB,KACjE,aAAa,CAAC,WAAW,CAAC,CAAC,EAAE,CAAC,CAAC,CAgDjC,CAAA;AA+DD;;;;;;GAMG;AACH,eAAO,MAAM,WAAW,GAAI,CAAC,EAAE,CAAC,SAAS,eAAe,CAAC,CAAC,CAAC,QACnD,MAAM,OAAO,CAAC,CAAC,CAAC,cAAc,CAAC,SAAS,oBAAoB,KACjE,WAAW,CAAC,WAAW,CAAC,CAAC,EAAE,CAAC,CAAC,CAK/B,CAAA"}
|
package/build/lazy.js
ADDED
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { lazy, Suspense, Component, useState } from 'react';
|
|
3
|
+
import { handler } from './helper.js';
|
|
4
|
+
import { isChunkLoadError, recoverFromChunkError, retryImport } from './lazy-retry.js';
|
|
5
|
+
/**
|
|
6
|
+
* Wrap an async module import as a stable lazily-loaded component with a `.preload()`.
|
|
7
|
+
*
|
|
8
|
+
* MUST be called at module scope, never inside a render, a hook body or an entrypoint handler
|
|
9
|
+
* factory — the OwlMeans route renderer (`utils/route.tsx`) remounts the whole route subtree on
|
|
10
|
+
* every navigation (a fresh component identity per render), so a lazy object created during
|
|
11
|
+
* render would re-suspend on every navigation instead of rendering instantly once loaded.
|
|
12
|
+
*
|
|
13
|
+
* The `Suspense` boundary sits inside the returned component, so the fallback replaces only this
|
|
14
|
+
* component — the layout around it stays mounted while the chunk loads.
|
|
15
|
+
*
|
|
16
|
+
* Once loaded, later renders resolve synchronously (no re-suspend), so a component whose chunk
|
|
17
|
+
* was already preloaded never shows its fallback. A load that fails to fetch is retried in place
|
|
18
|
+
* (`retryImport`, tuned or turned off by `opts.retry`); one that still fails is never cached: the
|
|
19
|
+
* internal `React.lazy` is recreated, so the next mount, `retry()` or `preload()` loads for real.
|
|
20
|
+
*
|
|
21
|
+
* The component always carries its own error boundary, so a chunk that failed for good never
|
|
22
|
+
* unmounts what is around it: `opts.error` renders in its place, or — without one — the guarded
|
|
23
|
+
* reload (`recoverFromChunkError`) starts and the fallback stays. Any other error without
|
|
24
|
+
* `opts.error` goes on to the nearest boundary above, as if there were none.
|
|
25
|
+
*/
|
|
26
|
+
export const lazyComponent = (load, exportName, opts) => {
|
|
27
|
+
let loaded;
|
|
28
|
+
let loading;
|
|
29
|
+
const fetchModule = () => opts?.retry === false ? load() : retryImport(load, opts?.retry);
|
|
30
|
+
const runLoad = () => loading ??= fetchModule().then(module => {
|
|
31
|
+
const Comp = module[exportName];
|
|
32
|
+
if (Comp == null) {
|
|
33
|
+
throw new SyntaxError(`Lazy module has no component export "${exportName}"`);
|
|
34
|
+
}
|
|
35
|
+
return loaded = Comp;
|
|
36
|
+
}).catch((error) => {
|
|
37
|
+
loading = undefined;
|
|
38
|
+
current = createLazy();
|
|
39
|
+
throw error;
|
|
40
|
+
});
|
|
41
|
+
const preload = () => loaded != null ? Promise.resolve(loaded) : runLoad();
|
|
42
|
+
const createLazy = () => lazy(() => {
|
|
43
|
+
const ready = loaded;
|
|
44
|
+
if (ready != null) {
|
|
45
|
+
// Already resolved: hand React a thenable that settles synchronously, so its lazy
|
|
46
|
+
// initializer reads the module in the same tick and never suspends.
|
|
47
|
+
const settled = { then: (resolve) => resolve({ default: ready }) };
|
|
48
|
+
return settled;
|
|
49
|
+
}
|
|
50
|
+
return runLoad().then(Comp => ({ default: Comp }));
|
|
51
|
+
});
|
|
52
|
+
let current = createLazy();
|
|
53
|
+
const Lazy = (props) => {
|
|
54
|
+
// The lazy THIS instance renders, taken when it mounts: a failed load stays failed for it
|
|
55
|
+
// while React re-renders it to recover from the error, until `retry` swaps in the recreated
|
|
56
|
+
// lazy. A new mount — a navigation back, another place — takes the recreated one at once.
|
|
57
|
+
const [Current, setCurrent] = useState(() => current);
|
|
58
|
+
const fallback = (typeof opts?.fallback === 'function' ? opts.fallback(props) : opts?.fallback) ?? null;
|
|
59
|
+
return _jsx(LazyErrorBoundary, { error: opts?.error, reload: opts?.reload === true, fallback: fallback, props: props, onRetry: () => setCurrent(() => current), children: _jsx(Suspense, { fallback: fallback, children: _jsx(Current, { ...props }) }) });
|
|
60
|
+
};
|
|
61
|
+
Lazy.displayName = `Lazy(${exportName})`;
|
|
62
|
+
return Object.assign(Lazy, { preload });
|
|
63
|
+
};
|
|
64
|
+
class LazyErrorBoundary extends Component {
|
|
65
|
+
state = { failed: false, error: undefined };
|
|
66
|
+
static getDerivedStateFromError(error) {
|
|
67
|
+
return { failed: true, error };
|
|
68
|
+
}
|
|
69
|
+
componentDidCatch(error) {
|
|
70
|
+
// A chunk that failed for good is recovered by a new document: always without a surface of its
|
|
71
|
+
// own, and with one when asked (`reload`) — a whole screen rather than a piece that degrades.
|
|
72
|
+
// The reload is guarded (once a minute per tab); when the guard refuses, the surface stays.
|
|
73
|
+
if (isChunkLoadError(error) && (this.props.error === undefined || this.props.reload)) {
|
|
74
|
+
if (recoverFromChunkError()) {
|
|
75
|
+
this.setState({ reloading: true });
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
/** Render the children again, over the recreated lazy, which loads anew. */
|
|
80
|
+
retry = () => {
|
|
81
|
+
this.setState({ failed: false, error: undefined, reloading: false });
|
|
82
|
+
this.props.onRetry();
|
|
83
|
+
};
|
|
84
|
+
render() {
|
|
85
|
+
if (!this.state.failed) {
|
|
86
|
+
return this.props.children;
|
|
87
|
+
}
|
|
88
|
+
const { error, fallback, props } = this.props;
|
|
89
|
+
if (this.state.reloading === true) {
|
|
90
|
+
return fallback;
|
|
91
|
+
}
|
|
92
|
+
if (error !== undefined) {
|
|
93
|
+
return typeof error === 'function' ? error(props, this.state.error, this.retry) : error;
|
|
94
|
+
}
|
|
95
|
+
if (isChunkLoadError(this.state.error)) {
|
|
96
|
+
return fallback;
|
|
97
|
+
}
|
|
98
|
+
// Not a chunk failure and no surface for it: the application's own boundary decides.
|
|
99
|
+
throw this.state.error;
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
/**
|
|
103
|
+
* `handler(lazyComponent(...))`, carrying `.preload()` through — bind it to a screen exactly like
|
|
104
|
+
* `handler(Component)`. The same module-scope rule applies: call it where the entrypoints are
|
|
105
|
+
* declared, never inside a render. A screen whose chunk still fails after its retries starts the
|
|
106
|
+
* guarded reload before showing its `error` (`reload` defaults to `true` here): a whole screen has
|
|
107
|
+
* nothing to degrade to, and in a dev-served app only a new document can load it again.
|
|
108
|
+
*/
|
|
109
|
+
export const lazyHandler = (load, exportName, opts) => {
|
|
110
|
+
const LazyComp = lazyComponent(load, exportName, { ...opts, reload: opts?.reload ?? true });
|
|
111
|
+
const refed = handler(LazyComp);
|
|
112
|
+
return Object.assign(refed, { preload: LazyComp.preload });
|
|
113
|
+
};
|
|
114
|
+
//# sourceMappingURL=lazy.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"lazy.js","sourceRoot":"","sources":["../src/lazy.tsx"],"names":[],"mappings":"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"}
|
package/build/navigate.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"navigate.d.ts","sourceRoot":"","sources":["../src/navigate.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,YAAY,CAAA;
|
|
1
|
+
{"version":3,"file":"navigate.d.ts","sourceRoot":"","sources":["../src/navigate.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,YAAY,CAAA;AAI3C,eAAO,MAAM,WAAW,QAAO,SA6C9B,CAAA"}
|
package/build/navigate.js
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import { useMemo } from 'react';
|
|
2
|
-
import { EntrypointOutcome } from '@owlmeans/entrypoint';
|
|
3
2
|
import { useContext } from './context.js';
|
|
4
3
|
export const useNavigate = () => {
|
|
5
4
|
const context = useContext();
|
|
@@ -8,25 +7,23 @@ export const useNavigate = () => {
|
|
|
8
7
|
const navigator = useMemo(() => {
|
|
9
8
|
const navigator = {
|
|
10
9
|
_navigate: navigate,
|
|
11
|
-
navigate: async (
|
|
12
|
-
const
|
|
13
|
-
if (
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
});
|
|
24
|
-
}
|
|
10
|
+
navigate: async (entrypoint, request) => {
|
|
11
|
+
const url = await entrypoint.url(request);
|
|
12
|
+
if (url.startsWith('http')) {
|
|
13
|
+
globalThis.location.href = url;
|
|
14
|
+
}
|
|
15
|
+
else {
|
|
16
|
+
navigate(url, {
|
|
17
|
+
state: {
|
|
18
|
+
...entrypoint.route.route, silent: request?.silent
|
|
19
|
+
},
|
|
20
|
+
replace: request?.replace ?? false
|
|
21
|
+
});
|
|
25
22
|
}
|
|
26
23
|
},
|
|
27
|
-
go: async (
|
|
28
|
-
press: (
|
|
29
|
-
void navigator.go(
|
|
24
|
+
go: async (target, request) => navigator.navigate(context.entrypoint(target), request),
|
|
25
|
+
press: (target, request) => () => {
|
|
26
|
+
void navigator.go(target, request);
|
|
30
27
|
},
|
|
31
28
|
back: async () => {
|
|
32
29
|
navigate(-1);
|
package/build/navigate.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"navigate.js","sourceRoot":"","sources":["../src/navigate.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,OAAO,CAAA;AAE/B,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"navigate.js","sourceRoot":"","sources":["../src/navigate.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,OAAO,CAAA;AAE/B,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAA;AAGzC,MAAM,CAAC,MAAM,WAAW,GAAG,GAAc,EAAE;IACzC,MAAM,OAAO,GAAG,UAAU,EAAE,CAAA;IAC5B,MAAM,QAAQ,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,WAAW,EAAE,CAAA;IAC/C,MAAM,QAAQ,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,WAAW,EAAE,CAAA;IAC/C,MAAM,SAAS,GAAc,OAAO,CAAC,GAAG,EAAE;QACxC,MAAM,SAAS,GAAc;YAC3B,SAAS,EAAE,QAAQ;YAEnB,QAAQ,EAAE,KAAK,EAAE,UAAU,EAAE,OAAO,EAAE,EAAE;gBACtC,MAAM,GAAG,GAAG,MAAM,UAAU,CAAC,GAAG,CAAC,OAAO,CAAC,CAAA;gBAEzC,IAAI,GAAG,CAAC,UAAU,CAAC,MAAM,CAAC,EAAE,CAAC;oBAC3B,UAAU,CAAC,QAAQ,CAAC,IAAI,GAAG,GAAG,CAAA;gBAChC,CAAC;qBAAM,CAAC;oBACN,QAAQ,CAAC,GAAG,EAAE;wBACZ,KAAK,EAAE;4BACL,GAAG,UAAU,CAAC,KAAK,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM;yBACnD;wBACD,OAAO,EAAE,OAAO,EAAE,OAAO,IAAI,KAAK;qBACnC,CAAC,CAAA;gBACJ,CAAC;YACH,CAAC;YAED,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,EAAE,CAC5B,SAAS,CAAC,QAAQ,CAAC,OAAO,CAAC,UAAU,CAA2B,MAAM,CAAC,EAAE,OAAO,CAAC;YAEnF,KAAK,EAAE,CAAC,MAAM,EAAE,OAAO,EAAE,EAAE,CAAC,GAAG,EAAE;gBAC/B,KAAK,SAAS,CAAC,EAAE,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;YACpC,CAAC;YAED,IAAI,EAAE,KAAK,IAAI,EAAE;gBACf,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAA;YACd,CAAC;YAED,SAAS,EAAE,GAAG,EAAE,CAAC,GAAG,EAAE;gBACpB,KAAK,SAAS,CAAC,IAAI,EAAE,CAAA;YACvB,CAAC;YAED,QAAQ,EAAE,GAAG,EAAE,CAAC,QAAQ;SACzB,CAAA;QAED,OAAO,SAAS,CAAA;IAClB,CAAC,EAAE,CAAC,QAAQ,CAAC,CAAC,CAAA;IAEd,OAAO,SAAS,CAAA;AAClB,CAAC,CAAA"}
|
package/build/router.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"router.d.ts","sourceRoot":"","sources":["../src/router.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,EAAE,EAAE,MAAM,OAAO,CAAA;AAC/B,OAAO,KAAK,EAAE,WAAW,EAAE,WAAW,EAAkB,MAAM,YAAY,CAAA;
|
|
1
|
+
{"version":3,"file":"router.d.ts","sourceRoot":"","sources":["../src/router.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,EAAE,EAAE,MAAM,OAAO,CAAA;AAC/B,OAAO,KAAK,EAAE,WAAW,EAAE,WAAW,EAAkB,MAAM,YAAY,CAAA;AAqB1E,eAAO,MAAM,MAAM,EAAE,EAAE,CAAC,WAAW,CAkClC,CAAA;AAED,eAAO,MAAM,eAAe,QAAO,WA6BlC,CAAA"}
|
package/build/router.js
CHANGED
|
@@ -1,8 +1,14 @@
|
|
|
1
1
|
import { createElement, useEffect, useRef, useState } from 'react';
|
|
2
|
-
import {
|
|
2
|
+
import { buildEntrypointTree, initializeRouter, visitEntrypointTree } from './utils/router.js';
|
|
3
3
|
import { createRouteRenderer } from './utils/route.js';
|
|
4
4
|
import { useContext } from './context.js';
|
|
5
5
|
import { assertContext } from '@owlmeans/context';
|
|
6
|
+
/** A child path that keeps its leading separator reads as absolute, and the router rejects it. */
|
|
7
|
+
const relative = (segment) => {
|
|
8
|
+
segment = segment.trim();
|
|
9
|
+
segment = segment.endsWith('/') ? segment.slice(0, -1) : segment;
|
|
10
|
+
return segment.startsWith('/') ? segment.substring(1) : segment;
|
|
11
|
+
};
|
|
6
12
|
export const Router = ({ provide }) => {
|
|
7
13
|
const progress = useRef(false);
|
|
8
14
|
const context = useContext();
|
|
@@ -37,16 +43,16 @@ export const makeRouterModel = () => {
|
|
|
37
43
|
routes: [],
|
|
38
44
|
resolve: async (ctx) => {
|
|
39
45
|
const context = assertContext(ctx, location);
|
|
40
|
-
const
|
|
41
|
-
const reactRoutes = await
|
|
42
|
-
const ctx = assertContext((module.ctx ?? context), location);
|
|
43
|
-
await module.route.resolve(ctx);
|
|
46
|
+
const entrypointTree = buildEntrypointTree(context);
|
|
47
|
+
const reactRoutes = await visitEntrypointTree(entrypointTree, async (module, children) => {
|
|
44
48
|
const renderer = module.handle != null
|
|
45
49
|
? { Component: createRouteRenderer({ context, module, hasChildren: children.length > 0 }) }
|
|
46
50
|
: undefined;
|
|
51
|
+
// The React tree nests, so each node contributes only its OWN segment — its ancestors are
|
|
52
|
+
// the branches it hangs under and already carry theirs.
|
|
47
53
|
const route = {
|
|
48
54
|
...(module.route.route.default ? { index: true } : undefined),
|
|
49
|
-
...(!module.route.route.default ? { path: module.
|
|
55
|
+
...(!module.route.route.default ? { path: relative(module.segment()), children } : undefined),
|
|
50
56
|
...renderer
|
|
51
57
|
};
|
|
52
58
|
return route;
|
package/build/router.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"router.js","sourceRoot":"","sources":["../src/router.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,aAAa,EAAE,SAAS,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAA;AAClE,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"router.js","sourceRoot":"","sources":["../src/router.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"debug.js","sourceRoot":"","sources":["../../src/services/debug.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"debug.js","sourceRoot":"","sources":["../../src/services/debug.ts"],"names":[],"mappings":"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"}
|
package/build/store.d.ts
CHANGED
|
@@ -1,4 +1,20 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
|
|
3
|
-
|
|
1
|
+
import type { ResourceRecord } from '@owlmeans/resource';
|
|
2
|
+
import type { StateModel } from '@owlmeans/state';
|
|
3
|
+
import type { UseStoreListOptions } from './types.js';
|
|
4
|
+
/**
|
|
5
|
+
* One record from a state resource, live.
|
|
6
|
+
*
|
|
7
|
+
* It never throws for missing data: an id the store knows nothing about yields a model whose
|
|
8
|
+
* `empty` is true — reading `record` gives the resource's configured default, and nothing is
|
|
9
|
+
* written into the store on the way. An ABSENT id is the same answer rather than an error, since
|
|
10
|
+
* a screen renders before the record that supplies the id has arrived; on a `single` resource an
|
|
11
|
+
* absent id addresses its sole record. Writing through an empty model with no id is refused.
|
|
12
|
+
*/
|
|
13
|
+
export declare const useStoreModel: <T extends ResourceRecord = ResourceRecord>(id?: string, alias?: string) => StateModel<T>;
|
|
14
|
+
/**
|
|
15
|
+
* A live LIST from a state resource: every record the query accepts, re-evaluated on every write
|
|
16
|
+
* that changes the answer, so a screen never recomputes ids and never re-subscribes to keep up.
|
|
17
|
+
* Omitting `query` matches everything.
|
|
18
|
+
*/
|
|
19
|
+
export declare const useStoreList: <T extends ResourceRecord = ResourceRecord>(opts?: UseStoreListOptions<T>) => StateModel<T>[];
|
|
4
20
|
//# sourceMappingURL=store.d.ts.map
|
package/build/store.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"store.d.ts","sourceRoot":"","sources":["../src/store.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,
|
|
1
|
+
{"version":3,"file":"store.d.ts","sourceRoot":"","sources":["../src/store.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAA;AACxD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAA;AAEjD,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,YAAY,CAAA;AAiCrD;;;;;;;;GAQG;AACH,eAAO,MAAM,aAAa,GAAI,CAAC,SAAS,cAAc,GAAG,cAAc,OAChE,MAAM,UAAU,MAAM,KAC1B,UAAU,CAAC,CAAC,CASd,CAAA;AAED;;;;GAIG;AACH,eAAO,MAAM,YAAY,GAAI,CAAC,SAAS,cAAc,GAAG,cAAc,SAC7D,mBAAmB,CAAC,CAAC,CAAC,KAC5B,UAAU,CAAC,CAAC,CAAC,EAkBf,CAAA"}
|
package/build/store.js
CHANGED
|
@@ -1,55 +1,62 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { useMemo, useSyncExternalStore } from 'react';
|
|
2
2
|
import { useContext } from './context.js';
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
3
|
+
/**
|
|
4
|
+
* Turn one state subscription into the pair `useSyncExternalStore` wants.
|
|
5
|
+
*
|
|
6
|
+
* The value is cached rather than rebuilt per render: the hook is asked for a snapshot on every
|
|
7
|
+
* render and must answer with the same reference until something actually changed, or React
|
|
8
|
+
* re-renders forever. A state subscription hands its value over synchronously, so the first
|
|
9
|
+
* snapshot is taken by subscribing and unsubscribing again — no render ever runs without one,
|
|
10
|
+
* and no subscription outlives the call.
|
|
11
|
+
*/
|
|
12
|
+
const bind = (subscribe) => {
|
|
13
|
+
let current;
|
|
14
|
+
let seeded = false;
|
|
15
|
+
const capture = (notify) => (value) => {
|
|
16
|
+
current = value;
|
|
17
|
+
seeded = true;
|
|
18
|
+
notify?.();
|
|
19
|
+
};
|
|
20
|
+
return {
|
|
21
|
+
subscribe: (notify) => subscribe(capture(notify)),
|
|
22
|
+
snapshot: () => {
|
|
23
|
+
if (!seeded) {
|
|
24
|
+
subscribe(capture())();
|
|
25
|
+
}
|
|
26
|
+
return current;
|
|
27
|
+
}
|
|
28
|
+
};
|
|
9
29
|
};
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
}
|
|
21
|
-
else if (typeof opts === 'boolean') {
|
|
22
|
-
params.listen = opts;
|
|
23
|
-
}
|
|
24
|
-
params.listen = params.listen ?? true;
|
|
30
|
+
/**
|
|
31
|
+
* One record from a state resource, live.
|
|
32
|
+
*
|
|
33
|
+
* It never throws for missing data: an id the store knows nothing about yields a model whose
|
|
34
|
+
* `empty` is true — reading `record` gives the resource's configured default, and nothing is
|
|
35
|
+
* written into the store on the way. An ABSENT id is the same answer rather than an error, since
|
|
36
|
+
* a screen renders before the record that supplies the id has arrived; on a `single` resource an
|
|
37
|
+
* absent id addresses its sole record. Writing through an empty model with no id is refused.
|
|
38
|
+
*/
|
|
39
|
+
export const useStoreModel = (id, alias) => {
|
|
25
40
|
const context = useContext();
|
|
26
|
-
const resource = useMemo(() => context.getStateResource(
|
|
27
|
-
const
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
const
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
setModels(_initialModels);
|
|
47
|
-
if (_return.length < 1) {
|
|
48
|
-
_return.push(..._initialModels);
|
|
49
|
-
}
|
|
50
|
-
return unsubscribe;
|
|
51
|
-
}, deps);
|
|
52
|
-
useEffect(() => unsubscribe, deps);
|
|
53
|
-
return _return;
|
|
41
|
+
const resource = useMemo(() => context.getStateResource(alias), [context, alias]);
|
|
42
|
+
const store = useMemo(() => bind(listener => resource.watch(id, listener)), [resource, id]);
|
|
43
|
+
return useSyncExternalStore(store.subscribe, store.snapshot, store.snapshot);
|
|
44
|
+
};
|
|
45
|
+
/**
|
|
46
|
+
* A live LIST from a state resource: every record the query accepts, re-evaluated on every write
|
|
47
|
+
* that changes the answer, so a screen never recomputes ids and never re-subscribes to keep up.
|
|
48
|
+
* Omitting `query` matches everything.
|
|
49
|
+
*/
|
|
50
|
+
export const useStoreList = (opts) => {
|
|
51
|
+
const context = useContext();
|
|
52
|
+
const resource = useMemo(() => context.getStateResource(opts?.resource), [context, opts?.resource]);
|
|
53
|
+
/**
|
|
54
|
+
* The subscription is keyed on the query's CONTENT, not on whether one was given: a screen
|
|
55
|
+
* that narrows its filter has to re-subscribe, and keyed on identity it kept answering the
|
|
56
|
+
* first filter it ever saw with nothing to say the list had gone stale.
|
|
57
|
+
*/
|
|
58
|
+
const key = JSON.stringify([opts?.query ?? null, opts?.sort ?? null]);
|
|
59
|
+
const store = useMemo(() => bind(listener => resource.query(opts?.query, listener, { sort: opts?.sort })), [resource, key]);
|
|
60
|
+
return useSyncExternalStore(store.subscribe, store.snapshot, store.snapshot);
|
|
54
61
|
};
|
|
55
62
|
//# sourceMappingURL=store.js.map
|
package/build/store.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"store.js","sourceRoot":"","sources":["../src/store.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"store.js","sourceRoot":"","sources":["../src/store.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,oBAAoB,EAAE,MAAM,OAAO,CAAA;AAGrD,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAA;AAGzC;;;;;;;;GAQG;AACH,MAAM,IAAI,GAAG,CAAI,SAAuD,EAAE,EAAE;IAC1E,IAAI,OAAsB,CAAA;IAC1B,IAAI,MAAM,GAAG,KAAK,CAAA;IAElB,MAAM,OAAO,GAAG,CAAC,MAAmB,EAAE,EAAE,CAAC,CAAC,KAAQ,EAAE,EAAE;QACpD,OAAO,GAAG,KAAK,CAAA;QACf,MAAM,GAAG,IAAI,CAAA;QACb,MAAM,EAAE,EAAE,CAAA;IACZ,CAAC,CAAA;IAED,OAAO;QACL,SAAS,EAAE,CAAC,MAAkB,EAAE,EAAE,CAAC,SAAS,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;QAC7D,QAAQ,EAAE,GAAM,EAAE;YAChB,IAAI,CAAC,MAAM,EAAE,CAAC;gBACZ,SAAS,CAAC,OAAO,EAAE,CAAC,EAAE,CAAA;YACxB,CAAC;YAED,OAAO,OAAY,CAAA;QACrB,CAAC;KACF,CAAA;AACH,CAAC,CAAA;AAED;;;;;;;;GAQG;AACH,MAAM,CAAC,MAAM,aAAa,GAAG,CAC3B,EAAW,EAAE,KAAc,EACZ,EAAE;IACjB,MAAM,OAAO,GAAG,UAAU,EAAE,CAAA;IAC5B,MAAM,QAAQ,GAAG,OAAO,CAAC,GAAG,EAAE,CAAC,OAAO,CAAC,gBAAgB,CAAI,KAAK,CAAC,EAAE,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC,CAAA;IACpF,MAAM,KAAK,GAAG,OAAO,CACnB,GAAG,EAAE,CAAC,IAAI,CAAgB,QAAQ,CAAC,EAAE,CAAC,QAAQ,CAAC,KAAK,CAAC,EAAE,EAAE,QAAQ,CAAC,CAAC,EACnE,CAAC,QAAQ,EAAE,EAAE,CAAC,CACf,CAAA;IAED,OAAO,oBAAoB,CAAC,KAAK,CAAC,SAAS,EAAE,KAAK,CAAC,QAAQ,EAAE,KAAK,CAAC,QAAQ,CAAC,CAAA;AAC9E,CAAC,CAAA;AAED;;;;GAIG;AACH,MAAM,CAAC,MAAM,YAAY,GAAG,CAC1B,IAA6B,EACZ,EAAE;IACnB,MAAM,OAAO,GAAG,UAAU,EAAE,CAAA;IAC5B,MAAM,QAAQ,GAAG,OAAO,CAAC,GAAG,EAAE,CAAC,OAAO,CAAC,gBAAgB,CAAI,IAAI,EAAE,QAAQ,CAAC,EAAE,CAAC,OAAO,EAAE,IAAI,EAAE,QAAQ,CAAC,CAAC,CAAA;IAEtG;;;;OAIG;IACH,MAAM,GAAG,GAAG,IAAI,CAAC,SAAS,CAAC,CAAC,IAAI,EAAE,KAAK,IAAI,IAAI,EAAE,IAAI,EAAE,IAAI,IAAI,IAAI,CAAC,CAAC,CAAA;IACrE,MAAM,KAAK,GAAG,OAAO,CACnB,GAAG,EAAE,CAAC,IAAI,CACR,QAAQ,CAAC,EAAE,CAAC,QAAQ,CAAC,KAAK,CAAC,IAAI,EAAE,KAAK,EAAE,QAAQ,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,CACxE,EACD,CAAC,QAAQ,EAAE,GAAG,CAAC,CAChB,CAAA;IAED,OAAO,oBAAoB,CAAC,KAAK,CAAC,SAAS,EAAE,KAAK,CAAC,QAAQ,EAAE,KAAK,CAAC,QAAQ,CAAC,CAAA;AAC9E,CAAC,CAAA"}
|