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
package/dist/morph.js CHANGED
@@ -25,70 +25,55 @@ import {
25
25
  wayBackOf,
26
26
  wayOut,
27
27
  within
28
- } from "./chunks/chunk-WTHN3UIQ.js";
28
+ } from "./chunks/chunk-LM3XLSCW.js";
29
29
  import {
30
30
  defineMove
31
- } from "./chunks/chunk-7LMNJ25V.js";
31
+ } from "./chunks/chunk-6FXXBNAF.js";
32
+ import "./chunks/chunk-JHM7F4CH.js";
32
33
  import {
33
34
  isFocusGivenBack,
34
35
  reducesMotion
35
- } from "./chunks/chunk-YBAP3PHO.js";
36
+ } from "./chunks/chunk-AEOAXMU3.js";
36
37
  import {
37
38
  isDeclined
38
- } from "./chunks/chunk-QJ7GGFM4.js";
39
+ } from "./chunks/chunk-YAL4MNCU.js";
39
40
 
40
41
  // src/morph/frame.ts
41
42
  var FRAME_STYLE = "position:fixed;top:0;border:0;margin:0;padding:0;max-width:none;max-height:none;pointer-events:none";
42
43
  function loadInFrame(address, style, name = "") {
43
44
  return new Promise((resolve) => {
44
- const frame = document.createElement("iframe");
45
- frame.name = name;
46
- frame.setAttribute("aria-hidden", "true");
47
- frame.tabIndex = -1;
48
- frame.inert = true;
49
- frame.style.cssText = `${FRAME_STYLE};width:${document.documentElement.clientWidth}px;height:${innerHeight}px;${style}`;
50
- const fail = () => {
51
- frame.remove();
52
- resolve(null);
45
+ let frame = document.createElement("iframe");
46
+ frame.name = name, frame.setAttribute("aria-hidden", "true"), frame.tabIndex = -1, frame.inert = !0, frame.style.cssText = `${FRAME_STYLE};width:${document.documentElement.clientWidth}px;height:${innerHeight}px;${style}`;
47
+ let fail = () => {
48
+ frame.remove(), resolve(null);
53
49
  };
54
- frame.addEventListener("error", fail);
55
- frame.addEventListener("load", async () => {
50
+ frame.addEventListener("error", fail), frame.addEventListener("load", async () => {
56
51
  try {
57
- await frame.contentDocument?.fonts.ready;
58
- if (!frame.contentDocument?.body) throw new Error("no page");
52
+ if (await frame.contentDocument?.fonts.ready, !frame.contentDocument?.body) throw new Error("no page");
59
53
  resolve(frame);
60
54
  } catch {
61
55
  fail();
62
56
  }
63
- });
64
- frame.src = address;
65
- document.documentElement.append(frame);
57
+ }), frame.src = address, document.documentElement.append(frame);
66
58
  });
67
59
  }
68
60
  var INTENTS = ["pointerover", "focusin", "touchstart"];
69
61
  function onApproach(tell) {
70
- let last = null;
71
- const heard = (event) => {
72
- const link = event.target instanceof Element ? event.target.closest("a[href]") : null;
73
- if (link === last) return;
74
- last = link;
75
- if (link && !isFocusGivenBack(link) && !reducesMotion()) {
76
- tell({
77
- link,
78
- via: "link",
79
- from: new URL(location.href),
80
- to: new URL(link.href),
81
- canHandOver: true
82
- });
83
- }
62
+ let last = null, heard = (event) => {
63
+ let link = event.target instanceof Element ? event.target.closest("a[href]") : null;
64
+ link !== last && (last = link, link && !isFocusGivenBack(link) && !reducesMotion() && tell({
65
+ link,
66
+ via: "link",
67
+ from: new URL(location.href),
68
+ to: new URL(link.href),
69
+ canHandOver: !0
70
+ }));
84
71
  };
85
- for (const intent of INTENTS) {
86
- addEventListener(intent, heard, { passive: true, capture: true });
87
- }
72
+ for (let intent of INTENTS)
73
+ addEventListener(intent, heard, { passive: !0, capture: !0 });
88
74
  return () => {
89
- for (const intent of INTENTS) {
90
- removeEventListener(intent, heard, { capture: true });
91
- }
75
+ for (let intent of INTENTS)
76
+ removeEventListener(intent, heard, { capture: !0 });
92
77
  };
93
78
  }
94
79
 
@@ -96,30 +81,27 @@ function onApproach(tell) {
96
81
  var BEHIND_WAIT_MS = 800;
97
82
  function behind(options = {}) {
98
83
  return (stage) => {
99
- const way = wayBackOf(stage);
84
+ let way = wayBackOf(stage);
100
85
  stage.appear = options.appear;
101
- let loading = null;
102
- const dropFrame = () => {
103
- loading?.frame.then((frame) => frame?.remove());
104
- loading = null;
86
+ let loading = null, dropFrame = () => {
87
+ loading?.frame.then((frame) => frame?.remove()), loading = null;
105
88
  };
106
89
  function showBehind(address, from) {
107
90
  if (loading?.address !== address) {
108
91
  dropFrame();
109
- const frame = loadInFrame(
92
+ let frame = loadInFrame(
110
93
  address,
111
94
  // Just under the layer, above everything of the page's.
112
95
  "left:0;opacity:0;z-index:2147483646",
113
96
  `${MORPH_KEY}:${JSON.stringify({ x: from.x, y: from.y, m: way.name, d: from.d, p: from.p, ...putBackFields(from, stage.name) })}`
114
97
  ).then((loaded) => {
115
- const view = loaded?.contentWindow;
98
+ let view = loaded?.contentWindow;
116
99
  if (!loaded || !view) return null;
117
100
  view.scrollTo(from.x, from.y);
118
- const there = loaded.contentDocument?.querySelector(
101
+ let there = loaded.contentDocument?.querySelector(
119
102
  from.p
120
103
  );
121
- if (there) there.style.visibility = "hidden";
122
- return new Promise(
104
+ return there && (there.style.visibility = "hidden"), new Promise(
123
105
  (resolve) => view.requestAnimationFrame(
124
106
  () => view.requestAnimationFrame(() => resolve(loaded))
125
107
  )
@@ -130,20 +112,16 @@ function behind(options = {}) {
130
112
  return loading.frame;
131
113
  }
132
114
  way.aims = (from, end, about) => {
133
- const ends = {
115
+ let ends = {
134
116
  from: { ...from.e },
135
117
  to: end
136
118
  };
137
- if (isDeclined(stage.morph.ends?.(ends, about))) return false;
138
- return { stop: ends.from, end: ends.to ?? end };
139
- };
140
- way.frameBehind = (visit, from) => within(showBehind(visit.to.href, from), options.wait ?? BEHIND_WAIT_MS);
141
- way.dropFrame = dropFrame;
142
- stage.onRemove.push(
119
+ return isDeclined(stage.morph.ends?.(ends, about)) ? !1 : { stop: ends.from, end: ends.to ?? end };
120
+ }, way.frameBehind = (visit, from) => within(showBehind(visit.to.href, from), options.wait ?? BEHIND_WAIT_MS), way.dropFrame = dropFrame, stage.onRemove.push(
143
121
  dropFrame,
144
122
  onApproach((visit) => {
145
- const from = way.origin();
146
- if (from && way.leadsBack?.(visit)) showBehind(visit.to.href, from);
123
+ let from = way.origin();
124
+ from && way.leadsBack?.(visit) && showBehind(visit.to.href, from);
147
125
  })
148
126
  );
149
127
  };
@@ -153,23 +131,13 @@ function behind(options = {}) {
153
131
  function copy() {
154
132
  return {
155
133
  build(element) {
156
- const layer = document.createElement("div");
157
- const content = cloned(element);
158
- const own = element;
159
- const drawn = own.offsetWidth && own.offsetHeight ? null : element.getBoundingClientRect();
160
- const width = own.offsetWidth || (drawn?.width ?? 0);
161
- const height = own.offsetHeight || (drawn?.height ?? 0);
162
- content.style.cssText += `;width:${width}px;height:${height}px;${CONTENT_STYLE}`;
163
- content.dataset.turnContent = "";
164
- layer.style.cssText = `${LAYER_STYLE};width:${width}px;height:${height}px`;
165
- layer.append(content);
166
- return layer;
134
+ let layer = document.createElement("div"), content = cloned(element), own = element, drawn = own.offsetWidth && own.offsetHeight ? null : element.getBoundingClientRect(), width = own.offsetWidth || (drawn?.width ?? 0), height = own.offsetHeight || (drawn?.height ?? 0);
135
+ return content.style.cssText += `;width:${width}px;height:${height}px;${CONTENT_STYLE}`, content.dataset.turnContent = "", layer.style.cssText = `${LAYER_STYLE};width:${width}px;height:${height}px`, layer.append(content), layer;
167
136
  },
168
137
  pose(layer) {
169
- const [width, height] = sizeOf(layer);
138
+ let [width, height] = sizeOf(layer);
170
139
  return ({ box, rotate = 0, radius }) => {
171
- const x = box.width / width;
172
- const y = box.height / height;
140
+ let x = box.width / width, y = box.height / height;
173
141
  return {
174
142
  move: {
175
143
  translate: centredOn(box, width, height),
@@ -189,79 +157,58 @@ function copy() {
189
157
  // src/morph/link-back.ts
190
158
  function linkBack(options = {}) {
191
159
  return (stage) => {
192
- const way = wayBackOf(stage);
193
- way.byLink = options;
194
- Object.assign(way.keep, options.keep);
195
- const isMarked = (link) => link.getAttribute("data-turn-back") === stage.name;
196
- way.leadsBack = (visit) => {
197
- if (isMarked(visit.link)) return true;
198
- return options.match ? options.match(visit) : visit.to.pathname === way.origin()?.f;
199
- };
200
- const started = way.origin();
201
- for (const link of document.querySelectorAll(
160
+ let way = wayBackOf(stage);
161
+ way.byLink = options, Object.assign(way.keep, options.keep);
162
+ let isMarked = (link) => link.getAttribute("data-turn-back") === stage.name;
163
+ way.leadsBack = (visit) => isMarked(visit.link) ? !0 : options.match ? options.match(visit) : visit.to.pathname === way.origin()?.f;
164
+ let started = way.origin();
165
+ for (let link of document.querySelectorAll(
202
166
  "a[data-turn-back]"
203
- )) {
204
- if (!isMarked(link)) continue;
205
- link.dataset.turn = way.name;
206
- if (started && started.f !== link.pathname) {
167
+ ))
168
+ if (isMarked(link) && (link.dataset.turn = way.name, started && started.f !== link.pathname)) {
207
169
  link.href = started.f;
208
- const label = link.dataset.turnBackLabel;
209
- if (label) link.setAttribute("aria-label", label);
170
+ let label = link.dataset.turnBackLabel;
171
+ label && link.setAttribute("aria-label", label);
210
172
  }
211
- }
212
173
  stage.onRemove.push(
213
174
  defineMove(way.name, {
214
175
  match: way.leadsBack,
215
176
  async leave(turn) {
216
- const origin = way.origin();
217
- const from = origin?.f === turn.to.pathname ? origin : null;
218
- const element = onPage(stage.morph.to);
219
- if (!element || !turn.canHandOver || stage.live) {
177
+ let origin = way.origin(), from = origin?.f === turn.to.pathname ? origin : null, element = onPage(stage.morph.to);
178
+ if (!element || !turn.canHandOver || stage.live)
220
179
  return turn.decline();
221
- }
222
- const about = stage.about(null, true);
223
- let end = stage.read(element);
224
- let stop = null;
180
+ let about = stage.about(null, !0), end = stage.read(element), stop = null;
225
181
  if (from && way.aims) {
226
- const aimed = way.aims(from, end, about);
227
- if (aimed === false) return turn.decline();
182
+ let aimed = way.aims(from, end, about);
183
+ if (aimed === !1) return turn.decline();
228
184
  ({ stop, end } = aimed);
229
185
  }
230
- if (shareOnScreen(end.box) < (options.inView ?? IN_VIEW)) {
186
+ if (shareOnScreen(end.box) < (options.inView ?? IN_VIEW))
231
187
  return turn.decline();
232
- }
233
- const frame = from && stop ? await way.frameBehind?.(turn, from) ?? null : null;
234
- const layer = await stage.put(element, end, stop);
235
- const leaving = turn.leaving();
236
- if (stop) {
237
- await stage.travel(
238
- end,
239
- stop,
240
- about,
241
- stage.timing(options),
242
- true,
243
- frame
244
- );
245
- }
246
- await leaving;
247
- const scrollsBack = from && (stop || options.scroll !== false && !turn.to.hash);
248
- stage.hand({
188
+ let frame = from && stop ? await way.frameBehind?.(turn, from) ?? null : null, layer = await stage.put(element, end, stop), leaving = turn.leaving();
189
+ stop && await stage.travel(
190
+ end,
191
+ stop,
192
+ about,
193
+ stage.timing(options),
194
+ !0,
195
+ frame
196
+ ), await leaving;
197
+ let scrollsBack = from && (stop || options.scroll !== !1 && !turn.to.hash);
198
+ return stage.hand({
249
199
  n: way.name,
250
200
  m: way.name,
251
201
  h: markup(layer),
252
202
  e: stop ?? end,
253
203
  ...stop ? { f: end } : {},
254
- t: Boolean(stop),
255
- b: Boolean(frame),
204
+ t: !!stop,
205
+ b: !!frame,
256
206
  ...backFields(from, stage.name),
257
207
  ...from && scrollsBack ? { x: from.x, y: from.y } : {}
258
- });
259
- return { data: from?.d ?? null };
208
+ }), { data: from?.d ?? null };
260
209
  },
261
210
  stay(turn, stay) {
262
- stage.drop();
263
- way.dropFrame?.();
264
- stage.morph.stay?.(turn, stay);
211
+ stage.drop(), way.dropFrame?.(), stage.morph.stay?.(turn, stay);
265
212
  }
266
213
  })
267
214
  );
@@ -271,84 +218,56 @@ function linkBack(options = {}) {
271
218
  // src/morph/peek.ts
272
219
  var PEEK_WAIT_MS = 1500;
273
220
  function peek(options = {}) {
274
- const asked = /* @__PURE__ */ new Map();
275
- const measureThere = (to, selector, measure) => {
276
- const key = `${to.href} ${selector} ${innerWidth}x${innerHeight}`;
277
- let answer = asked.get(key);
278
- if (!answer) {
279
- answer = loadInFrame(to.href, "left:-200vw;visibility:hidden").then(
280
- (frame) => {
281
- const page = frame?.contentDocument;
282
- const element = page?.querySelector(selector);
283
- for (const animation of page?.getAnimations() ?? []) {
284
- if (isEnding(animation)) animation.finish();
285
- }
286
- const end = element ? measure(element) : null;
287
- frame?.remove();
288
- if (!end) asked.delete(key);
289
- return end;
290
- }
291
- );
292
- asked.set(key, answer);
293
- }
294
- return answer;
295
- };
296
- const finder = (to, selector, measure) => within(measureThere(to, selector, measure), options.wait ?? PEEK_WAIT_MS);
297
- if (options.warm ?? true) {
298
- finder.start = (stage) => {
299
- stage.onRemove.push(
300
- onApproach((visit) => {
301
- const { match, from } = stage.morph;
302
- if (match ? match(visit) : from?.(visit.link)) {
303
- measureThere(visit.to, stage.morph.to, stage.read);
304
- }
305
- })
306
- );
307
- };
308
- }
309
- return finder;
221
+ let asked = /* @__PURE__ */ new Map(), measureThere = (to, selector, measure) => {
222
+ let key = `${to.href} ${selector} ${innerWidth}x${innerHeight}`, answer = asked.get(key);
223
+ return answer || (answer = loadInFrame(to.href, "left:-200vw;visibility:hidden").then(
224
+ (frame) => {
225
+ let page = frame?.contentDocument, element = page?.querySelector(selector);
226
+ for (let animation of page?.getAnimations() ?? [])
227
+ isEnding(animation) && animation.finish();
228
+ let end = element ? measure(element) : null;
229
+ return frame?.remove(), end || asked.delete(key), end;
230
+ }
231
+ ), asked.set(key, answer)), answer;
232
+ }, finder = (to, selector, measure) => within(measureThere(to, selector, measure), options.wait ?? PEEK_WAIT_MS);
233
+ return (options.warm ?? !0) && (finder.start = (stage) => {
234
+ stage.onRemove.push(
235
+ onApproach((visit) => {
236
+ let { match, from } = stage.morph;
237
+ (match ? match(visit) : from?.(visit.link)) && measureThere(visit.to, stage.morph.to, stage.read);
238
+ })
239
+ );
240
+ }), finder;
310
241
  }
311
242
 
312
243
  // src/morph/shadow.ts
313
244
  function asDropShadow(shadow2) {
314
245
  if (/^[-\d.]/.test(shadow2)) return shadow2;
315
- const [, color, x, y, blur] = /^(.*?\)|\S+) (\S+) (\S+) (\S+)/.exec(shadow2) ?? [];
246
+ let [, color, x, y, blur] = /^(.*?\)|\S+) (\S+) (\S+) (\S+)/.exec(shadow2) ?? [];
316
247
  return color && blur ? `${x} ${y} ${blur} ${color}` : void 0;
317
248
  }
318
249
  var dropShadow = (shadow2) => `drop-shadow(${shadow2})`;
319
250
  function shadow() {
320
251
  return (stage) => {
321
- const { read } = stage;
252
+ let { read } = stage;
322
253
  stage.read = (element) => {
323
- const end = read(element);
324
- const own = asDropShadow(getComputedStyle(element).boxShadow);
325
- if (own) end.shadow = own;
326
- return end;
327
- };
328
- stage.onPlay.push((layer, first, last, timing, finished) => {
329
- const start = first.shadow && asDropShadow(first.shadow);
330
- const stop = last.shadow && asDropShadow(last.shadow);
331
- const one = start ?? stop;
254
+ let end = read(element), own = asDropShadow(getComputedStyle(element).boxShadow);
255
+ return own && (end.shadow = own), end;
256
+ }, stage.onPlay.push((layer, first, last, timing, finished) => {
257
+ let start = first.shadow && asDropShadow(first.shadow), stop = last.shadow && asDropShadow(last.shadow), one = start ?? stop;
332
258
  if (!one) return;
333
- const caster = document.createElement("div");
334
- caster.setAttribute("aria-hidden", "true");
335
- caster.dataset.turnShadow = "";
336
- caster.style.cssText = `position:fixed;left:0;top:0;z-index:2147483646;pointer-events:none;filter:${dropShadow(one)}`;
337
- const shape = document.createElement("div");
259
+ let caster = document.createElement("div");
260
+ caster.setAttribute("aria-hidden", "true"), caster.dataset.turnShadow = "", caster.style.cssText = `position:fixed;left:0;top:0;z-index:2147483646;pointer-events:none;filter:${dropShadow(one)}`;
261
+ let shape = document.createElement("div");
338
262
  shape.style.cssText = `background:#000;width:${layer.style.width};height:${layer.style.height}`;
339
- for (const animation of layer.getAnimations()) {
340
- const { effect } = animation;
341
- if (effect instanceof KeyframeEffect) {
342
- shape.animate(effect.getKeyframes(), timing);
343
- }
263
+ for (let animation of layer.getAnimations()) {
264
+ let { effect } = animation;
265
+ effect instanceof KeyframeEffect && shape.animate(effect.getKeyframes(), timing);
344
266
  }
345
267
  caster.animate(
346
268
  start && stop ? { filter: [dropShadow(start), dropShadow(stop)] } : { opacity: start ? [1, 0] : [0, 1] },
347
269
  timing
348
- );
349
- caster.append(shape);
350
- layer.before(caster);
351
- finished.then(() => caster.remove());
270
+ ), caster.append(shape), layer.before(caster), finished.then(() => caster.remove());
352
271
  });
353
272
  };
354
273
  }
@@ -360,8 +279,7 @@ var TYPE = [
360
279
  "fontStretch",
361
280
  "letterSpacing",
362
281
  "fontVariationSettings"
363
- ];
364
- var FACE = [
282
+ ], FACE = [
365
283
  "fontFamily",
366
284
  "fontStyle",
367
285
  "textTransform",
@@ -369,19 +287,17 @@ var FACE = [
369
287
  "fontFeatureSettings"
370
288
  ];
371
289
  function glyphs(element) {
372
- const range = element.ownerDocument.createRange();
290
+ let range = element.ownerDocument.createRange();
373
291
  range.selectNodeContents(element);
374
- const { left, top, width, height } = range.getBoundingClientRect();
292
+ let { left, top, width, height } = range.getBoundingClientRect();
375
293
  return { left, top, width, height };
376
294
  }
377
295
  function splitDifference(one, other) {
378
- const least = Math.min(one.length, other.length);
379
- let head = 0;
380
- while (head < least && one[head] === other[head]) head++;
296
+ let least = Math.min(one.length, other.length), head = 0;
297
+ for (; head < least && one[head] === other[head]; ) head++;
381
298
  let tail = 0;
382
- while (tail < least - head && one[one.length - 1 - tail] === other[other.length - 1 - tail]) {
299
+ for (; tail < least - head && one[one.length - 1 - tail] === other[other.length - 1 - tail]; )
383
300
  tail++;
384
- }
385
301
  return [
386
302
  one.slice(0, head),
387
303
  one.slice(head, one.length - tail),
@@ -390,48 +306,33 @@ function splitDifference(one, other) {
390
306
  ];
391
307
  }
392
308
  function text(options = {}) {
393
- const pseudoOf = (isTo) => typeof options.box === "object" ? options.box[isTo ? "to" : "from"] : options.box;
394
- const part = (layer, name) => layer.querySelector(`[data-turn-part="${name}"]`);
309
+ let pseudoOf = (isTo) => typeof options.box == "object" ? options.box[isTo ? "to" : "from"] : options.box, part = (layer, name) => layer.querySelector(`[data-turn-part="${name}"]`);
395
310
  return {
396
311
  read(element, end, isTo) {
397
- const style = getComputedStyle(element);
398
- const type = {};
399
- for (const property of TYPE) type[property] = style[property];
400
- if (type.letterSpacing === "normal") type.letterSpacing = "0px";
401
- if (type.fontVariationSettings === "normal") {
402
- type.fontVariationSettings = `"opsz" ${Number.parseFloat(style.fontSize)}`;
403
- }
404
- let box = glyphs(element);
405
- const words = (element.textContent ?? "").replace(/\s+/g, " ").trim();
406
- end.background = style.backgroundColor;
407
- if (element.getClientRects().length === 0) {
408
- const copy2 = document.createElement("span");
312
+ let style = getComputedStyle(element), type = {};
313
+ for (let property of TYPE) type[property] = style[property];
314
+ type.letterSpacing === "normal" && (type.letterSpacing = "0px"), type.fontVariationSettings === "normal" && (type.fontVariationSettings = `"opsz" ${Number.parseFloat(style.fontSize)}`);
315
+ let box = glyphs(element), words = (element.textContent ?? "").replace(/\s+/g, " ").trim();
316
+ if (end.background = style.backgroundColor, element.getClientRects().length === 0) {
317
+ let copy2 = document.createElement("span");
409
318
  copy2.style.cssText = "position:fixed;left:0;top:0;white-space:nowrap;line-height:1;font-optical-sizing:none;visibility:hidden";
410
- for (const property of FACE) copy2.style[property] = style[property];
411
- Object.assign(copy2.style, type);
412
- copy2.textContent = words;
413
- document.documentElement.append(copy2);
414
- box = glyphs(copy2);
415
- copy2.remove();
416
- end.box = { ...box };
319
+ for (let property of FACE) copy2.style[property] = style[property];
320
+ Object.assign(copy2.style, type), copy2.textContent = words, document.documentElement.append(copy2), box = glyphs(copy2), copy2.remove(), end.box = { ...box };
417
321
  } else if (pseudoOf(isTo)) {
418
- const drawn = getComputedStyle(element, pseudoOf(isTo));
419
- const [left, top, width, height] = [
322
+ let drawn = getComputedStyle(element, pseudoOf(isTo)), [left, top, width, height] = [
420
323
  drawn.left,
421
324
  drawn.top,
422
325
  drawn.width,
423
326
  drawn.height
424
327
  ].map(Number.parseFloat);
425
328
  if (drawn.content !== "none" && [left, top, width, height].every(Number.isFinite)) {
426
- const own = element.getBoundingClientRect();
329
+ let own = element.getBoundingClientRect();
427
330
  end.box = {
428
331
  left: own.left + element.clientLeft + (left ?? 0),
429
332
  top: own.top + element.clientTop + (top ?? 0),
430
333
  width: width ?? 0,
431
334
  height: height ?? 0
432
- };
433
- end.radius = ownCorners(drawn, width ?? 0);
434
- end.background = drawn.backgroundColor;
335
+ }, end.radius = ownCorners(drawn, width ?? 0), end.background = drawn.backgroundColor;
435
336
  }
436
337
  }
437
338
  end.text = {
@@ -442,49 +343,25 @@ function text(options = {}) {
442
343
  };
443
344
  },
444
345
  build(element, from) {
445
- const layer = document.createElement("div");
446
- const content = document.createElement("span");
447
- const fill = document.createElement("span");
448
- const style = getComputedStyle(element);
449
- const type = from.text?.type ?? {};
346
+ let layer = document.createElement("div"), content = document.createElement("span"), fill = document.createElement("span"), style = getComputedStyle(element), type = from.text?.type ?? {};
450
347
  layer.style.cssText = `${LAYER_STYLE};width:0;height:0;white-space:nowrap;line-height:1;font-optical-sizing:none`;
451
- for (const property of FACE) layer.style[property] = style[property];
452
- Object.assign(layer.style, type);
453
- content.style.cssText = "position:absolute;left:0;top:0";
454
- content.textContent = from.text?.words ?? "";
455
- content.dataset.turnContent = "";
456
- content.dataset.turnWords = "";
457
- fill.style.cssText = "position:absolute;z-index:-1";
458
- fill.dataset.turnBox = "";
459
- layer.append(content, fill);
460
- return layer;
348
+ for (let property of FACE) layer.style[property] = style[property];
349
+ return Object.assign(layer.style, type), content.style.cssText = "position:absolute;left:0;top:0", content.textContent = from.text?.words ?? "", content.dataset.turnContent = "", content.dataset.turnWords = "", fill.style.cssText = "position:absolute;z-index:-1", fill.dataset.turnBox = "", layer.append(content, fill), layer;
461
350
  },
462
351
  pose(layer) {
463
- const fill = layer.lastElementChild;
464
- const insetOf = (words) => {
465
- const probe = layer.cloneNode(false);
466
- const line = document.createElement("span");
467
- probe.removeAttribute("popover");
468
- delete probe.dataset.turnLayer;
469
- Object.assign(probe.style, words.type, {
352
+ let fill = layer.lastElementChild, insetOf = (words) => {
353
+ let probe = layer.cloneNode(!1), line = document.createElement("span");
354
+ probe.removeAttribute("popover"), delete probe.dataset.turnLayer, Object.assign(probe.style, words.type, {
470
355
  translate: "none",
471
356
  rotate: "none",
472
357
  visibility: "hidden"
473
- });
474
- line.style.cssText = "position:absolute;left:0;top:0";
475
- line.textContent = words.words;
476
- probe.append(line);
477
- document.documentElement.append(probe);
478
- const corner = probe.getBoundingClientRect();
479
- const drawn = glyphs(line);
480
- probe.remove();
481
- return [drawn.left - corner.left, drawn.top - corner.top];
358
+ }), line.style.cssText = "position:absolute;left:0;top:0", line.textContent = words.words, probe.append(line), document.documentElement.append(probe);
359
+ let corner = probe.getBoundingClientRect(), drawn = glyphs(line);
360
+ return probe.remove(), [drawn.left - corner.left, drawn.top - corner.top];
482
361
  };
483
362
  return ({ text: words, rotate = 0, box, radius, background }) => {
484
363
  if (!words) throw new Error("pageturn/morph: an end has no text");
485
- const [x, y] = insetOf(words);
486
- const left = words.box.left - x;
487
- const top = words.box.top - y;
364
+ let [x, y] = insetOf(words), left = words.box.left - x, top = words.box.top - y;
488
365
  return {
489
366
  // By a translation, not `left` and `top`: Safari does not show those travel.
490
367
  move: { translate: `${left}px ${top}px`, rotate: `${rotate}deg` },
@@ -514,33 +391,22 @@ function text(options = {}) {
514
391
  };
515
392
  },
516
393
  play(layer, start, stop, timing, back2) {
517
- const content = layer.firstElementChild;
518
- const [from, to] = [start.text?.words ?? "", stop.text?.words ?? ""];
394
+ let content = layer.firstElementChild, [from, to] = [start.text?.words ?? "", stop.text?.words ?? ""];
519
395
  if (from === to || !to || content.firstElementChild) return;
520
- const [head, leaving, arriving, rest] = splitDifference(from, to);
521
- const swap = (typeof options.swap === "function" ? options.swap({ back: back2 }) : options.swap) ?? {};
522
- const span = (name, words, style) => `<span data-turn-part="${name}" style="${style}">${words.replace(/[&<]/g, (sign) => sign === "&" ? "&amp;" : "&lt;")}</span>`;
396
+ let [head, leaving, arriving, rest] = splitDifference(from, to), swap = (typeof options.swap == "function" ? options.swap({ back: back2 }) : options.swap) ?? {}, span = (name, words, style) => `<span data-turn-part="${name}" style="${style}">${words.replace(/[&<]/g, (sign) => sign === "&" ? "&amp;" : "&lt;")}</span>`;
523
397
  content.innerHTML = span("head", head, "") + `<span style="position:relative;display:inline-block">${span("arriving", arriving, "display:inline-block")}${span("leaving", leaving, "position:absolute;left:0;top:0")}</span><span data-turn-part="fit" style="display:inline-block">${span("rest", rest, "display:inline-block;white-space:pre")}</span>`;
524
- const [fit, restPart, leavingPart, arrivingPart] = [
398
+ let [fit, restPart, leavingPart, arrivingPart] = [
525
399
  "fit",
526
400
  "rest",
527
401
  "leaving",
528
402
  "arriving"
529
- ].map((name) => part(layer, name));
530
- const slot = arrivingPart?.parentElement;
531
- if (swap.clip) slot.style.clipPath = swap.clip;
532
- const widthOf = (element) => element?.getBoundingClientRect().width ?? 0;
533
- const shareToClose = () => 100 * (widthOf(arrivingPart) - widthOf(leavingPart)) / (widthOf(restPart) || 1);
534
- const atStart = shareToClose();
535
- const atStop = atTheirEnd(layer.getAnimations(), shareToClose);
536
- const swapTiming = over(timing, swap);
537
- fit?.animate({ translate: [`${-atStart}% 0`, `${-atStop}% 0`] }, timing);
538
- restPart?.animate({ translate: ["0% 0", `${atStop}% 0`] }, swapTiming);
539
- leavingPart?.animate(
403
+ ].map((name) => part(layer, name)), slot = arrivingPart?.parentElement;
404
+ swap.clip && (slot.style.clipPath = swap.clip);
405
+ let widthOf = (element) => element?.getBoundingClientRect().width ?? 0, shareToClose = () => 100 * (widthOf(arrivingPart) - widthOf(leavingPart)) / (widthOf(restPart) || 1), atStart = shareToClose(), atStop = atTheirEnd(layer.getAnimations(), shareToClose), swapTiming = over(timing, swap);
406
+ fit?.animate({ translate: [`${-atStart}% 0`, `${-atStop}% 0`] }, timing), restPart?.animate({ translate: ["0% 0", `${atStop}% 0`] }, swapTiming), leavingPart?.animate(
540
407
  swap.leave ?? [{ opacity: 1 }, { opacity: 0 }],
541
408
  swapTiming
542
- );
543
- arrivingPart?.animate(
409
+ ), arrivingPart?.animate(
544
410
  swap.arrive ?? [{ opacity: 0 }, { opacity: 1 }],
545
411
  swapTiming
546
412
  );
@@ -550,24 +416,16 @@ function text(options = {}) {
550
416
 
551
417
  // src/morph/turned.ts
552
418
  function ownTransform(style) {
553
- const [x = 1, y = x] = style.scale.split(" ").map(Number.parseFloat);
419
+ let [x = 1, y = x] = style.scale.split(" ").map(Number.parseFloat);
554
420
  return new DOMMatrix().rotate(Number.parseFloat(style.rotate) || 0).scale(x || 1, y || 1).multiply(new DOMMatrix(style.transform));
555
421
  }
556
422
  function turned() {
557
423
  return (stage) => {
558
424
  stage.endOf = (element) => {
559
- const end = endOf(element);
560
- let matrix = new DOMMatrix();
561
- for (let node = element; node; node = node.parentElement) {
425
+ let end = endOf(element), matrix = new DOMMatrix();
426
+ for (let node = element; node; node = node.parentElement)
562
427
  matrix = ownTransform(getComputedStyle(node)).multiply(matrix);
563
- }
564
- const rotate = Math.atan2(matrix.b, matrix.a) * 180 / Math.PI;
565
- const scaleX = Math.hypot(matrix.a, matrix.b);
566
- const own = element;
567
- const isTurned = Math.abs(rotate) > 0.01 && own.offsetWidth > 0;
568
- const { box } = end;
569
- const width = isTurned ? own.offsetWidth * scaleX : box.width;
570
- const height = isTurned ? own.offsetHeight * Math.hypot(matrix.c, matrix.d) : box.height;
428
+ let rotate = Math.atan2(matrix.b, matrix.a) * 180 / Math.PI, scaleX = Math.hypot(matrix.a, matrix.b), own = element, isTurned = Math.abs(rotate) > 0.01 && own.offsetWidth > 0, { box } = end, width = isTurned ? own.offsetWidth * scaleX : box.width, height = isTurned ? own.offsetHeight * Math.hypot(matrix.c, matrix.d) : box.height;
571
429
  return {
572
430
  ...end,
573
431
  box: {
package/dist/native.js CHANGED
@@ -1,2 +1,3 @@
1
- import "./chunks/chunk-237GNQNZ.js";
2
- import "./chunks/chunk-QJ7GGFM4.js";
1
+ import "./chunks/chunk-C3T7BGNG.js";
2
+ import "./chunks/chunk-AEOAXMU3.js";
3
+ import "./chunks/chunk-YAL4MNCU.js";