pageturn 0.1.0 → 0.2.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.
Files changed (75) hide show
  1. package/CHANGELOG.md +41 -0
  2. package/README.md +179 -4
  3. package/dist/astro.js +0 -2
  4. package/dist/chunks/chunk-3ABPYO7H.js +43 -0
  5. package/dist/chunks/chunk-6FXXBNAF.js +197 -0
  6. package/dist/chunks/chunk-AEOAXMU3.js +33 -0
  7. package/dist/chunks/chunk-BOM5VXA5.js +167 -0
  8. package/dist/chunks/chunk-C3T7BGNG.js +30 -0
  9. package/dist/chunks/chunk-FYSSNYA4.js +17 -0
  10. package/dist/chunks/chunk-JHM7F4CH.js +172 -0
  11. package/dist/chunks/chunk-LM3XLSCW.js +799 -0
  12. package/dist/chunks/{chunk-QJ7GGFM4.js → chunk-YAL4MNCU.js} +4 -6
  13. package/dist/core.js +4 -3
  14. package/dist/dev/chunks/chunk-3JAWIMHB.js +184 -0
  15. package/dist/dev/chunks/chunk-3SU4CIKL.js +799 -0
  16. package/dist/dev/chunks/chunk-AEOAXMU3.js +33 -0
  17. package/dist/dev/chunks/chunk-C3T7BGNG.js +30 -0
  18. package/dist/dev/chunks/chunk-FYSSNYA4.js +17 -0
  19. package/dist/dev/chunks/chunk-I4SBUABE.js +175 -0
  20. package/dist/dev/chunks/chunk-U3XN54YY.js +219 -0
  21. package/dist/dev/chunks/chunk-Y6TD2T53.js +43 -0
  22. package/dist/dev/chunks/chunk-YAL4MNCU.js +22 -0
  23. package/dist/dev/core.js +19 -0
  24. package/dist/dev/index.js +21 -0
  25. package/dist/dev/morph-markup.js +34 -0
  26. package/dist/dev/morph.js +457 -0
  27. package/dist/dev/native.js +3 -0
  28. package/dist/dev/next.js +79 -0
  29. package/dist/dev/nuxt-plugin.js +24 -0
  30. package/dist/dev/prefetch.js +2 -0
  31. package/dist/dev/react-router.js +46 -0
  32. package/dist/dev/router.js +9 -0
  33. package/dist/dev/sveltekit.js +32 -0
  34. package/dist/dev/testing.js +48 -0
  35. package/dist/dev/turbo.js +49 -0
  36. package/dist/dev/vue.js +11 -0
  37. package/dist/head-core.js +1 -1
  38. package/dist/head-string.js +6 -6
  39. package/dist/head.js +1 -1
  40. package/dist/index.js +6 -5
  41. package/dist/morph-head.js +1 -1
  42. package/dist/morph-markup.js +11 -9
  43. package/dist/morph.js +145 -287
  44. package/dist/native.js +3 -2
  45. package/dist/next.js +79 -0
  46. package/dist/nuxt-plugin.js +24 -0
  47. package/dist/nuxt.js +34 -0
  48. package/dist/pageturn-morph.js +1 -1
  49. package/dist/pageturn.js +1 -1
  50. package/dist/prefetch.js +2 -2
  51. package/dist/react-router.js +46 -0
  52. package/dist/router.js +5 -183
  53. package/dist/sveltekit-server.js +22 -0
  54. package/dist/sveltekit.js +32 -0
  55. package/dist/testing.js +12 -22
  56. package/dist/turbo.js +49 -0
  57. package/dist/types/astro/integration.d.ts +0 -4
  58. package/dist/types/common/dev.d.ts +6 -0
  59. package/dist/types/common/page.d.ts +5 -0
  60. package/dist/types/common/registry.d.ts +3 -1
  61. package/dist/types/next/next.d.ts +27 -0
  62. package/dist/types/nuxt/module.d.ts +32 -0
  63. package/dist/types/react-router/react-router.d.ts +12 -0
  64. package/dist/types/router/router.d.ts +4 -2
  65. package/dist/types/sveltekit/server.d.ts +21 -0
  66. package/dist/types/sveltekit/sveltekit.d.ts +32 -0
  67. package/dist/types/turbo/turbo.d.ts +1 -0
  68. package/dist/types/vue/vue.d.ts +36 -0
  69. package/dist/vue.js +11 -0
  70. package/package.json +102 -23
  71. package/dist/chunks/chunk-237GNQNZ.js +0 -37
  72. package/dist/chunks/chunk-7LMNJ25V.js +0 -244
  73. package/dist/chunks/chunk-QC36TQP3.js +0 -24
  74. package/dist/chunks/chunk-WTHN3UIQ.js +0 -1000
  75. package/dist/chunks/chunk-YBAP3PHO.js +0 -247
