@webqit/webflo 0.11.61 → 0.20.2-next.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.
- package/.github/FUNDING.yml +12 -0
- package/.github/workflows/publish.yml +48 -0
- package/.gitignore +2 -0
- package/LICENSE +2 -2
- package/README.md +71 -2050
- package/package.json +28 -13
- package/site/-/_.md +139 -0
- package/site/-/docs.old.md +2010 -0
- package/site/.vitepress/cache/deps/@braintree_sanitize-url 2.js +93 -0
- package/site/.vitepress/cache/deps/@braintree_sanitize-url.js +93 -0
- package/site/.vitepress/cache/deps/@braintree_sanitize-url.js 2.map +7 -0
- package/site/.vitepress/cache/deps/@braintree_sanitize-url.js.map +7 -0
- package/site/.vitepress/cache/deps/_metadata 2.json +85 -0
- package/site/.vitepress/cache/deps/_metadata.json +85 -0
- package/site/.vitepress/cache/deps/chunk-BUSYA2B4 2.js +9 -0
- package/site/.vitepress/cache/deps/chunk-BUSYA2B4.js +9 -0
- package/site/.vitepress/cache/deps/chunk-BUSYA2B4.js 2.map +7 -0
- package/site/.vitepress/cache/deps/chunk-BUSYA2B4.js.map +7 -0
- package/site/.vitepress/cache/deps/chunk-Q2AYPHVK 2.js +9719 -0
- package/site/.vitepress/cache/deps/chunk-Q2AYPHVK.js +9719 -0
- package/site/.vitepress/cache/deps/chunk-Q2AYPHVK.js 2.map +7 -0
- package/site/.vitepress/cache/deps/chunk-Q2AYPHVK.js.map +7 -0
- package/site/.vitepress/cache/deps/chunk-QAXAIFA7 2.js +12705 -0
- package/site/.vitepress/cache/deps/chunk-QAXAIFA7.js +12705 -0
- package/site/.vitepress/cache/deps/chunk-QAXAIFA7.js 2.map +7 -0
- package/site/.vitepress/cache/deps/chunk-QAXAIFA7.js.map +7 -0
- package/site/.vitepress/cache/deps/cytoscape 2.js +30278 -0
- package/site/.vitepress/cache/deps/cytoscape-cose-bilkent 2.js +4710 -0
- package/site/.vitepress/cache/deps/cytoscape-cose-bilkent.js +4710 -0
- package/site/.vitepress/cache/deps/cytoscape-cose-bilkent.js 2.map +7 -0
- package/site/.vitepress/cache/deps/cytoscape-cose-bilkent.js.map +7 -0
- package/site/.vitepress/cache/deps/cytoscape.js +30278 -0
- package/site/.vitepress/cache/deps/cytoscape.js 2.map +7 -0
- package/site/.vitepress/cache/deps/cytoscape.js.map +7 -0
- package/site/.vitepress/cache/deps/dayjs 2.js +285 -0
- package/site/.vitepress/cache/deps/dayjs.js +285 -0
- package/site/.vitepress/cache/deps/dayjs.js 2.map +7 -0
- package/site/.vitepress/cache/deps/dayjs.js.map +7 -0
- package/site/.vitepress/cache/deps/debug 2.js +453 -0
- package/site/.vitepress/cache/deps/debug.js +453 -0
- package/site/.vitepress/cache/deps/debug.js 2.map +7 -0
- package/site/.vitepress/cache/deps/debug.js.map +7 -0
- package/site/.vitepress/cache/deps/package 2.json +3 -0
- package/site/.vitepress/cache/deps/package.json +3 -0
- package/site/.vitepress/cache/deps/vitepress___@vue_devtools-api 2.js +4507 -0
- package/site/.vitepress/cache/deps/vitepress___@vue_devtools-api.js +4507 -0
- package/site/.vitepress/cache/deps/vitepress___@vue_devtools-api.js 2.map +7 -0
- package/site/.vitepress/cache/deps/vitepress___@vue_devtools-api.js.map +7 -0
- package/site/.vitepress/cache/deps/vitepress___@vueuse_core 2.js +584 -0
- package/site/.vitepress/cache/deps/vitepress___@vueuse_core.js +584 -0
- package/site/.vitepress/cache/deps/vitepress___@vueuse_core.js 2.map +7 -0
- package/site/.vitepress/cache/deps/vitepress___@vueuse_core.js.map +7 -0
- package/site/.vitepress/cache/deps/vitepress___@vueuse_integrations_useFocusTrap 2.js +1166 -0
- package/site/.vitepress/cache/deps/vitepress___@vueuse_integrations_useFocusTrap.js +1166 -0
- package/site/.vitepress/cache/deps/vitepress___@vueuse_integrations_useFocusTrap.js 2.map +7 -0
- package/site/.vitepress/cache/deps/vitepress___@vueuse_integrations_useFocusTrap.js.map +7 -0
- package/site/.vitepress/cache/deps/vitepress___mark__js_src_vanilla__js 2.js +1667 -0
- package/site/.vitepress/cache/deps/vitepress___mark__js_src_vanilla__js.js +1667 -0
- package/site/.vitepress/cache/deps/vitepress___mark__js_src_vanilla__js.js 2.map +7 -0
- package/site/.vitepress/cache/deps/vitepress___mark__js_src_vanilla__js.js.map +7 -0
- package/site/.vitepress/cache/deps/vitepress___minisearch 2.js +1815 -0
- package/site/.vitepress/cache/deps/vitepress___minisearch.js +1815 -0
- package/site/.vitepress/cache/deps/vitepress___minisearch.js 2.map +7 -0
- package/site/.vitepress/cache/deps/vitepress___minisearch.js.map +7 -0
- package/site/.vitepress/cache/deps/vue 2.js +344 -0
- package/site/.vitepress/cache/deps/vue.js +344 -0
- package/site/.vitepress/cache/deps/vue.js 2.map +7 -0
- package/site/.vitepress/cache/deps/vue.js.map +7 -0
- package/site/.vitepress/config.ts +147 -0
- package/site/.vitepress/theme/custom.css +50 -0
- package/site/.vitepress/theme/index.ts +6 -0
- package/site/api/webflo-fetch/FormData.md +0 -0
- package/site/api/webflo-fetch/Headers.md +0 -0
- package/site/api/webflo-fetch/LiveResponse.md +0 -0
- package/site/api/webflo-fetch/Request.md +0 -0
- package/site/api/webflo-fetch/Response.md +0 -0
- package/site/api/webflo-fetch/fetch.md +0 -0
- package/site/api/webflo-routing/HttpCookies.md +0 -0
- package/site/api/webflo-routing/HttpEvent/respondWith.md +1 -0
- package/site/api/webflo-routing/HttpEvent/waitUntil.md +1 -0
- package/site/api/webflo-routing/HttpEvent/waitUntilNavigate.md +1 -0
- package/site/api/webflo-routing/HttpEvent.md +30 -0
- package/site/api/webflo-routing/HttpSession.md +0 -0
- package/site/api/webflo-routing/HttpState.md +0 -0
- package/site/api/webflo-routing/HttpUser.md +0 -0
- package/site/api/webflo-routing/handler/fetch.md +42 -0
- package/site/api/webflo-routing/handler/next.md +54 -0
- package/site/api/webflo-routing/handler.md +119 -0
- package/site/api.md +26 -0
- package/site/contributing.md +16 -0
- package/site/docs/advanced/lifecycles.md +20 -0
- package/site/docs/advanced/redirects.md +0 -0
- package/site/docs/advanced/routing.md +1 -0
- package/site/docs/advanced.md +9 -0
- package/site/docs/concepts/realtime.md +637 -0
- package/site/docs/concepts/rendering.md +60 -0
- package/site/docs/concepts/request-response.md +47 -0
- package/site/docs/concepts/routing.md +656 -0
- package/site/docs/concepts/state.md +44 -0
- package/site/docs/concepts/templates.md +48 -0
- package/site/docs/concepts.md +97 -0
- package/site/docs/getting-started.md +378 -0
- package/site/docs/tech-stack.md +56 -0
- package/site/docs.md +100 -0
- package/site/examples/pwa.md +10 -0
- package/site/examples/web.md +11 -0
- package/site/examples.md +10 -0
- package/site/faq.md +13 -0
- package/site/guides/guide-auth.md +13 -0
- package/site/guides/guide-file-upload.md +11 -0
- package/site/guides/guide-service-worker.md +10 -0
- package/site/guides/tutorial-1-todo.md +24 -0
- package/site/guides.md +15 -0
- package/site/index.md +39 -0
- package/site/public/img/brand/logo-670x670.png +0 -0
- package/site/recipes/realtime.md +11 -0
- package/site/recipes/streaming.md +15 -0
- package/site/reference/cli.md +11 -0
- package/site/reference/config.md +13 -0
- package/site/reference/tools.md +9 -0
- package/src/Context.js +3 -11
- package/src/config-pi/deployment/Env.js +6 -19
- package/src/config-pi/deployment/Layout.js +11 -3
- package/src/config-pi/runtime/Client.js +40 -48
- package/src/config-pi/runtime/Server.js +52 -20
- package/src/config-pi/runtime/client/Worker.js +22 -20
- package/src/config-pi/static/Init.js +57 -0
- package/src/config-pi/static/index.js +2 -0
- package/src/deployment-pi/origins/index.js +1 -1
- package/src/deployment-pi/util.js +161 -0
- package/src/index.js +3 -9
- package/src/init-pi/index.js +117 -0
- package/src/init-pi/templates/pwa/app/handler.server.js +8 -0
- package/src/init-pi/templates/pwa/app/page.html +7 -0
- package/src/init-pi/templates/pwa/package.json +19 -0
- package/src/init-pi/templates/pwa/public/assets/app.css +16 -0
- package/src/init-pi/templates/pwa/public/index.html +39 -0
- package/src/init-pi/templates/pwa/public/manifest.json +29 -0
- package/src/init-pi/templates/web/app/handler.server.js +8 -0
- package/src/init-pi/templates/web/app/page.html +7 -0
- package/src/init-pi/templates/web/package.json +19 -0
- package/src/init-pi/templates/web/public/assets/app.css +16 -0
- package/src/init-pi/templates/web/public/index.html +39 -0
- package/src/runtime-pi/WebfloRuntime.js +350 -0
- package/src/runtime-pi/index.js +3 -10
- package/src/runtime-pi/webflo-client/ClientSideCookies.js +17 -0
- package/src/runtime-pi/webflo-client/ClientSideWorkport.js +63 -0
- package/src/runtime-pi/webflo-client/DeviceCapabilities.js +213 -0
- package/src/runtime-pi/webflo-client/WebfloClient.js +500 -0
- package/src/runtime-pi/webflo-client/WebfloRootClient1.js +206 -0
- package/src/runtime-pi/webflo-client/WebfloRootClient2.js +113 -0
- package/src/runtime-pi/webflo-client/WebfloSubClient.js +118 -0
- package/src/runtime-pi/webflo-client/index.js +17 -0
- package/src/runtime-pi/webflo-client/webflo-codegen.js +469 -0
- package/src/runtime-pi/webflo-client/webflo-devmode.js +243 -0
- package/src/runtime-pi/webflo-client/webflo-embedded.js +50 -0
- package/src/runtime-pi/webflo-fetch/LiveResponse.js +437 -0
- package/src/runtime-pi/webflo-fetch/cookies.js +10 -0
- package/src/runtime-pi/webflo-fetch/fetch.js +16 -0
- package/src/runtime-pi/webflo-fetch/formdata.js +54 -0
- package/src/runtime-pi/webflo-fetch/headers.js +151 -0
- package/src/runtime-pi/webflo-fetch/index.js +5 -0
- package/src/runtime-pi/webflo-fetch/message.js +49 -0
- package/src/runtime-pi/webflo-fetch/request.js +62 -0
- package/src/runtime-pi/webflo-fetch/response.js +110 -0
- package/src/runtime-pi/webflo-fetch/util.js +28 -0
- package/src/runtime-pi/webflo-messaging/WQBroadcastChannel.js +10 -0
- package/src/runtime-pi/webflo-messaging/WQMessageChannel.js +26 -0
- package/src/runtime-pi/webflo-messaging/WQMessageEvent.js +87 -0
- package/src/runtime-pi/webflo-messaging/WQMessagePort.js +38 -0
- package/src/runtime-pi/webflo-messaging/WQRelayPort.js +47 -0
- package/src/runtime-pi/webflo-messaging/WQSockPort.js +113 -0
- package/src/runtime-pi/webflo-messaging/WQStarPort.js +104 -0
- package/src/runtime-pi/webflo-messaging/wq-message-port.js +404 -0
- package/src/runtime-pi/webflo-routing/HttpCookies.js +42 -0
- package/src/runtime-pi/webflo-routing/HttpEvent.js +112 -0
- package/src/runtime-pi/webflo-routing/HttpSession.js +11 -0
- package/src/runtime-pi/webflo-routing/HttpState.js +153 -0
- package/src/runtime-pi/webflo-routing/HttpUser.js +54 -0
- package/src/runtime-pi/webflo-routing/WebfloRouter.js +245 -0
- package/src/runtime-pi/webflo-server/ServerSideCookies.js +19 -0
- package/src/runtime-pi/webflo-server/ServerSideSession.js +38 -0
- package/src/runtime-pi/webflo-server/WebfloServer.js +937 -0
- package/src/runtime-pi/webflo-server/index.js +11 -0
- package/src/runtime-pi/webflo-server/messaging/Client.js +27 -0
- package/src/runtime-pi/webflo-server/messaging/ClientRequestRealtime.js +50 -0
- package/src/runtime-pi/webflo-server/messaging/Clients.js +25 -0
- package/src/runtime-pi/webflo-server/webflo-devmode.js +326 -0
- package/src/runtime-pi/{client → webflo-url}/Url.js +27 -76
- package/src/runtime-pi/webflo-url/index.js +1 -0
- package/src/runtime-pi/webflo-url/urlpattern.js +38 -0
- package/src/runtime-pi/{util-url.js → webflo-url/util.js} +5 -43
- package/src/runtime-pi/webflo-url/xURL.js +94 -0
- package/src/runtime-pi/webflo-worker/WebfloWorker.js +234 -0
- package/src/runtime-pi/webflo-worker/WorkerSideCookies.js +19 -0
- package/src/runtime-pi/webflo-worker/WorkerSideWorkport.js +18 -0
- package/src/runtime-pi/webflo-worker/index.js +11 -0
- package/src/services-pi/index.js +2 -0
- package/src/services-pi/push/index.js +23 -0
- package/src/util.js +10 -0
- package/src/{webflo.js → webflo-cli.js} +4 -4
- package/src/runtime-pi/Application.js +0 -29
- package/src/runtime-pi/Cookies.js +0 -82
- package/src/runtime-pi/HttpEvent.js +0 -107
- package/src/runtime-pi/Router.js +0 -130
- package/src/runtime-pi/Runtime.js +0 -21
- package/src/runtime-pi/client/Application.js +0 -76
- package/src/runtime-pi/client/Context.js +0 -7
- package/src/runtime-pi/client/Router.js +0 -48
- package/src/runtime-pi/client/Runtime.js +0 -525
- package/src/runtime-pi/client/Workport.js +0 -190
- package/src/runtime-pi/client/createStorage.js +0 -58
- package/src/runtime-pi/client/generate.js +0 -481
- package/src/runtime-pi/client/index.js +0 -21
- package/src/runtime-pi/client/worker/Application.js +0 -44
- package/src/runtime-pi/client/worker/Context.js +0 -7
- package/src/runtime-pi/client/worker/Runtime.js +0 -275
- package/src/runtime-pi/client/worker/Workport.js +0 -78
- package/src/runtime-pi/client/worker/index.js +0 -21
- package/src/runtime-pi/server/Application.js +0 -101
- package/src/runtime-pi/server/Context.js +0 -16
- package/src/runtime-pi/server/Router.js +0 -159
- package/src/runtime-pi/server/Runtime.js +0 -558
- package/src/runtime-pi/server/index.js +0 -21
- package/src/runtime-pi/util-http.js +0 -86
- package/src/runtime-pi/xFormData.js +0 -24
- package/src/runtime-pi/xHeaders.js +0 -146
- package/src/runtime-pi/xRequest.js +0 -46
- package/src/runtime-pi/xRequestHeaders.js +0 -109
- package/src/runtime-pi/xResponse.js +0 -33
- package/src/runtime-pi/xResponseHeaders.js +0 -117
- package/src/runtime-pi/xURL.js +0 -105
- package/src/runtime-pi/xfetch.js +0 -23
- package/src/runtime-pi/xxHttpMessage.js +0 -102
- package/src/static-pi/index.js +0 -11
|
@@ -0,0 +1,206 @@
|
|
|
1
|
+
import { Observer } from '@webqit/quantum-js';
|
|
2
|
+
import { WebfloClient } from './WebfloClient.js';
|
|
3
|
+
import { ClientSideWorkport } from './ClientSideWorkport.js';
|
|
4
|
+
import { DeviceCapabilities } from './DeviceCapabilities.js';
|
|
5
|
+
import { WebfloHMR } from './webflo-devmode.js';
|
|
6
|
+
|
|
7
|
+
export class WebfloRootClient1 extends WebfloClient {
|
|
8
|
+
|
|
9
|
+
static get Workport() { return ClientSideWorkport; }
|
|
10
|
+
|
|
11
|
+
static get DeviceCapabilities() { return DeviceCapabilities; }
|
|
12
|
+
|
|
13
|
+
static create(cx, host) {
|
|
14
|
+
return new this(this.Context.create(cx), host);
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
#network;
|
|
18
|
+
get network() { return this.#network; }
|
|
19
|
+
|
|
20
|
+
#workport;
|
|
21
|
+
get workport() { return this.#workport; }
|
|
22
|
+
|
|
23
|
+
#deviceCapabilities;
|
|
24
|
+
get deviceCapabilities() { return this.#deviceCapabilities; }
|
|
25
|
+
|
|
26
|
+
#hmr;
|
|
27
|
+
|
|
28
|
+
get withViewTransitions() {
|
|
29
|
+
return document.querySelector('meta[name="webflo:viewtransitions"]')?.value;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
constructor(cx, host) {
|
|
33
|
+
if (!(host instanceof Document)) {
|
|
34
|
+
throw new Error('Argument #1 must be a Document instance');
|
|
35
|
+
}
|
|
36
|
+
super(cx, host);
|
|
37
|
+
this.#network = { status: window.navigator.onLine };
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
async initialize() {
|
|
41
|
+
// INITIALIZATIONS
|
|
42
|
+
const instanceController = await super.initialize();
|
|
43
|
+
// Bind network status handlers
|
|
44
|
+
const onlineHandler = () => Observer.set(this.network, 'status', window.navigator.onLine);
|
|
45
|
+
window.addEventListener('online', onlineHandler, { signal: instanceController.signal });
|
|
46
|
+
window.addEventListener('offline', onlineHandler, { signal: instanceController.signal });
|
|
47
|
+
// Window opener pinging
|
|
48
|
+
if (window.opener) {
|
|
49
|
+
const beforeunloadHandler = () => window.opener.postMessage('close');
|
|
50
|
+
window.addEventListener('beforeunload', beforeunloadHandler, { signal: instanceController.signal });
|
|
51
|
+
}
|
|
52
|
+
// Bind top-level User-Agent requests
|
|
53
|
+
this.background.handleRequests('ua:query', async (e) => {
|
|
54
|
+
if (e.data?.query === 'push_registration') {
|
|
55
|
+
const pushManager = (await navigator.serviceWorker.getRegistration()).pushManager;
|
|
56
|
+
return await pushManager.getSubscription();
|
|
57
|
+
}
|
|
58
|
+
}, { signal: instanceController.signal });
|
|
59
|
+
// Bind top-level Storage requests
|
|
60
|
+
this.background.handleRequests('storage:query', (e) => {
|
|
61
|
+
const { source, namespace, query, key, value } = e.data;
|
|
62
|
+
const storage = source === 'session' ? sessionStorage : (source === 'local' ? localStorage : null);
|
|
63
|
+
if (!storage) return;
|
|
64
|
+
const data = JSON.parse(storage.getItem(namespace) || (query === 'set' ? '{}' : 'null'));
|
|
65
|
+
switch (query) {
|
|
66
|
+
case 'has': return !!data && Reflect.has(data, key);
|
|
67
|
+
case 'get': return data && Reflect.get(data, key);
|
|
68
|
+
case 'set':
|
|
69
|
+
Reflect.set(data, key, value);
|
|
70
|
+
return storage.setItem(namespace, JSON.stringify(data))
|
|
71
|
+
case 'delete':
|
|
72
|
+
if (!data) return;
|
|
73
|
+
Reflect.deleteProperty(data, key);
|
|
74
|
+
return storage.setItem(namespace, JSON.stringify(data));
|
|
75
|
+
case 'clear': return storage.removeItem(namespace);
|
|
76
|
+
case 'keys': return data && Reflect.ownKeys(data) || [];
|
|
77
|
+
case 'values': return data && Object.values(data) || [];
|
|
78
|
+
case 'entries': return data && Object.entries(data) || [];
|
|
79
|
+
case 'size': return data && Object.keys(data).length || 0;
|
|
80
|
+
}
|
|
81
|
+
}, { signal: instanceController.signal });
|
|
82
|
+
return instanceController;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
async setupCapabilities() {
|
|
86
|
+
const instanceController = await super.setupCapabilities();
|
|
87
|
+
// Service Worker && Capabilities
|
|
88
|
+
const cleanups = [];
|
|
89
|
+
instanceController.signal.addEventListener('abort', () => cleanups.forEach((c) => c()), { once: true });
|
|
90
|
+
this.#deviceCapabilities = await this.constructor.DeviceCapabilities.initialize(this, this.config.CLIENT.capabilities);
|
|
91
|
+
cleanups.push(() => this.#deviceCapabilities.close());
|
|
92
|
+
if (this.config.CLIENT.capabilities?.service_worker?.filename) {
|
|
93
|
+
const { service_worker: { filename, ...restServiceWorkerParams } = {} } = this.config.CLIENT.capabilities;
|
|
94
|
+
this.#workport = await this.constructor.Workport.initialize(null, (this.config.CLIENT.public_base_url || '') + filename, restServiceWorkerParams);
|
|
95
|
+
cleanups.push(() => this.#workport.close());
|
|
96
|
+
}
|
|
97
|
+
return instanceController;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
async hydrate() {
|
|
101
|
+
const instanceController = await super.hydrate();
|
|
102
|
+
const scopeObj = {};
|
|
103
|
+
scopeObj.data = this.host.querySelector(`script[rel="hydration"][type="application/json"]`)?.textContent?.trim() || null;
|
|
104
|
+
scopeObj.response = new Response.from(scopeObj.data, { headers: { 'Content-Type': 'application/json' } });
|
|
105
|
+
for (const name of ['X-Background-Messaging-Port', 'X-Live-Response-Message-ID', 'X-Webflo-Dev-Mode']) {
|
|
106
|
+
const metaElement = this.host.querySelector(`meta[name="${name}"]`);
|
|
107
|
+
if (!metaElement) continue;
|
|
108
|
+
scopeObj.response.headers.set(name, metaElement.content?.trim() || '');
|
|
109
|
+
}
|
|
110
|
+
if (scopeObj.response.isLive()) {
|
|
111
|
+
this.background.addPort(scopeObj.response.wqRealtime);
|
|
112
|
+
}
|
|
113
|
+
if (scopeObj.response.body || scopeObj.response.isLive()) {
|
|
114
|
+
const httpEvent = this.createHttpEvent({ request: this.createRequest(this.location.href) }, true);
|
|
115
|
+
await this.render(httpEvent, scopeObj.response);
|
|
116
|
+
} else {
|
|
117
|
+
await this.navigate(this.location.href);
|
|
118
|
+
}
|
|
119
|
+
if (scopeObj.response.headers.get('X-Webflo-Dev-Mode') === 'true') {
|
|
120
|
+
this.enterDevMode();
|
|
121
|
+
}
|
|
122
|
+
return instanceController;
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
async enterDevMode() {
|
|
126
|
+
this.#hmr = WebfloHMR.manage(this);
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
control() {
|
|
130
|
+
// ON LOCATION CHANGE
|
|
131
|
+
const locationCallback = (newHref) => {
|
|
132
|
+
try {
|
|
133
|
+
const scrollPosition = this.host === window.document
|
|
134
|
+
? [window.scrollX, window.scrollY]
|
|
135
|
+
: [this.host.scrollLeft, this.host.scrollTop,];
|
|
136
|
+
const state = { ...(this.currentEntry()?.getState?.() || {}), scrollPosition };
|
|
137
|
+
window.history.replaceState(state, '', this.location.href);
|
|
138
|
+
} catch (e) { }
|
|
139
|
+
try { window.history.pushState({}, '', newHref); } catch (e) { }
|
|
140
|
+
};
|
|
141
|
+
const instanceController = super.controlClassic/*IMPORTANT*/(locationCallback);
|
|
142
|
+
// ONPOPSTATE
|
|
143
|
+
const popstateHandler = (e) => {
|
|
144
|
+
if (this.isHashChange(location)) {
|
|
145
|
+
Observer.set(this.location, 'href', location.href);
|
|
146
|
+
return;
|
|
147
|
+
}
|
|
148
|
+
// Navigation details
|
|
149
|
+
const detail = {
|
|
150
|
+
navigationType: 'traverse',
|
|
151
|
+
navigationOrigins: [],
|
|
152
|
+
destination: this._asEntry(e.state),
|
|
153
|
+
source: this.currentEntry(),
|
|
154
|
+
userInitiated: true,
|
|
155
|
+
};
|
|
156
|
+
// Traversal?
|
|
157
|
+
// Push
|
|
158
|
+
this.navigate(location.href, {}, detail);
|
|
159
|
+
};
|
|
160
|
+
window.addEventListener('popstate', popstateHandler, { signal: instanceController.signal });
|
|
161
|
+
return instanceController;
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
reload() {
|
|
165
|
+
return window.history.reload();
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
back() {
|
|
169
|
+
return window.history.back();
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
forward() {
|
|
173
|
+
return window.history.forward();
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
traverseTo(...args) {
|
|
177
|
+
return window.history.go(...args);
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
async push(url, state = {}) {
|
|
181
|
+
if (typeof url === 'string' && url.startsWith('&')) { url = this.location.href.split('#')[0] + (this.location.href.includes('?') ? url : url.replace('&', '?')); }
|
|
182
|
+
url = new URL(url, this.location.href);
|
|
183
|
+
window.history.pushState(state, '', url.href);
|
|
184
|
+
Observer.set(this.location, 'href', url.href);
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
entries() {
|
|
188
|
+
return window.history;
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
currentEntry() {
|
|
192
|
+
return this._asEntry(history.state);
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
async updateCurrentEntry(params, url = null) {
|
|
196
|
+
window.history.replaceState(params.state, '', url);
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
async applyPostRenderState(httpEvent) {
|
|
200
|
+
const destinationState = httpEvent.detail.destination?.getState() || {};
|
|
201
|
+
if (destinationState.scrollPosition?.length) {
|
|
202
|
+
window.scroll(...destinationState.scrollPosition);
|
|
203
|
+
(document.querySelector('[autofocus]') || document.body).focus();
|
|
204
|
+
} else await super.applyPostRenderState(httpEvent);
|
|
205
|
+
}
|
|
206
|
+
}
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
import { Observer } from '@webqit/quantum-js';
|
|
2
|
+
import { WebfloRootClient1 } from './WebfloRootClient1.js';
|
|
3
|
+
|
|
4
|
+
export class WebfloRootClient2 extends WebfloRootClient1 {
|
|
5
|
+
|
|
6
|
+
control() {
|
|
7
|
+
const instanceController = super.controlSuper/*IMPORTANT*/();
|
|
8
|
+
// Detect source elements
|
|
9
|
+
let navigationOrigins = [];
|
|
10
|
+
// Capture all link-clicks
|
|
11
|
+
const clickHandler = (e) => {
|
|
12
|
+
if (!this._canIntercept(e) || e.defaultPrevented) return;
|
|
13
|
+
let anchorEl = e.target.closest('a');
|
|
14
|
+
if (!anchorEl || !anchorEl.href || anchorEl.target) return;
|
|
15
|
+
navigationOrigins = [anchorEl, null, anchorEl.closest('[navigationcontext]')];
|
|
16
|
+
};
|
|
17
|
+
// Capture all form-submits
|
|
18
|
+
const submitHandler = (e) => {
|
|
19
|
+
if (!this._canIntercept(e) || e.defaultPrevented) return;
|
|
20
|
+
navigationOrigins = [e.submitter, e.target.closest('form'), e.target.closest('[navigationcontext]')];
|
|
21
|
+
};
|
|
22
|
+
// Handle navigation event which happens after the above
|
|
23
|
+
const navigateHandler = (e) => {
|
|
24
|
+
if (!e.canIntercept
|
|
25
|
+
|| e.downloadRequest !== null
|
|
26
|
+
|| !this.isSpaRoute(e.destination.url)
|
|
27
|
+
|| e.navigationType === 'reload') return;
|
|
28
|
+
if (e.hashChange) {
|
|
29
|
+
Observer.set(this.location, 'href', e.destination.url);
|
|
30
|
+
return;
|
|
31
|
+
}
|
|
32
|
+
const { navigationType, destination, signal, formData, info, userInitiated } = e;
|
|
33
|
+
if (formData && navigationOrigins[1]?.hasAttribute('webflo-no-intercept')) return;
|
|
34
|
+
if (formData && (navigationOrigins[0] || {}).name) { formData.set(navigationOrigins[0].name, navigationOrigins[0].value); }
|
|
35
|
+
// Navigation details
|
|
36
|
+
const detail = {
|
|
37
|
+
navigationType,
|
|
38
|
+
navigationOrigins,
|
|
39
|
+
destination,
|
|
40
|
+
source: this.currentEntry(),
|
|
41
|
+
userInitiated,
|
|
42
|
+
info
|
|
43
|
+
};
|
|
44
|
+
navigationOrigins = [];
|
|
45
|
+
// Traversal?
|
|
46
|
+
// Push
|
|
47
|
+
const url = new URL(destination.url, this.location.href);
|
|
48
|
+
const init = {
|
|
49
|
+
method: formData && 'POST' || 'GET',
|
|
50
|
+
body: formData,
|
|
51
|
+
signal
|
|
52
|
+
};
|
|
53
|
+
this.updateCurrentEntry({
|
|
54
|
+
state: {
|
|
55
|
+
...(this.currentEntry().getState() || {}),
|
|
56
|
+
scrollPosition: [window.scrollX, window.scrollY],
|
|
57
|
+
}
|
|
58
|
+
});
|
|
59
|
+
const runtime = this;
|
|
60
|
+
e.intercept({
|
|
61
|
+
scroll: 'after-transition',
|
|
62
|
+
focusReset: 'after-transition',
|
|
63
|
+
async handler() {
|
|
64
|
+
if (navigationType === 'replace') return;
|
|
65
|
+
await runtime.navigate(url, init, detail);
|
|
66
|
+
},
|
|
67
|
+
});
|
|
68
|
+
};
|
|
69
|
+
window.addEventListener('click', clickHandler, { signal: instanceController.signal });
|
|
70
|
+
window.addEventListener('submit', submitHandler, { signal: instanceController.signal });
|
|
71
|
+
window.navigation.addEventListener('navigate', navigateHandler, { signal: instanceController.signal });
|
|
72
|
+
return instanceController;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
reload(params) {
|
|
76
|
+
return window.navigation.reload(params);
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
back() {
|
|
80
|
+
return window.navigation.canGoBack && window.navigation.back();
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
forward() {
|
|
84
|
+
return window.navigation.canGoForward && window.navigation.forward();
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
traverseTo(...args) {
|
|
88
|
+
return window.navigation.traverseTo(...args);
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
async push(url, state = {}) {
|
|
92
|
+
if (typeof url === 'string' && url.startsWith('&')) { url = this.location.href.split('#')[0] + (this.location.href.includes('?') ? url : url.replace('&', '?')); }
|
|
93
|
+
url = new URL(url, this.location.href);
|
|
94
|
+
await window.navigation.navigate(url.href, state).committed;
|
|
95
|
+
Observer.set(this.location, 'href', url.href);
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
entries() {
|
|
99
|
+
return window.navigation.entries();
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
currentEntry() {
|
|
103
|
+
return window.navigation.currentEntry;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
async updateCurrentEntry(params, url = null) {
|
|
107
|
+
if (!url || url === window.navigation.currentEntry.url) {
|
|
108
|
+
window.navigation.updateCurrentEntry(params);
|
|
109
|
+
} else {
|
|
110
|
+
await window.navigation.navigate(url, { ...params, history: 'replace' }).committed;
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
}
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
import { Observer } from '@webqit/quantum-js';
|
|
2
|
+
import { WebfloClient } from './WebfloClient.js';
|
|
3
|
+
import { defineElement } from './webflo-embedded.js';
|
|
4
|
+
import { Url } from '../webflo-url/Url.js';
|
|
5
|
+
import { _wq } from '../../util.js';
|
|
6
|
+
|
|
7
|
+
export class WebfloSubClient extends WebfloClient {
|
|
8
|
+
|
|
9
|
+
static defineElement() {
|
|
10
|
+
defineElement(this);
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
static create(superRuntime, host) {
|
|
14
|
+
return new this(superRuntime, host);
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
#superRuntime;
|
|
18
|
+
get superRuntime() { return this.#superRuntime; }
|
|
19
|
+
|
|
20
|
+
get network() { return this.#superRuntime.network; }
|
|
21
|
+
|
|
22
|
+
get workport() { return this.#superRuntime.workport; }
|
|
23
|
+
|
|
24
|
+
get deviceCapabilities() { return this.#superRuntime.deviceCapabilities; }
|
|
25
|
+
|
|
26
|
+
get withViewTransitions() { return this.host.hasAttribute('viewtransitions'); }
|
|
27
|
+
|
|
28
|
+
constructor(superRuntime, host) {
|
|
29
|
+
if (!(superRuntime instanceof WebfloClient)) {
|
|
30
|
+
throw new Error('Argument #2 must be a Webflo Client instance');
|
|
31
|
+
}
|
|
32
|
+
if (!(host instanceof HTMLElement)) {
|
|
33
|
+
throw new Error('Argument #1 must be a HTMLElement instance');
|
|
34
|
+
}
|
|
35
|
+
super(superRuntime.cx, host);
|
|
36
|
+
this.#superRuntime = superRuntime;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
async initialize() {
|
|
40
|
+
if (this.host.location.origin !== window.location.origin) {
|
|
41
|
+
throw new Error(`Webflo embeddable origin violation in "${window.location}"`);
|
|
42
|
+
}
|
|
43
|
+
const instanceController = await super.initialize();
|
|
44
|
+
_wq(this.background, 'meta').set('parentNode', this.#superRuntime.background);
|
|
45
|
+
instanceController.signal.addEventListener('abort', () => {
|
|
46
|
+
if (_wq(this.background, 'meta').get('parentNode') === this.#superRuntime.background) {
|
|
47
|
+
_wq(this.background, 'meta').set('parentNode', null);
|
|
48
|
+
}
|
|
49
|
+
}, { once: true });
|
|
50
|
+
return instanceController;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
async hydrate() {
|
|
54
|
+
const instanceController = await super.hydrate();
|
|
55
|
+
if (this.host.hasAttribute('location')) {
|
|
56
|
+
await this.navigate(this.location.href);
|
|
57
|
+
}
|
|
58
|
+
return instanceController;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
control() {
|
|
62
|
+
const locationCallback = (newHref) => {
|
|
63
|
+
this.host.reflectLocation(newHref);
|
|
64
|
+
};
|
|
65
|
+
return super.controlClassic/*IMPORTANT*/(locationCallback);
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
reload(params) {}
|
|
69
|
+
|
|
70
|
+
back() {}
|
|
71
|
+
|
|
72
|
+
forward() {}
|
|
73
|
+
|
|
74
|
+
traverseTo(...args) {}
|
|
75
|
+
|
|
76
|
+
async push(url, state = {}) {}
|
|
77
|
+
|
|
78
|
+
entries() {}
|
|
79
|
+
|
|
80
|
+
currentEntry() {}
|
|
81
|
+
|
|
82
|
+
async updateCurrentEntry(params, url = null) {
|
|
83
|
+
this.host.reflectLocation(url);
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
async applyPostRenderState(httpEvent) {
|
|
87
|
+
if (httpEvent.url.hash) {
|
|
88
|
+
this.host.querySelector(httpEvent.url.hash)?.scrollIntoView();
|
|
89
|
+
} else await super.applyPostRenderState(httpEvent);
|
|
90
|
+
(this.host.querySelector('[autofocus]') || this.host).focus();
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
redirect(location, responseRealtime = null) {
|
|
94
|
+
location = typeof location === 'string' ? new URL(location, this.location.origin) : location;
|
|
95
|
+
const width = Math.min(800, window.innerWidth);
|
|
96
|
+
const height = Math.min(600, window.innerHeight);
|
|
97
|
+
const left = (window.outerWidth - width) / 2;
|
|
98
|
+
const top = (window.outerHeight - height) / 2;
|
|
99
|
+
const popup = window.open(location, '_blank', `popup=true,width=${width},height=${height},left=${left},top=${top}`);
|
|
100
|
+
if (responseRealtime) {
|
|
101
|
+
Observer.set(this.navigator, 'redirecting', new Url/*NOT URL*/(location), { diff: true });
|
|
102
|
+
responseRealtime.addEventListener('close', (e) => {
|
|
103
|
+
window.removeEventListener('message', windowMessageHandler);
|
|
104
|
+
Observer.set(this.navigator, 'redirecting', null);
|
|
105
|
+
popup.postMessage('timeout:5');
|
|
106
|
+
setTimeout(() => {
|
|
107
|
+
popup.close();
|
|
108
|
+
}, 5000);
|
|
109
|
+
}, { once: true });
|
|
110
|
+
const windowMessageHandler = (e) => {
|
|
111
|
+
if (e.source === popup && e.data === 'close') {
|
|
112
|
+
responseRealtime.close();
|
|
113
|
+
}
|
|
114
|
+
};
|
|
115
|
+
window.addEventListener('message', windowMessageHandler);
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { WebfloRootClient1 } from './WebfloRootClient1.js';
|
|
2
|
+
import { WebfloRootClient2 } from './WebfloRootClient2.js';
|
|
3
|
+
import { WebfloSubClient } from './WebfloSubClient.js';
|
|
4
|
+
|
|
5
|
+
export async function start() {
|
|
6
|
+
const WebfloRootClient = window.navigation ? WebfloRootClient2 : WebfloRootClient1;
|
|
7
|
+
const instance = WebfloRootClient.create(this || {}, document);
|
|
8
|
+
await instance.initialize();
|
|
9
|
+
WebfloSubClient.defineElement();
|
|
10
|
+
return instance;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export {
|
|
14
|
+
WebfloRootClient1,
|
|
15
|
+
WebfloRootClient2,
|
|
16
|
+
WebfloSubClient
|
|
17
|
+
}
|