@webqit/webflo 0.20.17 → 0.20.19

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.17",
15
+ "version": "0.20.19",
16
16
  "license": "MIT",
17
17
  "repository": {
18
18
  "type": "git",
@@ -322,6 +322,7 @@ export class WebfloClient extends WebfloRuntime {
322
322
  method: null
323
323
  });
324
324
  };
325
+
325
326
  // Ping existing background processes
326
327
  // !IMPORTANT: Posting to the group when empty will keep the event until next addition
327
328
  // and we don't want that
@@ -329,6 +330,7 @@ export class WebfloClient extends WebfloRuntime {
329
330
  const url = { ...Url.copy(scopeObj.url), method: scopeObj.request.method };
330
331
  this.#background.postMessage(url, { wqEventOptions: { type: 'navigate' } });
331
332
  }
333
+
332
334
  // Dispatch for response
333
335
  scopeObj.response = await this.dispatchNavigationEvent({
334
336
  httpEvent: scopeObj.httpEvent,
@@ -342,20 +344,15 @@ export class WebfloClient extends WebfloRuntime {
342
344
  clientPortB: wqMessageChannel.port2,
343
345
  originalRequestInit: scopeObj.init
344
346
  });
347
+
345
348
  // Decode response
346
349
  scopeObj.finalUrl = scopeObj.response.url || scopeObj.request.url;
347
350
  if (scopeObj.response.redirected || scopeObj.detail.navigationType === 'rdr' || scopeObj.detail.isHoisted) {
348
351
  const stateData = { ...(this.currentEntry()?.getState() || {}), redirected: true, };
349
352
  await this.updateCurrentEntry({ state: stateData }, scopeObj.finalUrl);
350
353
  }
354
+
351
355
  // Transition UI
352
- Observer.set(this.transition.from, Url.copy(this.location));
353
- Observer.set(this.transition.to, 'href', scopeObj.finalUrl);
354
- Observer.set(this.transition, 'rel', this.transition.from.pathname === this.transition.to.pathname ? 'unchanged' : (
355
- `${this.transition.from.pathname}/`.startsWith(`${this.transition.to.pathname}/`) ? 'parent' : (
356
- `${this.transition.to.pathname}/`.startsWith(`${this.transition.from.pathname}/`) ? 'child' : 'unrelated'
357
- )
358
- ));
359
356
  await this.transitionUI(async () => {
360
357
  // Set post-request states
361
358
  Observer.set(this.location, 'href', scopeObj.finalUrl);
@@ -374,12 +371,12 @@ export class WebfloClient extends WebfloRuntime {
374
371
  !(['GET'].includes(scopeObj.request.method) || scopeObj.response.redirected || scopeObj.detail.navigationType === 'rdr')
375
372
  );
376
373
  await this.applyPostRenderState(scopeObj.httpEvent);
377
- });
374
+ }, scopeObj.finalUrl, scopeObj.detail);
378
375
  }
379
376
 
