@webqit/webflo 0.20.28 → 0.20.29

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/package.json CHANGED
@@ -12,7 +12,7 @@
12
12
  "vanila-javascript"
13
13
  ],
14
14
  "homepage": "https://webqit.io/tooling/webflo",
15
- "version": "0.20.28",
15
+ "version": "0.20.29",
16
16
  "license": "MIT",
17
17
  "repository": {
18
18
  "type": "git",
@@ -41,7 +41,7 @@
41
41
  "dependencies": {
42
42
  "@octokit/webhooks": "^7.15.1",
43
43
  "@webqit/backpack": "^0.1.12",
44
- "@webqit/fetch-plus": "^0.1.21",
44
+ "@webqit/fetch-plus": "^0.1.23",
45
45
  "@webqit/keyval": "^0.2.17",
46
46
  "@webqit/observer": "^3.8.14",
47
47
  "@webqit/oohtml-ssr": "^2.2.2",
@@ -155,7 +155,7 @@ export class AppRuntime {
155
155
  if (!this.isClientSide
156
156
  && response instanceof LiveResponse) {
157
157
  // Must convert to Response on the server-side before returning
158
- const outgoingResponse = response.toResponse({ port: httpEvent.client });
158
+ const outgoingResponse = response.toResponse({ port: httpEvent.client, signal: httpEvent.signal });
159
159
  return outgoingResponse;
160
160
  }
161
161
 
@@ -168,11 +168,11 @@ export class AppRuntime {
168
168
  && response.headers.get('Location')) return;
169
169
 
170
170
  const status = await httpEvent.thread.consume('status', true);
171
- if (!status.length) return;
171
+ if (!status) return;
172
172
 
173
173
  httpEvent.waitUntil(httpEvent.client.readyStateChange('open').then(async () => {
174
- await new Promise((r) => setTimeout(r, 100));
175
- httpEvent.client.postMessage(status, { type: 'alert' });
174
+ await new Promise((r) => setTimeout(r, 500));
175
+ httpEvent.client.postMessage(status, { type: 'status' });
176
176
  await new Promise((r) => setTimeout(r, 100));
177
177
  }));
178
178
  }
@@ -1,6 +1,8 @@
1
1
  import { _before, _toTitle } from '@webqit/util/str/index.js';
2
- import { LiveResponse, RequestPlus } from '@webqit/fetch-plus';
2
+ import { Observer } from '@webqit/observer';
3
+ import { URLPlus } from '@webqit/url-plus';
3
4
  import { StarPort } from '@webqit/port-plus';
5
+ import { LiveResponse, RequestPlus } from '@webqit/fetch-plus';
4
6
  import { HttpThread111 } from '../webflo-routing/HttpThread111.js';
5
7
  import { HttpCookies101 } from '../webflo-routing/HttpCookies101.js';
6
8
  import { HttpCookies110 } from '../webflo-routing/HttpCookies110.js';
@@ -11,8 +13,6 @@ import { WebfloRouter111 } from '../webflo-routing/WebfloRouter111.js';
11
13
  import { KeyvalsFactory110 } from '../webflo-routing/KeyvalsFactory110.js';
12
14
  import { ClientRequestPort100 } from '../webflo-messaging/ClientRequestPort100.js';
13
15
  import { AppRuntime } from '../AppRuntime.js';
14
- import { Observer } from '@webqit/observer';
15
- import { URLPlus } from '@webqit/url-plus';
16
16
  import { _meta } from '../../util.js';
17
17
 
18
18
  export class WebfloClient extends AppRuntime {
@@ -69,29 +69,52 @@ export class WebfloClient extends AppRuntime {
69
69
 
70
70
  // ----------
71
71
  // Bind prompt handlers
72
- const promptsHandler = (e) => {
72
+ const dialogHandler = (e) => {
73
73
  window.queueMicrotask(() => {
74
74
  if (e.defaultPrevented) return;
75
+
75
76
  if (e.type === 'confirm') {
76
- if (e.data?.message) {
77
- e.respondWith(confirm(e.data.message));
78
- }
77
+ const dialogElement = document.createElement('wq-confirm');
78
+ dialogElement.toggleAttribute('wq-default', true);
79
+
80
+ dialogElement.render(e.data);
81
+ document.body.append(dialogElement);
82
+ dialogElement.showPopover();
83
+
84
+ dialogElement.addEventListener('response', (r) => {
85
+ e.respondWith(r.data);
86
+ setTimeout(() => dialogElement.remove(), 300);
87
+ }, { once: true });
79
88
  } else if (e.type === 'prompt') {
80
- if (e.data?.message) {
81
- e.respondWith(prompt(e.data.message));
82
- }
83
- } else if (e.type === 'alert') {
84
- for (const item of [].concat(e.data)) {
85
- if (item?.message) {
86
- alert(item.message);
87
- }
88
- }
89
+ const dialogElement = document.createElement('wq-prompt');
90
+ dialogElement.toggleAttribute('wq-default', true);
91
+
92
+ dialogElement.render(e.data);
93
+ document.body.append(dialogElement);
94
+ dialogElement.showPopover();
95
+
96
+ dialogElement.addEventListener('response', (r) => {
97
+ e.respondWith(r.data);
98
+ setTimeout(() => dialogElement.remove(), 300);
99
+ }, { once: true });
100
+ } else if (e.type === 'status') {
101
+ const dialogElement = document.createElement('wq-toast');
102
+ dialogElement.toggleAttribute('wq-default', true);
103
+
104
+ dialogElement.render(e.data);
105
+ document.body.append(dialogElement);
106
+ dialogElement.showPopover();
107
+
108
+ dialogElement.addEventListener('toggle', (t) => {
109
+ if (t.newState !== 'closed') return;
110
+ dialogElement.remove();
111
+ }, { once: true });
89
112
  }
90
113
  });
91
114
  };
92
- this.background.addEventListener('confirm', promptsHandler, { signal: instanceController.signal });
93
- this.background.addEventListener('prompt', promptsHandler, { signal: instanceController.signal });
94
- this.background.addEventListener('alert', promptsHandler, { signal: instanceController.signal });
115
+ this.background.addEventListener('confirm', dialogHandler, { signal: instanceController.signal });
116
+ this.background.addEventListener('prompt', dialogHandler, { signal: instanceController.signal });
117
+ this.background.addEventListener('status', dialogHandler, { signal: instanceController.signal });
95
118
 
96
119
  // ----------
97
120
  // Call default-init
@@ -305,7 +328,7 @@ export class WebfloClient extends AppRuntime {
305
328
  if (typeof cookieStore === 'undefined') {
306
329
  const entries = document.cookie.split(';').map((c) => c.split('=').map((s) => s.trim()));
307
330
  const store = this.#keyvals.create({ type: 'inmemory', path: ['cookies', scopeObj.tenantID], origins });
308
- entries.forEach(([key, value]) => store.set(key, { value }));
331
+ entries.forEach(([key, value]) => store.set({ key, value }));
309
332
  const initial = Object.fromEntries(entries);
310
333
  scopeObj.cookies = HttpCookies101.create({
311
334
  context: { handlersRegistry: this.#keyvals.getHandlers('cookies', true) },
@@ -440,7 +463,7 @@ export class WebfloClient extends AppRuntime {
440
463
  let response = await super.dispatchNavigationEvent({ httpEvent, crossLayerFetch, clientPortB });
441
464
 
442
465
  // Extract interactive. mode handling
443
- const handleInteractiveMode = () => {
466
+ const handleInteractiveMode = (returnImmediate = false) => {
444
467
  return new Promise(async (resolve) => {
445
468
  // Must come as first thing
446
469
  const backgroundPort = LiveResponse.getPort(response);
@@ -450,13 +473,18 @@ export class WebfloClient extends AppRuntime {
450
473
  ? response
451
474
  : LiveResponse.from(response);
452
475
 
453
- liveResponse.addEventListener('replace', (e) => {
476
+ await liveResponse.readyStateChange('live');
477
+ // IMPORTANT: ensures we're listening to subsequent changes.
478
+
479
+ liveResponse.addEventListener('replace', () => {
454
480
  if (liveResponse.headers.get('Location')) {
455
481
  this.processRedirect(liveResponse);
456
482
  } else {
457
483
  resolve(liveResponse);
458
484
  }
459
485
  }, { signal: httpEvent.signal });
486
+
487
+ if (returnImmediate) resolve(liveResponse);
460
488
  });
461
489
  };
462
490
 
@@ -495,7 +523,7 @@ export class WebfloClient extends AppRuntime {
495
523
 
496
524
  // Obtain and connect clientPortB as first thing
497
525
  if (LiveResponse.hasPort(response)) {
498
- response = await handleInteractiveMode();
526
+ response = await handleInteractiveMode(true);
499
527
  }
500
528
  }
501
529
 
@@ -100,9 +100,9 @@ export class WebfloRootClientA extends WebfloClient {
100
100
  scopeObj.response.headers.set(name, metaElement.content?.trim() || '');
101
101
  }
102
102
 
103
- if (scopeObj.response.port) {
104
- this.background.addPort(scopeObj.response.port);
105
- }
103
+ // Must come as first thing
104
+ const backgroundPort = LiveResponse.getPort(scopeObj.response);
105
+ if (backgroundPort) this.background.addPort(backgroundPort);
106
106
 
107
107
  if (scopeObj.response.body || scopeObj.response.port) {
108
108
  const httpEvent = HttpEvent111.create({ request: this.createRequest(this.location.href) }, true);
@@ -1,15 +1,10 @@
1
1
  import { Observer } from '@webqit/observer';
2
2
  import { LiveResponse } from '@webqit/fetch-plus';
3
3
  import { WebfloClient } from './WebfloClient.js';
4
- import { defineElement } from './webflo-embedded.js';
5
4
  import { _meta } from '../../util.js';
6
5
 
7
6
  export class WebfloSubClient extends WebfloClient {
8
7
 
9
- static defineElement() {
10
- defineElement(this);
11
- }
12
-
13
8
  static create(superRuntime, host) {
14
9
  return new this(superRuntime, host);
15
10
  }
@@ -67,7 +62,7 @@ export class WebfloSubClient extends WebfloClient {
67
62
  const locationCallback = (newHref) => {
68
63
  this.host.reflectLocation(newHref);
69
64
  };
70
-
65
+
71
66
  return super.controlClassic/*IMPORTANT*/(locationCallback);
72
67
  }
73
68
 
@@ -99,33 +94,35 @@ export class WebfloSubClient extends WebfloClient {
99
94
 
100
95
  async redirect(location, response = null) {
101
96
  location = typeof location === 'string' ? new URL(location, this.location.origin) : location;
102
-
97
+
103
98
  const width = Math.min(800, window.innerWidth);
104
99
  const height = Math.min(600, window.innerHeight);
105
100
  const left = (window.outerWidth - width) / 2;
106
101
  const top = (window.outerHeight - height) / 2;
107
102
  const popup = window.open(location, '_blank', `popup=true,width=${width},height=${height},left=${left},top=${top}`);
108
-
109
- const backgroundPort = response instanceof LiveResponse
103
+
104
+ const backgroundPort = response instanceof LiveResponse
110
105
  ? response.port
111
106
  : LiveResponse.getPort(response);
107
+
112
108
  if (backgroundPort) {
113
109
  Observer.set(this.navigator, 'redirecting', new URL(location), { diff: true });
114
-
115
- backgroundPort.readyStateChange('close').then((e) => {
116
- window.removeEventListener('message', windowMessageHandler);
117
-
110
+ backgroundPort.readyStateChange('close').then(() => {
118
111
  Observer.set(this.navigator, 'redirecting', null);
119
- popup.postMessage('timeout:5');
120
-
121
- setTimeout(() => {
122
- popup.close();
123
- }, 5000);
124
112
  });
125
-
113
+
126
114
  const windowMessageHandler = (e) => {
127
- if (e.source === popup && e.data === 'close') {
128
- backgroundPort.close();
115
+ if (e.source === popup) {
116
+ window.removeEventListener('message', windowMessageHandler);
117
+ if (e.data === 'canclose') {
118
+ popup.postMessage('timeout:5');
119
+ setTimeout(() => {
120
+ popup.close();
121
+ }, 5000);
122
+ }
123
+ if (e.data === 'closed') {
124
+ backgroundPort.close();
125
+ }
129
126
  }
130
127
  };
131
128
 
@@ -1,11 +1,15 @@
1
1
  import { WebfloRootClientA } from './WebfloRootClientA.js';
2
2
  import { WebfloRootClientB } from './WebfloRootClientB.js';
3
- import { WebfloSubClient } from './WebfloSubClient.js';
3
+ import { defineElement } from './webflo-embedded.js';
4
+ import { defineElements } from './webflo-elements.js';
4
5
 
5
6
  export async function start(bootstrap) {
6
7
  const WebfloRootClient = window.navigation ? WebfloRootClientB : WebfloRootClientA;
7
8
  const instance = WebfloRootClient.create(bootstrap, document);
8
9
  await instance.initialize();
9
- WebfloSubClient.defineElement();
10
+
11
+ defineElement();
12
+ defineElements();
13
+
10
14
  return instance;
11
15
  }