@@ -0,0 +1,167 @@
1
+ import {
2
+ addressOf,
3
+ choose,
4
+ followArrival,
5
+ leave,
6
+ readSession,
7
+ returnArrival,
8
+ tellArrival,
9
+ turnOf,
10
+ writeSession
11
+ } from "./chunk-JHM7F4CH.js";
12
+ import {
13
+ inBrowser,
14
+ reducesMotion
15
+ } from "./chunk-AEOAXMU3.js";
16
+ import {
17
+ registry
18
+ } from "./chunk-YAL4MNCU.js";
19
+
20
+ // src/router/router.ts
21
+ var ENTRIES_KEY = "pageturn:router:entries", KEPT_ENTRIES = 50, CLICK_FRESH_MS = 1e3, INERT = {
22
+ left: Promise.resolve(),
23
+ swapped() {
24
+ },
25
+ cancelled() {
26
+ }
27
+ }, current = null, shown = inBrowser ? location.href : "", lastClick = null;
28
+ inBrowser && (registry.w = !0, addEventListener(
29
+ "click",
30
+ (event) => {
31
+ let link = event.composedPath().find((target) => target instanceof HTMLAnchorElement);
32
+ link && (lastClick = { link, at: Date.now() });
33
+ },
34
+ !0
35
+ ));
36
+ function keyOf(url) {
37
+ let api = window.navigation, here = api?.currentEntry;
38
+ for (let entry of here ? [here, api.entries()[here.index - 1]] : [])
39
+ if (entry?.url && addressOf(new URL(entry.url)) === addressOf(url))
40
+ return entry.key;
41
+ return addressOf(url);
42
+ }
43
+ var readEntries = () => readSession(ENTRIES_KEY) ?? {};
44
+ function writeEntry(key, entry) {
45
+ let { [key]: _, ...entries } = readEntries(), kept = Object.entries(entries).slice(1 - KEPT_ENTRIES);
46
+ writeSession(ENTRIES_KEY, {
47
+ ...Object.fromEntries(kept),
48
+ ...entry ? { [key]: entry } : {}
49
+ });
50
+ }
51
+ function reportOf(from) {
52
+ let { e: report } = registry;
53
+ if (!report && !window.pageturn?.arrival) return null;
54
+ let data = null;
55
+ try {
56
+ data = report?.({ decline: () => registry.f }) ?? null;
57
+ } catch (error) {
58
+ reportError(error);
59
+ }
60
+ let isNone = data === registry.f;
61
+ return {
62
+ from: from.pathname,
63
+ at: Date.now(),
64
+ data: isNone ? null : data,
65
+ ...isNone ? { none: !0 } : {}
66
+ };
67
+ }
68
+ function clickedTo(to) {
69
+ let click = lastClick;
70
+ return click && Date.now() - click.at < CLICK_FRESH_MS && addressOf(new URL(click.link.href)) === addressOf(to) ? click.link : null;
71
+ }
72
+ function startNavigation(start) {
73
+ if (!inBrowser) return INERT;
74
+ let to = new URL(start.to, location.href);
75
+ if (!window.pageturn || window.top !== window || reducesMotion() || // The same path and query: a place in the page (#…), not another page.
76
+ addressOf(to) === addressOf(new URL(shown)))
77
+ return shown = to.href, INERT;
78
+ current && end(current, "superseded");
79
+ let from = new URL(shown), playing = {
80
+ via: start.via,
81
+ to,
82
+ from,
83
+ leftKey: start.via === "history" ? "" : keyOf(from),
84
+ e: reportOf(from)
85
+ };
86
+ current = playing;
87
+ let drive = {
88
+ left: Promise.resolve(),
89
+ swapped: () => swapped(playing),
90
+ cancelled: () => {
91
+ current === playing && end(playing, "cancelled");
92
+ }
93
+ };
94
+ if (start.via === "history") return drive;
95
+ let clicked = start.via === "link" ? start.link ?? clickedTo(to) : null, visit = {
96
+ link: clicked ?? Object.assign(document.createElement("a"), { href: to.href }),
97
+ via: clicked ? "link" : "script",
98
+ from,
99
+ to,
100
+ canHandOver: !0
101
+ }, name = start.move !== void 0 ? start.move : clicked ? choose(visit) : registry.settings.defaultMove;
102
+ if (name === null) return drive;
103
+ let turn = turnOf(visit, name);
104
+ return document.dispatchEvent(
105
+ new CustomEvent("pageturn:leaving", { cancelable: !0, detail: turn })
106
+ ) ? (playing.turn = turn, {
107
+ ...drive,
108
+ left: leave(turn, (played) => {
109
+ playing.turn = played;
110
+ }).then((handover) => {
111
+ current === playing && (playing.handover = handover);
112
+ })
113
+ }) : drive;
114
+ }
115
+ function swapped(playing) {
116
+ if (current !== playing) return;
117
+ current = null;
118
+ let reached = new URL(location.href);
119
+ shown = reached.href;
120
+ let published = window.pageturn;
121
+ if (!published) return;
122
+ published.endArrival(), delete document.documentElement.dataset.turnLeaving;
123
+ let arrival = null;
124
+ if (playing.via === "history")
125
+ arrival = returnArrival(
126
+ readEntries()[keyOf(reached)] ?? null,
127
+ playing.e
128
+ );
129
+ else {
130
+ let { turn, handover } = playing;
131
+ turn && handover && handover.arriveAs !== null && (arrival = {
132
+ move: handover.arriveAs ?? turn.move,
133
+ via: "link",
134
+ from: playing.from.pathname,
135
+ data: handover.data ?? null,
136
+ remembered: null,
137
+ reported: null
138
+ }), writeEntry(
139
+ playing.leftKey,
140
+ turn && handover?.returnAs ? {
141
+ move: turn.move,
142
+ to: reached.pathname,
143
+ returnAs: handover.returnAs,
144
+ remember: handover.remember ?? null
145
+ } : null
146
+ ), document.documentElement.dataset.turnEntering = "";
147
+ }
148
+ published.arrival = arrival, arrival && published.t?.(arrival), followArrival(), arrival && tellArrival(arrival);
149
+ }
150
+ function end(playing, reason) {
151
+ current = null, delete document.documentElement.dataset.turnLeaving;
152
+ let { turn } = playing;
153
+ if (!turn) return;
154
+ let stay = { reason, handover: playing.handover ?? null };
155
+ try {
156
+ registry.b.get(turn.move)?.stay?.(turn, stay);
157
+ } catch (error) {
158
+ reportError(error);
159
+ }
160
+ document.dispatchEvent(
161
+ new CustomEvent("pageturn:stayed", { detail: { turn, stay } })
162
+ );
163
+ }
164
+
165
+ export {
166
+ startNavigation
167
+ };
@@ -0,0 +1,30 @@
1
+ import {
2
+ inBrowser
3
+ } from "./chunk-AEOAXMU3.js";
4
+ import {
5
+ registry
6
+ } from "./chunk-YAL4MNCU.js";
7
+
8
+ // src/default-move/native.ts
9
+ var nextSwap;
10
+ !registry.a && inBrowser && (addEventListener("pageswap", (event) => {
11
+ let transition = event.viewTransition;
12
+ nextSwap === null ? transition?.skipTransition() : nextSwap && transition?.types.add(nextSwap), nextSwap = void 0;
13
+ }), registry.a = {
14
+ v(move, to) {
15
+ let store = window.pageturn?.j;
16
+ return store && window.pageturn?.a && "CSSViewTransitionRule" in window && getComputedStyle(document.documentElement).getPropertyValue("--pageturn-native").trim() !== "" ? (store.h(
17
+ {
18
+ move,
19
+ data: null,
20
+ from: location.pathname,
21
+ at: Date.now(),
22
+ a: !0
23
+ },
24
+ to
25
+ ), store.i(null), nextSwap = move, !0) : !1;
26
+ },
27
+ c: (value) => {
28
+ nextSwap = value;
29
+ }
30
+ });
@@ -0,0 +1,17 @@
1
+ import {
2
+ registry
3
+ } from "./chunk-YAL4MNCU.js";
4
+
5
+ // src/prefetch/prefetch.ts
6
+ var asked = /* @__PURE__ */ new Set();
7
+ registry.u ??= (to) => {
8
+ let address = to.href.split("#")[0] ?? to.href;
9
+ if (asked.has(address)) return;
10
+ let connection = navigator.connection;
11
+ if (connection?.saveData || /2g/.test(connection?.effectiveType ?? ""))
12
+ return;
13
+ asked.add(address);
14
+ let link = document.createElement("link");
15
+ link.relList.supports("prefetch") ? (link.rel = "prefetch", link.href = address, document.head.append(link)) : fetch(address, { priority: "low" }).catch(() => {
16
+ });
17
+ };
@@ -0,0 +1,172 @@
1
+ import {
2
+ afterDomContentLoaded
3
+ } from "./chunk-AEOAXMU3.js";
4
+ import {
5
+ isDeclined,
6
+ registry
7
+ } from "./chunk-YAL4MNCU.js";
8
+
9
+ // src/kernel/cap.ts
10
+ function capOf(property, ceiling) {
11
+ let value = getComputedStyle(document.documentElement).getPropertyValue(
12
+ property
13
+ ), max = Number.parseFloat(value) * (/ms\s*$/.test(value) ? 1 : 1e3);
14
+ return max >= 0 ? Math.min(max, ceiling) : ceiling;
15
+ }
16
+ var isEnding = (animation) => animation.effect?.getTiming().iterations !== 1 / 0, untilEnded = (animations, milliseconds) => Promise.race([
17
+ Promise.allSettled(animations.map((animation) => animation.finished)),
18
+ new Promise((resolve) => setTimeout(resolve, milliseconds))
19
+ ]);
20
+
21
+ // src/kernel/arrival.ts
22
+ var root = () => document.documentElement, watching = null, endedBy = null, ARRIVE_MAX_MS = 1e4, isArriving = () => "turnArriving" in root().dataset || "turnEntering" in root().dataset, nextFrame = () => new Promise((resolve) => requestAnimationFrame(resolve));
23
+ function endArrivalBy(by) {
24
+ isArriving() && (endedBy = by, window.pageturn?.endArrival());
25
+ }
26
+ function followArrival() {
27
+ if (stopFollowing(), !isArriving()) return;
28
+ let move = root().dataset.turnArriving ?? null, entering = "turnEntering" in root().dataset, isCut = !1;
29
+ endedBy = null;
30
+ let watch = new MutationObserver(() => {
31
+ if (move = root().dataset.turnArriving ?? move, entering && !("turnEntering" in root().dataset) && window.pageturn?.l ? entering = !1 : endedBy === null && (isCut = !0), isArriving() || (watch.disconnect(), watching === watch && (watching = null), !entering && move === null)) return;
32
+ let isManual = registry.settings.arrivalEnds === "manually", whole = endedBy !== "leave" && (isManual || endedBy === "settled" && !isCut);
33
+ document.dispatchEvent(
34
+ new CustomEvent("pageturn:arrived", {
35
+ detail: { move, entering, whole }
36
+ })
37
+ );
38
+ });
39
+ watching = watch, watch.observe(root(), {
40
+ attributeFilter: ["data-turn-arriving", "data-turn-entering"]
41
+ }), afterDomContentLoaded(async () => {
42
+ await nextFrame(), await nextFrame(), watching === watch && registry.settings.arrivalEnds !== "manually" && waitForAnimations(watch);
43
+ });
44
+ }
45
+ async function waitForAnimations(watch) {
46
+ let until = performance.now() + capOf("--turn-arrive-max", ARRIVE_MAX_MS);
47
+ for (let isFirst = !0; ; isFirst = !1) {
48
+ let running = document.getAnimations().filter(
49
+ (animation) => animation.playState === "running" && // A hover's transition is not part of an arrival.
50
+ !(typeof CSSTransition < "u" && animation instanceof CSSTransition) && isEnding(animation)
51
+ ), arrival = window.pageturn?.arrival, left = until - performance.now();
52
+ if (running.length === 0 || left <= 0) break;
53
+ if (await untilEnded(running, left), await nextFrame(), watching !== watch) return;
54
+ }
55
+ watching === watch && endArrivalBy("settled");
56
+ }
57
+ function tellArrival(arrival) {
58
+ try {
59
+ registry.b.get(arrival.move)?.arrive?.(arrival);
60
+ } catch (error) {
61
+ reportError(error);
62
+ }
63
+ }
64
+ function stopFollowing() {
65
+ watching?.disconnect(), watching = null;
66
+ }
67
+
68
+ // src/common/session.ts
69
+ function readSession(key) {
70
+ try {
71
+ let text = sessionStorage.getItem(key);
72
+ return text ? JSON.parse(text) : null;
73
+ } catch {
74
+ return null;
75
+ }
76
+ }
77
+ function writeSession(key, value) {
78
+ try {
79
+ return sessionStorage.setItem(key, JSON.stringify(value)), !0;
80
+ } catch {
81
+ return !1;
82
+ }
83
+ }
84
+ function removeSession(key) {
85
+ try {
86
+ sessionStorage.getItem(key) !== null && sessionStorage.removeItem(key);
87
+ } catch {
88
+ }
89
+ }
90
+
91
+ // src/head/storage.ts
92
+ var STORE_VERSION = 2;
93
+ var addressOf = (place) => place.pathname + place.search;
94
+ function returnArrival(entry, report) {
95
+ return !entry?.returnAs || !report || report.none || report.from !== entry.to ? null : {
96
+ move: entry.returnAs,
97
+ via: "history",
98
+ from: report.from,
99
+ data: null,
100
+ remembered: entry.remember ?? null,
101
+ reported: report.data ?? null
102
+ };
103
+ }
104
+
105
+ // src/kernel/leaving.ts
106
+ function playCssLeave(name, timeout) {
107
+ let root2 = document.documentElement, before = new Set(document.getAnimations());
108
+ root2.dataset.turnLeaving = name;
109
+ let started = document.getAnimations().filter((animation) => !before.has(animation) && isEnding(animation));
110
+ return started.length === 0 ? Promise.resolve() : untilEnded(started, capOf("--turn-leave-max", timeout)).then(
111
+ () => {
112
+ }
113
+ );
114
+ }
115
+
116
+ // src/kernel/turn.ts
117
+ function choose(visit) {
118
+ let named = visit.link.closest("[data-turn]")?.getAttribute("data-turn");
119
+ if (named) return named === "none" ? null : named;
120
+ try {
121
+ for (let chooser of registry.d) {
122
+ let name = chooser(visit);
123
+ if (name !== void 0) return name;
124
+ }
125
+ for (let [name, move] of registry.b)
126
+ if (move.match?.(visit)) return name;
127
+ } catch (error) {
128
+ reportError(error);
129
+ }
130
+ return registry.settings.defaultMove;
131
+ }
132
+ function turnOf(visit, move) {
133
+ let leaving;
134
+ return {
135
+ ...visit,
136
+ move,
137
+ leaving: () => (leaving || endArrivalBy("leave"), leaving ??= playCssLeave(move, registry.settings.leaveTimeout), leaving),
138
+ decline: () => registry.f
139
+ };
140
+ }
141
+ function leave(turn, played) {
142
+ let timedOut = new Promise(
143
+ (resolve) => setTimeout(resolve, registry.settings.leaveTimeout, null)
144
+ );
145
+ return Promise.race([run(turn, played).catch(() => null), timedOut]);
146
+ }
147
+ async function run(turn, played) {
148
+ played(turn);
149
+ let outcome = await registry.b.get(turn.move)?.leave?.(turn);
150
+ if (isDeclined(outcome)) {
151
+ let fallback = registry.settings.defaultMove;
152
+ if (fallback === null) return null;
153
+ if (fallback !== turn.move) return run(turnOf(turn, fallback), played);
154
+ } else if (outcome)
155
+ return outcome;
156
+ return await turn.leaving(), {};
157
+ }
158
+
159
+ export {
160
+ followArrival,
161
+ tellArrival,
162
+ stopFollowing,
163
+ readSession,
164
+ writeSession,
165
+ removeSession,
166
+ STORE_VERSION,
167
+ addressOf,
168
+ returnArrival,
169
+ choose,
170
+ turnOf,
171
+ leave
172
+ };