380
377
  async dispatchNavigationEvent({ httpEvent, crossLayerFetch, clientPortB, originalRequestInit, processObj = {} }) {
381
378
  let response = await super.dispatchNavigationEvent({ httpEvent, crossLayerFetch, clientPortB });
382
-
379
+
383
380
  // Extract interactive. mode handling
384
381
  const handleInteractiveMode = async (resolve) => {
385
382
  const liveResponse = await LiveResponse.from(response);
@@ -469,19 +466,29 @@ export class WebfloClient extends WebfloRuntime {
469
466
  return 2; // Window reload
470
467
  }
471
468
 
472
- async transitionUI(updateCallback) {
473
- if (document.startViewTransition && this.withViewTransitions) {
469
+ async transitionUI(updateCallback, finalUrl, detail) {
470
+ // Set initial states
471
+ Observer.set(this.transition.from, Url.copy(this.location));
472
+ Observer.set(this.transition.to, 'href', finalUrl);
473
+ const viewTransitionRel = this.transition.from.pathname === this.transition.to.pathname ? 'same' : (
474
+ `${this.transition.from.pathname}/`.startsWith(`${this.transition.to.pathname}/`) ? 'out' : (
475
+ `${this.transition.to.pathname}/`.startsWith(`${this.transition.from.pathname}/`) ? 'in' : 'other'
476
+ )
477
+ );
478
+ Observer.set(this.transition, 'rel', viewTransitionRel);
479
+ // Trigger transition
480
+ if (document.startViewTransition && this.withViewTransitions && !detail.hasUAVisualTransition) {
474
481
  const synthesizeWhile = window.webqit?.realdom?.synthesizeWhile || ((callback) => callback());
475
482
  return new Promise(async (resolve) => {
476
483
  await synthesizeWhile(async () => {
477
- Observer.set(this.transition, 'phase', 1);
478
- const viewTransition = document.startViewTransition(updateCallback);
484
+ Observer.set(this.transition, 'phase', 'old');
485
+ const viewTransition = document.startViewTransition({ update: updateCallback, styles: ['navigation', viewTransitionRel] });
479
486
  try { await viewTransition.updateCallbackDone; } catch (e) { console.log(e); }
480
- Observer.set(this.transition, 'phase', 2);
487
+ Observer.set(this.transition, 'phase', 'new');
481
488
  try { await viewTransition.ready; } catch (e) { console.log(e); }
482
- Observer.set(this.transition, 'phase', 3);
489
+ Observer.set(this.transition, 'phase', 'start');
483
490
  try { await viewTransition.finished; } catch (e) { console.log(e); }
484
- Observer.set(this.transition, 'phase', 0);
491
+ Observer.set(this.transition, 'phase', 'end');
485
492
  resolve();
486
493
  });
487
494
  });
@@ -24,12 +24,16 @@ export class WebfloRootClient2 extends WebfloRootClient1 {
24
24
  if (!e.canIntercept
25
25
  || e.downloadRequest !== null
26
26
  || !this.isSpaRoute(e.destination.url)
27
- || e.navigationType === 'reload') return;
27
+ || ['reload'].includes(e.navigationType)) return;
28
28
  if (e.hashChange) {
29
29
  Observer.set(this.location, 'href', e.destination.url);
30
30
  return;
31
31
  }
32
- const { navigationType, destination, signal, formData, info, userInitiated } = e;
32
+ if (e.navigationType === 'replace') {
33
+ e.intercept({});
34
+ return;
35
+ }
36
+ const { navigationType, destination, signal, formData, info, userInitiated, hasUAVisualTransition } = e;
33
37
  if (formData && navigationOrigins[1]?.hasAttribute('webflo-no-intercept')) return;
34
38
  if (formData && (navigationOrigins[0] || {}).name) { formData.set(navigationOrigins[0].name, navigationOrigins[0].value); }
35
39
  // Navigation details
@@ -39,6 +43,7 @@ export class WebfloRootClient2 extends WebfloRootClient1 {
39
43
  destination,
40
44
  source: this.currentEntry(),
41
45
  userInitiated,
46
+ hasUAVisualTransition,
42
47
  info
43
48
  };
44
49
  navigationOrigins = [];
@@ -50,18 +55,11 @@ export class WebfloRootClient2 extends WebfloRootClient1 {
50
55
  body: formData,
51
56
  //signal TODO: auto-aborts on a redirect response which thus fails to parse
52
57
  };
53
- this.updateCurrentEntry({
54
- state: {
55
- ...(this.currentEntry().getState() || {}),
56
- scrollPosition: [window.scrollX, window.scrollY],
57
- }
58
- });
59
58
  const runtime = this;
60
59
  e.intercept({
61
60
  scroll: 'after-transition',
62
61
  focusReset: 'after-transition',
63
62
  async handler() {
64
- if (navigationType === 'replace') return;
65
63
  await runtime.navigate(url, init, detail);
66
64
  },
67
65
  });
@@ -100,7 +100,7 @@ export class WebfloSubClient extends WebfloClient {
100
100
  if (response && LiveResponse.hasBackground(response)) {
101
101
  Observer.set(this.navigator, 'redirecting', new Url/*NOT URL*/(location), { diff: true });
102
102
  const backgroundPort = LiveResponse.getBackground(response);
103
- backgroundPort.postMessage('keep-alive');
103
+ backgroundPort.postMessage(true, { wqEventOptions: { type: 'keep-alive' } });
104
104
  backgroundPort.addEventListener('close', (e) => {
105
105
  window.removeEventListener('message', windowMessageHandler);
106
106
  Observer.set(this.navigator, 'redirecting', null);
@@ -498,7 +498,7 @@ export class WebfloServer extends WebfloRuntime {
498
498
  const xRedirectCode = httpEvent.request.headers.get('X-Redirect-Code') || 300;
499
499
  const destinationURL = new URL(response.headers.get('Location'), httpEvent.url.origin);
500
500
  const isSameOriginRedirect = destinationURL.origin === httpEvent.url.origin;
501
- let isSameSpaRedirect = false;
501
+ let isSameSpaRedirect = true;
502
502
  if (isSameOriginRedirect && xRedirectPolicy === 'manual-when-cross-spa' && $sparoots.length) {
503
503
  // Longest-first sorting
504
504
  const sparoots = $sparoots.sort((a, b) => a.length > b.length ? -1 : 1);