@maxigarcia/theme-transitions 0.2.1 → 0.4.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.
package/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # @maxigarcia/theme-transitions
2
2
 
3
- Lightweight, CSS-first theme transitions for the web. Wrap your theme change in the [View Transitions API](https://developer.mozilla.org/en-US/docs/Web/API/View_Transitions_API) and reveal the new theme with a **circular** or **sweep** animation—no animation framework required.
3
+ Lightweight, CSS-first theme transitions for the web. Wrap your theme change in the [View Transitions API](https://developer.mozilla.org/en-US/docs/Web/API/View_Transitions_API) and reveal the new theme with a **circular**, **sweep**, **fall**, or **page turn** animation—no animation framework required.
4
4
 
5
5
  ## Install
6
6
 
@@ -14,16 +14,20 @@ npm install @maxigarcia/theme-transitions
14
14
  | --------------- | ---------------------------------------------------------------- |
15
15
  | Circular reveal | [src/circular-reveal/README.md](./src/circular-reveal/README.md) |
16
16
  | Sweep reveal | [src/sweep-reveal/README.md](./src/sweep-reveal/README.md) |
17
+ | Fall | [src/fall/README.md](./src/fall/README.md) |
18
+ | Page turn | [src/page-turn/README.md](./src/page-turn/README.md) |
17
19
 
18
20
  Each module has its own README with setup, API, and usage examples.
19
21
 
20
22
  ## Package exports
21
23
 
22
- | Import | Purpose |
23
- | --------------------------------------------------- | ------------------------------------------------------------ |
24
- | `@maxigarcia/theme-transitions` | `onCircularRevealAnimation`, `onSweepRevealAnimation`, types |
25
- | `@maxigarcia/theme-transitions/circular-reveal.css` | Styles for circular reveal |
26
- | `@maxigarcia/theme-transitions/sweep-reveal.css` | Styles for sweep reveal |
24
+ | Import | Purpose |
25
+ | --------------------------------------------------- | ------------------------------------------------------------------------------------------------------ |
26
+ | `@maxigarcia/theme-transitions` | `onCircularRevealAnimation`, `onSweepRevealAnimation`, `onFallAnimation`, `onPageTurnAnimation`, types |
27
+ | `@maxigarcia/theme-transitions/page-turn.css` | Styles for page turn |
28
+ | `@maxigarcia/theme-transitions/circular-reveal.css` | Styles for circular reveal |
29
+ | `@maxigarcia/theme-transitions/fall.css` | Styles for fall |
30
+ | `@maxigarcia/theme-transitions/sweep-reveal.css` | Styles for sweep reveal |
27
31
 
28
32
  ## Live demo
29
33
 
@@ -1,4 +1,4 @@
1
- import { $html, $onTransitionEnd } from '../utils/index.js';
1
+ import { $html } from '../utils/index.js';
2
2
  export function onCircularRevealAnimation(apply, origin, options) {
3
3
  if (!document.startViewTransition) {
4
4
  apply();
@@ -16,12 +16,12 @@ export function onCircularRevealAnimation(apply, origin, options) {
16
16
  }
17
17
  html.style.setProperty('--theme-reveal-x', `${x}%`);
18
18
  html.style.setProperty('--theme-reveal-y', `${y}%`);
19
- document.startViewTransition(apply);
19
+ const transition = document.startViewTransition(apply);
20
20
  const animationComplete = () => {
21
21
  html.style.removeProperty('--theme-reveal-x');
22
22
  html.style.removeProperty('--theme-reveal-y');
23
23
  html.style.removeProperty('--theme-reveal-blur');
24
24
  html.classList.remove('circular-reveal', 'circular-reveal--blur-circle');
25
25
  };
26
- $onTransitionEnd(animationComplete, 600);
26
+ void transition.finished.finally(animationComplete);
27
27
  }
@@ -0,0 +1,57 @@
1
+ @keyframes theme-fall-out {
2
+ 0% {
3
+ transform: translateY(0) scaleY(1) scaleX(1) skewY(0deg);
4
+ }
5
+
6
+ 15% {
7
+ transform: translateY(3vh) scaleY(0.94) scaleX(1.02) skewY(1deg);
8
+ }
9
+
10
+ 100% {
11
+ transform: translateY(105%) scaleY(0.75) scaleX(1.06) skewY(4deg);
12
+ }
13
+ }
14
+
15
+ html.fall::view-transition-old(root),
16
+ html.fall::view-transition-new(root),
17
+ html.fall::view-transition-old(*),
18
+ html.fall::view-transition-new(*) {
19
+ mix-blend-mode: normal;
20
+ }
21
+
22
+ html.fall::view-transition-group(root),
23
+ html.fall::view-transition-group(*) {
24
+ animation: none;
25
+ transform-origin: bottom center;
26
+ overflow: visible;
27
+ }
28
+
29
+ html.fall::view-transition-image-pair(root),
30
+ html.fall::view-transition-image-pair(*) {
31
+ isolation: isolate;
32
+ }
33
+
34
+ html.fall::view-transition-old(root),
35
+ html.fall::view-transition-old(*) {
36
+ animation: theme-fall-out var(--theme-fall-duration, 700ms) cubic-bezier(0.33, 0, 0.67, 0.15) forwards;
37
+ transform-origin: bottom center;
38
+ opacity: 1;
39
+ z-index: 1;
40
+ }
41
+
42
+ html.fall::view-transition-new(root),
43
+ html.fall::view-transition-new(*) {
44
+ animation: none;
45
+ opacity: 1;
46
+ z-index: 0;
47
+ }
48
+
49
+ /* Reduce motion */
50
+ @media (prefers-reduced-motion: reduce) {
51
+ html.fall::view-transition-old(root),
52
+ html.fall::view-transition-new(root),
53
+ html.fall::view-transition-old(*),
54
+ html.fall::view-transition-new(*) {
55
+ animation: none;
56
+ }
57
+ }
@@ -0,0 +1,6 @@
1
+ export interface FallOptions {
2
+ /** Fall duration in milliseconds. Defaults to `700`. */
3
+ duration?: number;
4
+ }
5
+ export declare function onFallAnimation(apply: () => void, options?: FallOptions): void;
6
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/fall/index.ts"],"names":[],"mappings":"AAEA,MAAM,WAAW,WAAW;IAC1B,wDAAwD;IACxD,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,wBAAgB,eAAe,CAC7B,KAAK,EAAE,MAAM,IAAI,EACjB,OAAO,CAAC,EAAE,WAAW,GACpB,IAAI,CAqBN"}
@@ -0,0 +1,17 @@
1
+ import { $html } from '../utils/index.js';
2
+ export function onFallAnimation(apply, options) {
3
+ if (!document.startViewTransition) {
4
+ apply();
5
+ return;
6
+ }
7
+ const duration = options?.duration ?? 700;
8
+ const html = $html();
9
+ html.classList.add('fall');
10
+ html.style.setProperty('--theme-fall-duration', `${duration}ms`);
11
+ const transition = document.startViewTransition(apply);
12
+ const animationComplete = () => {
13
+ html.classList.remove('fall');
14
+ html.style.removeProperty('--theme-fall-duration');
15
+ };
16
+ void transition.finished.finally(animationComplete);
17
+ }
package/dist/index.d.ts CHANGED
@@ -1,3 +1,5 @@
1
1
  export * from './circular-reveal/index.js';
2
+ export * from './fall/index.js';
3
+ export * from './page-turn/index.js';
2
4
  export * from './sweep-reveal/index.js';
3
5
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,4BAA4B,CAAC;AAC3C,cAAc,yBAAyB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,4BAA4B,CAAC;AAC3C,cAAc,iBAAiB,CAAC;AAChC,cAAc,sBAAsB,CAAC;AACrC,cAAc,yBAAyB,CAAC"}
package/dist/index.js CHANGED
@@ -1,2 +1,4 @@
1
1
  export * from './circular-reveal/index.js';
2
+ export * from './fall/index.js';
3
+ export * from './page-turn/index.js';
2
4
  export * from './sweep-reveal/index.js';
@@ -0,0 +1,110 @@
1
+ @keyframes theme-page-turn-out-left {
2
+ 0% {
3
+ filter: brightness(1);
4
+ transform: perspective(var(--theme-page-turn-perspective, 2000px)) rotateY(0deg) rotateX(0deg);
5
+ }
6
+
7
+ 16% {
8
+ filter: brightness(0.98);
9
+ transform: perspective(var(--theme-page-turn-perspective, 2000px)) rotateY(-14deg) rotateX(0.5deg);
10
+ }
11
+
12
+ 42% {
13
+ filter: brightness(0.92) drop-shadow(-8px 2px 6px rgb(0 0 0 / 0.14));
14
+ transform: perspective(var(--theme-page-turn-perspective, 2000px)) rotateY(-50deg) rotateX(0.25deg);
15
+ }
16
+
17
+ 72% {
18
+ filter: brightness(0.9) drop-shadow(-4px 1px 4px rgb(0 0 0 / 0.1));
19
+ transform: perspective(var(--theme-page-turn-perspective, 2000px)) rotateY(-80deg) rotateX(0deg);
20
+ }
21
+
22
+ 100% {
23
+ filter: brightness(0.9);
24
+ transform: perspective(var(--theme-page-turn-perspective, 2000px)) rotateY(-90deg) rotateX(0deg);
25
+ }
26
+ }
27
+
28
+ @keyframes theme-page-turn-out-right {
29
+ 0% {
30
+ filter: brightness(1);
31
+ transform: perspective(var(--theme-page-turn-perspective, 2000px)) rotateY(0deg) rotateX(0deg);
32
+ }
33
+
34
+ 16% {
35
+ filter: brightness(0.98);
36
+ transform: perspective(var(--theme-page-turn-perspective, 2000px)) rotateY(14deg) rotateX(0.5deg);
37
+ }
38
+
39
+ 42% {
40
+ filter: brightness(0.92) drop-shadow(8px 2px 6px rgb(0 0 0 / 0.14));
41
+ transform: perspective(var(--theme-page-turn-perspective, 2000px)) rotateY(50deg) rotateX(0.25deg);
42
+ }
43
+
44
+ 72% {
45
+ filter: brightness(0.9) drop-shadow(4px 1px 4px rgb(0 0 0 / 0.1));
46
+ transform: perspective(var(--theme-page-turn-perspective, 2000px)) rotateY(80deg) rotateX(0deg);
47
+ }
48
+
49
+ 100% {
50
+ filter: brightness(0.9);
51
+ transform: perspective(var(--theme-page-turn-perspective, 2000px)) rotateY(90deg) rotateX(0deg);
52
+ }
53
+ }
54
+
55
+ html.page-turn::view-transition-old(root),
56
+ html.page-turn::view-transition-new(root),
57
+ html.page-turn::view-transition-old(*),
58
+ html.page-turn::view-transition-new(*) {
59
+ mix-blend-mode: normal;
60
+ }
61
+
62
+ html.page-turn::view-transition-group(root),
63
+ html.page-turn::view-transition-group(*) {
64
+ animation: none;
65
+ overflow: visible;
66
+ transform-style: preserve-3d;
67
+ }
68
+
69
+ html.page-turn::view-transition-image-pair(root),
70
+ html.page-turn::view-transition-image-pair(*) {
71
+ isolation: isolate;
72
+ transform-style: preserve-3d;
73
+ }
74
+
75
+ html.page-turn::view-transition-new(root),
76
+ html.page-turn::view-transition-new(*) {
77
+ animation: none;
78
+ opacity: 1;
79
+ transform: translateZ(-1px);
80
+ z-index: 0;
81
+ }
82
+
83
+ html.page-turn::view-transition-old(root),
84
+ html.page-turn::view-transition-old(*) {
85
+ animation: theme-page-turn-out-left var(--theme-page-turn-duration, 750ms) cubic-bezier(0.45, 0.05, 0.55, 0.95)
86
+ forwards;
87
+ backface-visibility: hidden;
88
+ opacity: 1;
89
+ transform-origin: left center;
90
+ transform-style: preserve-3d;
91
+ z-index: 1;
92
+ }
93
+
94
+ html.page-turn--right::view-transition-old(root),
95
+ html.page-turn--right::view-transition-old(*) {
96
+ animation-name: theme-page-turn-out-right;
97
+ transform-origin: right center;
98
+ }
99
+
100
+ /* Reduce motion */
101
+ @media (prefers-reduced-motion: reduce) {
102
+ html.page-turn::view-transition-old(root),
103
+ html.page-turn::view-transition-new(root),
104
+ html.page-turn::view-transition-old(*),
105
+ html.page-turn::view-transition-new(*) {
106
+ animation: none;
107
+ filter: none;
108
+ transform: none;
109
+ }
110
+ }
@@ -0,0 +1,9 @@
1
+ export type PageTurnEdge = 'left' | 'right';
2
+ export interface PageTurnOptions {
3
+ /** Page turn duration in milliseconds. Defaults to `750`. */
4
+ duration?: number;
5
+ /** Edge the page pivots on. Defaults to `left`. */
6
+ edge?: PageTurnEdge;
7
+ }
8
+ export declare function onPageTurnAnimation(apply: () => void, options?: PageTurnOptions): void;
9
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/page-turn/index.ts"],"names":[],"mappings":"AAEA,MAAM,MAAM,YAAY,GAAG,MAAM,GAAG,OAAO,CAAC;AAE5C,MAAM,WAAW,eAAe;IAC9B,6DAA6D;IAC7D,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,mDAAmD;IACnD,IAAI,CAAC,EAAE,YAAY,CAAC;CACrB;AAED,wBAAgB,mBAAmB,CACjC,KAAK,EAAE,MAAM,IAAI,EACjB,OAAO,CAAC,EAAE,eAAe,GACxB,IAAI,CAqBN"}
@@ -0,0 +1,18 @@
1
+ import { $html } from '../utils/index.js';
2
+ export function onPageTurnAnimation(apply, options) {
3
+ if (!document.startViewTransition) {
4
+ apply();
5
+ return;
6
+ }
7
+ const duration = options?.duration ?? 750;
8
+ const edge = options?.edge ?? 'left';
9
+ const html = $html();
10
+ html.classList.add('page-turn', `page-turn--${edge}`);
11
+ html.style.setProperty('--theme-page-turn-duration', `${duration}ms`);
12
+ const transition = document.startViewTransition(apply);
13
+ const animationComplete = () => {
14
+ html.classList.remove('page-turn', `page-turn--${edge}`);
15
+ html.style.removeProperty('--theme-page-turn-duration');
16
+ };
17
+ void transition.finished.finally(animationComplete);
18
+ }
@@ -1,4 +1,4 @@
1
- import { $html, $onTransitionEnd } from '../utils/index.js';
1
+ import { $html } from '../utils/index.js';
2
2
  export function onSweepRevealAnimation(apply, direction = 'up') {
3
3
  if (!document.startViewTransition) {
4
4
  apply();
@@ -19,11 +19,11 @@ export function onSweepRevealAnimation(apply, direction = 'up') {
19
19
  html.classList.add('sweep-reveal');
20
20
  html.style.setProperty('--theme-reveal-direction-from', directionFrom);
21
21
  html.style.setProperty('--theme-reveal-direction-to', directionTo);
22
- document.startViewTransition(apply);
22
+ const transition = document.startViewTransition(apply);
23
23
  const animationComplete = () => {
24
24
  html.classList.remove('sweep-reveal');
25
25
  html.style.removeProperty('--theme-reveal-direction-from');
26
26
  html.style.removeProperty('--theme-reveal-direction-to');
27
27
  };
28
- $onTransitionEnd(animationComplete, 600);
28
+ void transition.finished.finally(animationComplete);
29
29
  }
@@ -1,3 +1,2 @@
1
1
  export declare function $html(): HTMLElement;
2
- export declare function $onTransitionEnd(callback: () => void, duration?: number): void;
3
2
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/utils/index.ts"],"names":[],"mappings":"AAAA,wBAAgB,KAAK,gBAEpB;AAED,wBAAgB,gBAAgB,CAAC,QAAQ,EAAE,MAAM,IAAI,EAAE,QAAQ,GAAE,MAAY,QAI5E"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/utils/index.ts"],"names":[],"mappings":"AAAA,wBAAgB,KAAK,gBAEpB"}
@@ -1,8 +1,3 @@
1
1
  export function $html() {
2
2
  return document.documentElement;
3
3
  }
4
- export function $onTransitionEnd(callback, duration = 600) {
5
- setTimeout(() => {
6
- callback();
7
- }, duration);
8
- }
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@maxigarcia/theme-transitions",
3
3
  "type": "module",
4
- "version": "0.2.1",
4
+ "version": "0.4.0",
5
5
  "license": "ISC",
6
6
  "homepage": "https://github.com/MaxiGarcia13/js-theme-animation-monorepo/tree/main/packages/theme-transitions#readme",
7
7
  "repository": {
@@ -31,7 +31,9 @@
31
31
  "types": "./dist/index.d.ts",
32
32
  "import": "./dist/index.js"
33
33
  },
34
+ "./page-turn.css": "./dist/page-turn/index.css",
34
35
  "./circular-reveal.css": "./dist/circular-reveal/index.css",
36
+ "./fall.css": "./dist/fall/index.css",
35
37
  "./sweep-reveal.css": "./dist/sweep-reveal/index.css"
36
38
  },
37
39
  "main": "./dist/index.js",