react-morpheus 0.1.9 → 0.1.11
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 +38 -3
- package/dist/index.d.ts +3 -0
- package/dist/index.js +18 -0
- package/package.json +3 -2
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,21 @@ 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](https://github.com/Danilaa1/cuelume) is a required peer dependency;
|
|
34
|
+
sound playback remains opt-in. It synthesizes cues with the Web Audio API, so
|
|
35
|
+
React Morpheus does not bundle audio files.
|
|
36
|
+
|
|
31
37
|
## Usage
|
|
32
38
|
|
|
33
39
|
Import the component and stylesheet, keep the open state in your app, and pass
|
|
@@ -55,6 +61,8 @@ function Example() {
|
|
|
55
61
|
anchor={MorphAnchor.TopMiddle}
|
|
56
62
|
expanded={expanded}
|
|
57
63
|
onClose={() => setExpanded(false)}
|
|
64
|
+
openSound="bloom"
|
|
65
|
+
closeSound="droplet"
|
|
58
66
|
overlayColor="#0f172a"
|
|
59
67
|
overlayOpacity={0.18}
|
|
60
68
|
overlayBlur={3}
|
|
@@ -81,6 +89,31 @@ the source component's own click handler. Overlay clicks call `onClose`; update
|
|
|
81
89
|
your controlled state there. Use `beforeClose` and `afterClose` for work that
|
|
82
90
|
should run around the closing animation.
|
|
83
91
|
|
|
92
|
+
## Sounds
|
|
93
|
+
|
|
94
|
+
Use `openSound` and `closeSound` to add Cuelume cues to the controlled state
|
|
95
|
+
transition. React Morpheus calls Cuelume directly; you do not need to call
|
|
96
|
+
`bind()` or `play()` yourself.
|
|
97
|
+
|
|
98
|
+
```tsx
|
|
99
|
+
<Morpheus
|
|
100
|
+
expanded={expanded}
|
|
101
|
+
openSound="bloom"
|
|
102
|
+
closeSound="droplet"
|
|
103
|
+
// ...the remaining props
|
|
104
|
+
/>
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
Each configured cue plays once when `expanded` changes. The initial render is
|
|
108
|
+
silent, including when `expanded` is initially `true`. Omit either prop to keep
|
|
109
|
+
that direction silent.
|
|
110
|
+
|
|
111
|
+
Both props accept Cuelume's `SoundName` values:
|
|
112
|
+
|
|
113
|
+
`arrival`, `bloom`, `chime`, `droplet`, `error`, `loading`, `page`, `press`,
|
|
114
|
+
`pulse`, `ready`, `release`, `scan`, `sparkle`, `success`, `tick`, `toggle`, and
|
|
115
|
+
`whisper`.
|
|
116
|
+
|
|
84
117
|
## Props
|
|
85
118
|
|
|
86
119
|
| Prop | Type | Required | Notes |
|
|
@@ -90,6 +123,8 @@ should run around the closing animation.
|
|
|
90
123
|
| `onClose` | `() => void` | Optional | Called when the overlay requests closing. Use it to update your controlled open state. |
|
|
91
124
|
| `beforeClose` | `() => void` | Optional | Called when the closing animation starts, after `expanded` has changed to `false`. Useful for close-intent side effects. |
|
|
92
125
|
| `afterClose` | `() => void` | Optional | Called after the closing animation completes. |
|
|
126
|
+
| `openSound` | `SoundName` | Optional | Cuelume sound played once when `expanded` changes to `true`. |
|
|
127
|
+
| `closeSound` | `SoundName` | Optional | Cuelume sound played once when `expanded` changes to `false`. |
|
|
93
128
|
| `collapsedContent` | `ReactNode` | Required | The source surface Morpheus measures, renders, and uses as the opener. |
|
|
94
129
|
| `expandedContent` | `ReactNode` | Required | The destination surface Morpheus measures and animates into. |
|
|
95
130
|
| `className` | `string` | Optional | Classes applied to the root wrapper. Useful for block layout and responsive width constraints. |
|
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,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "react-morpheus",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.11",
|
|
4
4
|
"description": "A controlled React component for morphing one UI surface into another.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"react",
|
|
@@ -38,7 +38,7 @@
|
|
|
38
38
|
"scripts": {
|
|
39
39
|
"prepare": "bun run build",
|
|
40
40
|
"build": "bun run build:js && bun run build:css",
|
|
41
|
-
"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",
|
|
42
42
|
"build:css": "tailwindcss -i src/style.css -o dist/style.css --minify",
|
|
43
43
|
"check": "tsc --noEmit",
|
|
44
44
|
"test": "bun test",
|
|
@@ -48,6 +48,7 @@
|
|
|
48
48
|
"release:patch": "bun run scripts/release.ts patch"
|
|
49
49
|
},
|
|
50
50
|
"peerDependencies": {
|
|
51
|
+
"cuelume": "^0.2.2",
|
|
51
52
|
"framer-motion": "^12.42.2",
|
|
52
53
|
"react": "^19.0.0",
|
|
53
54
|
"react-dom": "^19.0.0"
|