@leavepulse/ui 0.95.1 → 0.95.2
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.
|
@@ -1,7 +1,10 @@
|
|
|
1
1
|
import { ref, onScopeDispose, readonly } from "vue";
|
|
2
|
+
import { prefersReducedMotion } from "./easing.js";
|
|
2
3
|
const OVERLAY = '[role="dialog"], [role="alertdialog"], [role="menu"], [role="listbox"], [data-state="open"][data-side]';
|
|
3
4
|
const INPUT_EVENTS = ["pointerdown", "keydown", "wheel", "touchstart", "input"];
|
|
4
5
|
const CARRY_MS = 6e4;
|
|
6
|
+
const FADE_OUT_MS = 220;
|
|
7
|
+
const FADE_IN_MS = 320;
|
|
5
8
|
function editableFocused() {
|
|
6
9
|
const el = document.activeElement;
|
|
7
10
|
if (!(el instanceof HTMLElement)) return false;
|
|
@@ -34,6 +37,9 @@ function useAppUpdate(options) {
|
|
|
34
37
|
const carried = readCarried(key);
|
|
35
38
|
if (carried && carried.href === location.href && Date.now() - carried.at < CARRY_MS) {
|
|
36
39
|
restored.value = true;
|
|
40
|
+
if (!prefersReducedMotion()) {
|
|
41
|
+
document.documentElement.animate([{ opacity: 0 }, { opacity: 1 }], { duration: FADE_IN_MS, easing: "cubic-bezier(0.2, 0, 0, 1)" });
|
|
42
|
+
}
|
|
37
43
|
const top = carried.top;
|
|
38
44
|
const restore = () => window.scrollTo({ top, behavior: "instant" });
|
|
39
45
|
requestAnimationFrame(() => requestAnimationFrame(restore));
|
|
@@ -44,7 +50,12 @@ function useAppUpdate(options) {
|
|
|
44
50
|
sessionStorage.setItem(key, JSON.stringify({ href: location.href, top: window.scrollY, at: Date.now() }));
|
|
45
51
|
} catch {
|
|
46
52
|
}
|
|
47
|
-
|
|
53
|
+
if (document.hidden || prefersReducedMotion()) {
|
|
54
|
+
location.reload();
|
|
55
|
+
return;
|
|
56
|
+
}
|
|
57
|
+
const fade = document.documentElement.animate([{ opacity: 1 }, { opacity: 0 }], { duration: FADE_OUT_MS, easing: "ease-in", fill: "forwards" });
|
|
58
|
+
fade.finished.then(() => location.reload(), () => location.reload());
|
|
48
59
|
}
|
|
49
60
|
function safe() {
|
|
50
61
|
if (document.hidden) return true;
|
package/package.json
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { onScopeDispose, readonly, ref, type Ref } from "vue"
|
|
2
|
+
import { prefersReducedMotion } from "./easing"
|
|
2
3
|
|
|
3
4
|
/*
|
|
4
5
|
* A new build is out and every open tab should run it, without anyone losing
|
|
@@ -20,6 +21,10 @@ import { onScopeDispose, readonly, ref, type Ref } from "vue"
|
|
|
20
21
|
* window scroll position, and anything the app already keeps in storage, such
|
|
21
22
|
* as form drafts. After the reload `restored` is true for the app to say
|
|
22
23
|
* "updated" if it wants to.
|
|
24
|
+
*
|
|
25
|
+
* A visible reload does not blink: the page fades out before it and fades back
|
|
26
|
+
* in after it, so the swap reads as one change rather than a flash of blank.
|
|
27
|
+
* Under reduced motion, and in a hidden tab, it simply reloads.
|
|
23
28
|
*/
|
|
24
29
|
|
|
25
30
|
export interface AppUpdateOptions {
|
|
@@ -51,6 +56,8 @@ export interface AppUpdate {
|
|
|
51
56
|
const OVERLAY = '[role="dialog"], [role="alertdialog"], [role="menu"], [role="listbox"], [data-state="open"][data-side]'
|
|
52
57
|
const INPUT_EVENTS = ["pointerdown", "keydown", "wheel", "touchstart", "input"] as const
|
|
53
58
|
const CARRY_MS = 60_000
|
|
59
|
+
const FADE_OUT_MS = 220
|
|
60
|
+
const FADE_IN_MS = 320
|
|
54
61
|
|
|
55
62
|
interface Carried {
|
|
56
63
|
href: string
|
|
@@ -94,6 +101,9 @@ export function useAppUpdate(options: AppUpdateOptions): AppUpdate {
|
|
|
94
101
|
const carried = readCarried(key)
|
|
95
102
|
if (carried && carried.href === location.href && Date.now() - carried.at < CARRY_MS) {
|
|
96
103
|
restored.value = true
|
|
104
|
+
if (!prefersReducedMotion()) {
|
|
105
|
+
document.documentElement.animate([{ opacity: 0 }, { opacity: 1 }], { duration: FADE_IN_MS, easing: "cubic-bezier(0.2, 0, 0, 1)" })
|
|
106
|
+
}
|
|
97
107
|
const top = carried.top
|
|
98
108
|
const restore = () => window.scrollTo({ top, behavior: "instant" })
|
|
99
109
|
requestAnimationFrame(() => requestAnimationFrame(restore))
|
|
@@ -106,7 +116,12 @@ export function useAppUpdate(options: AppUpdateOptions): AppUpdate {
|
|
|
106
116
|
} catch {
|
|
107
117
|
// Storage off: the reload still happens, only the scroll is lost.
|
|
108
118
|
}
|
|
109
|
-
|
|
119
|
+
if (document.hidden || prefersReducedMotion()) {
|
|
120
|
+
location.reload()
|
|
121
|
+
return
|
|
122
|
+
}
|
|
123
|
+
const fade = document.documentElement.animate([{ opacity: 1 }, { opacity: 0 }], { duration: FADE_OUT_MS, easing: "ease-in", fill: "forwards" })
|
|
124
|
+
fade.finished.then(() => location.reload(), () => location.reload())
|
|
110
125
|
}
|
|
111
126
|
|
|
112
127
|
function safe(): boolean {
|