react-morpheus 0.1.8 → 0.1.10
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 +16 -3
- package/dist/index.d.ts +3 -0
- package/dist/index.js +18 -0
- package/package.json +16 -3
package/README.md
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
# React Morpheus
|
|
2
2
|
|
|
3
|
+
[](https://www.npmjs.com/package/react-morpheus)
|
|
4
|
+
|
|
3
5
|
A controlled React component for morphing one UI state into another.
|
|
4
6
|
|
|
5
7
|
React Morpheus exists for interfaces where a control should become the next
|
|
@@ -17,17 +19,20 @@ https://github.com/user-attachments/assets/f90e7096-f587-4793-8e80-476cf844569d
|
|
|
17
19
|
## Installation
|
|
18
20
|
|
|
19
21
|
```sh
|
|
20
|
-
bun add react-morpheus
|
|
22
|
+
bun add react-morpheus cuelume
|
|
21
23
|
```
|
|
22
24
|
|
|
23
25
|
```sh
|
|
24
|
-
npm i react-morpheus
|
|
26
|
+
npm i react-morpheus cuelume
|
|
25
27
|
```
|
|
26
28
|
|
|
27
29
|
```sh
|
|
28
|
-
yarn add react-morpheus
|
|
30
|
+
yarn add react-morpheus cuelume
|
|
29
31
|
```
|
|
30
32
|
|
|
33
|
+
Cuelume is a peer dependency that provides the optional synthesized sound
|
|
34
|
+
palette. No audio files are bundled.
|
|
35
|
+
|
|
31
36
|
## Usage
|
|
32
37
|
|
|
33
38
|
Import the component and stylesheet, keep the open state in your app, and pass
|
|
@@ -55,6 +60,8 @@ function Example() {
|
|
|
55
60
|
anchor={MorphAnchor.TopMiddle}
|
|
56
61
|
expanded={expanded}
|
|
57
62
|
onClose={() => setExpanded(false)}
|
|
63
|
+
openSound="bloom"
|
|
64
|
+
closeSound="droplet"
|
|
58
65
|
overlayColor="#0f172a"
|
|
59
66
|
overlayOpacity={0.18}
|
|
60
67
|
overlayBlur={3}
|
|
@@ -90,6 +97,8 @@ should run around the closing animation.
|
|
|
90
97
|
| `onClose` | `() => void` | Optional | Called when the overlay requests closing. Use it to update your controlled open state. |
|
|
91
98
|
| `beforeClose` | `() => void` | Optional | Called when the closing animation starts, after `expanded` has changed to `false`. Useful for close-intent side effects. |
|
|
92
99
|
| `afterClose` | `() => void` | Optional | Called after the closing animation completes. |
|
|
100
|
+
| `openSound` | `SoundName` | Optional | Cuelume sound played once when `expanded` changes to `true`. |
|
|
101
|
+
| `closeSound` | `SoundName` | Optional | Cuelume sound played once when `expanded` changes to `false`. |
|
|
93
102
|
| `collapsedContent` | `ReactNode` | Required | The source surface Morpheus measures, renders, and uses as the opener. |
|
|
94
103
|
| `expandedContent` | `ReactNode` | Required | The destination surface Morpheus measures and animates into. |
|
|
95
104
|
| `className` | `string` | Optional | Classes applied to the root wrapper. Useful for block layout and responsive width constraints. |
|
|
@@ -102,6 +111,10 @@ should run around the closing animation.
|
|
|
102
111
|
| `overlayZIndex` | `number` | Optional | Stacking level for the expanded surface. Defaults to `1000`; the overlay renders one layer below it. |
|
|
103
112
|
| `spring` | `Transition` | Optional | Framer Motion transition. Pass your own transition or use `morphSpringPresets`. |
|
|
104
113
|
|
|
114
|
+
Sound is opt-in. Both props accept any Cuelume sound name, including `bloom`,
|
|
115
|
+
`droplet`, `toggle`, `release`, and `whisper`. Omitting a prop keeps that
|
|
116
|
+
transition silent.
|
|
117
|
+
|
|
105
118
|
## Pitfalls
|
|
106
119
|
|
|
107
120
|
### Responsiveness
|
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import * as react from 'react';
|
|
2
2
|
import { ReactNode, RefObject } from 'react';
|
|
3
|
+
import { SoundName } from 'cuelume';
|
|
3
4
|
import { Transition } from 'framer-motion';
|
|
4
5
|
|
|
5
6
|
declare enum MorphAnchor {
|
|
@@ -81,6 +82,8 @@ type MorphProps = {
|
|
|
81
82
|
onClose?: (() => void) | undefined;
|
|
82
83
|
beforeClose?: (() => void) | undefined;
|
|
83
84
|
afterClose?: (() => void) | undefined;
|
|
85
|
+
openSound?: SoundName | undefined;
|
|
86
|
+
closeSound?: SoundName | undefined;
|
|
84
87
|
collapsedContent: ReactNode;
|
|
85
88
|
expandedContent: ReactNode;
|
|
86
89
|
className?: string;
|
package/dist/index.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
// src/component.tsx
|
|
2
|
+
import { play } from "cuelume";
|
|
2
3
|
import { motion as motion2 } from "framer-motion";
|
|
3
4
|
import {
|
|
4
5
|
createContext,
|
|
@@ -652,6 +653,8 @@ function MorpheusRoot({
|
|
|
652
653
|
onClose,
|
|
653
654
|
beforeClose,
|
|
654
655
|
afterClose,
|
|
656
|
+
openSound,
|
|
657
|
+
closeSound,
|
|
655
658
|
collapsedContent,
|
|
656
659
|
expandedContent,
|
|
657
660
|
className = "rmorph:relative rmorph:inline-block rmorph:align-top",
|
|
@@ -682,6 +685,9 @@ function MorpheusRoot({
|
|
|
682
685
|
const beforeCloseRef = useRef2(beforeClose);
|
|
683
686
|
const afterCloseRef = useRef2(afterClose);
|
|
684
687
|
const previousExpandedRef = useRef2(expanded);
|
|
688
|
+
const previousSoundExpandedRef = useRef2(expanded);
|
|
689
|
+
const openSoundRef = useRef2(openSound);
|
|
690
|
+
const closeSoundRef = useRef2(closeSound);
|
|
685
691
|
const portalStartFrameRef = useRef2(null);
|
|
686
692
|
const handoffFirstFrameRef = useRef2(null);
|
|
687
693
|
const handoffSecondFrameRef = useRef2(null);
|
|
@@ -691,6 +697,18 @@ function MorpheusRoot({
|
|
|
691
697
|
expandedRef.current = expanded;
|
|
692
698
|
beforeCloseRef.current = beforeClose;
|
|
693
699
|
afterCloseRef.current = afterClose;
|
|
700
|
+
openSoundRef.current = openSound;
|
|
701
|
+
closeSoundRef.current = closeSound;
|
|
702
|
+
useEffect(() => {
|
|
703
|
+
if (previousSoundExpandedRef.current === expanded) {
|
|
704
|
+
return;
|
|
705
|
+
}
|
|
706
|
+
previousSoundExpandedRef.current = expanded;
|
|
707
|
+
const sound = expanded ? openSoundRef.current : closeSoundRef.current;
|
|
708
|
+
if (sound) {
|
|
709
|
+
play(sound);
|
|
710
|
+
}
|
|
711
|
+
}, [expanded]);
|
|
694
712
|
const cancelPortalFrames = useCallback(() => {
|
|
695
713
|
if (portalStartFrameRef.current !== null) {
|
|
696
714
|
cancelAnimationFrame(portalStartFrameRef.current);
|
package/package.json
CHANGED
|
@@ -1,7 +1,19 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "react-morpheus",
|
|
3
|
-
"version": "0.1.
|
|
4
|
-
"description": "A React component for morphing one surface into
|
|
3
|
+
"version": "0.1.10",
|
|
4
|
+
"description": "A controlled React component for morphing one UI surface into another.",
|
|
5
|
+
"keywords": [
|
|
6
|
+
"react",
|
|
7
|
+
"react-component",
|
|
8
|
+
"typescript",
|
|
9
|
+
"framer-motion",
|
|
10
|
+
"ui-animation",
|
|
11
|
+
"layout-animation",
|
|
12
|
+
"morph",
|
|
13
|
+
"morphing-ui",
|
|
14
|
+
"shared-element-transition",
|
|
15
|
+
"animated-popover"
|
|
16
|
+
],
|
|
5
17
|
"type": "module",
|
|
6
18
|
"license": "MIT",
|
|
7
19
|
"sideEffects": [
|
|
@@ -26,7 +38,7 @@
|
|
|
26
38
|
"scripts": {
|
|
27
39
|
"prepare": "bun run build",
|
|
28
40
|
"build": "bun run build:js && bun run build:css",
|
|
29
|
-
"build:js": "tsup src/index.ts --format esm --dts --external react --external react-dom --external framer-motion --clean",
|
|
41
|
+
"build:js": "tsup src/index.ts --format esm --dts --external react --external react-dom --external framer-motion --external cuelume --clean",
|
|
30
42
|
"build:css": "tailwindcss -i src/style.css -o dist/style.css --minify",
|
|
31
43
|
"check": "tsc --noEmit",
|
|
32
44
|
"test": "bun test",
|
|
@@ -36,6 +48,7 @@
|
|
|
36
48
|
"release:patch": "bun run scripts/release.ts patch"
|
|
37
49
|
},
|
|
38
50
|
"peerDependencies": {
|
|
51
|
+
"cuelume": "^0.2.2",
|
|
39
52
|
"framer-motion": "^12.42.2",
|
|
40
53
|
"react": "^19.0.0",
|
|
41
54
|
"react-dom": "^19.0.0"
|