@moontra/moonui 2.4.5 → 2.4.7
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 +73 -51
- package/dist/index.d.mts +81 -3
- package/dist/index.d.ts +81 -3
- package/dist/index.global.js +29 -29
- package/dist/index.global.js.map +1 -1
- package/dist/index.js +104 -103
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +105 -104
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
- package/src/components/ui/scroll-reveal.tsx +201 -112
- package/src/components/ui/tags-input.tsx +1 -1
package/package.json
CHANGED
|
@@ -1,54 +1,96 @@
|
|
|
1
1
|
"use client"
|
|
2
2
|
|
|
3
3
|
import * as React from "react"
|
|
4
|
-
import { motion,
|
|
4
|
+
import { motion, Variants, Transition, UseInViewOptions } from "framer-motion"
|
|
5
5
|
import { cn } from "../../lib/utils"
|
|
6
6
|
|
|
7
|
+
/**
|
|
8
|
+
* ScrollReveal Component
|
|
9
|
+
*
|
|
10
|
+
* Reveals content with smooth animations when scrolling into view
|
|
11
|
+
* Built with Framer Motion for performance and flexibility
|
|
12
|
+
*
|
|
13
|
+
* @example
|
|
14
|
+
* ```tsx
|
|
15
|
+
* <ScrollReveal direction="up" delay={0.2}>
|
|
16
|
+
* <Card>Your content</Card>
|
|
17
|
+
* </ScrollReveal>
|
|
18
|
+
* ```
|
|
19
|
+
*/
|
|
20
|
+
|
|
7
21
|
interface ScrollRevealProps {
|
|
22
|
+
/** Content to reveal */
|
|
8
23
|
children: React.ReactNode
|
|
9
|
-
|
|
24
|
+
/** Animation direction */
|
|
25
|
+
direction?: "up" | "down" | "left" | "right" | "fade" | "scale" | "blur"
|
|
26
|
+
/** Animation delay in seconds */
|
|
10
27
|
delay?: number
|
|
28
|
+
/** Animation duration in seconds */
|
|
11
29
|
duration?: number
|
|
30
|
+
/** Distance to animate from (pixels) */
|
|
12
31
|
distance?: number
|
|
32
|
+
/** Viewport threshold for trigger (0-1) */
|
|
13
33
|
threshold?: number
|
|
34
|
+
/** Trigger animation only once */
|
|
35
|
+
once?: boolean
|
|
36
|
+
/** Deprecated: Use 'once' instead */
|
|
14
37
|
triggerOnce?: boolean
|
|
38
|
+
/** Stagger delay for multiple children (deprecated: use ScrollRevealContainer) */
|
|
15
39
|
stagger?: number
|
|
40
|
+
/** Additional CSS classes */
|
|
16
41
|
className?: string
|
|
42
|
+
/** Custom animation variants */
|
|
17
43
|
variants?: Variants
|
|
44
|
+
/** Enable/disable animations */
|
|
18
45
|
animate?: boolean
|
|
46
|
+
/** Custom styles */
|
|
19
47
|
style?: React.CSSProperties
|
|
48
|
+
/** Element ID */
|
|
20
49
|
id?: string
|
|
50
|
+
/** Viewport options for intersection observer */
|
|
51
|
+
viewport?: UseInViewOptions
|
|
21
52
|
}
|
|
22
53
|
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
54
|
+
// Default animation variants with professional easing
|
|
55
|
+
const createDefaultVariants = (direction: string, distance: number): Variants => {
|
|
56
|
+
const baseVariants: Record<string, Variants> = {
|
|
57
|
+
up: {
|
|
58
|
+
hidden: { opacity: 0, y: distance },
|
|
59
|
+
visible: { opacity: 1, y: 0 }
|
|
60
|
+
},
|
|
61
|
+
down: {
|
|
62
|
+
hidden: { opacity: 0, y: -distance },
|
|
63
|
+
visible: { opacity: 1, y: 0 }
|
|
64
|
+
},
|
|
65
|
+
left: {
|
|
66
|
+
hidden: { opacity: 0, x: distance },
|
|
67
|
+
visible: { opacity: 1, x: 0 }
|
|
68
|
+
},
|
|
69
|
+
right: {
|
|
70
|
+
hidden: { opacity: 0, x: -distance },
|
|
71
|
+
visible: { opacity: 1, x: 0 }
|
|
72
|
+
},
|
|
73
|
+
fade: {
|
|
74
|
+
hidden: { opacity: 0 },
|
|
75
|
+
visible: { opacity: 1 }
|
|
76
|
+
},
|
|
77
|
+
scale: {
|
|
78
|
+
hidden: { opacity: 0, scale: 0.85 },
|
|
79
|
+
visible: { opacity: 1, scale: 1 }
|
|
80
|
+
},
|
|
81
|
+
blur: {
|
|
82
|
+
hidden: { opacity: 0, filter: "blur(10px)" },
|
|
83
|
+
visible: { opacity: 1, filter: "blur(0px)" }
|
|
84
|
+
}
|
|
51
85
|
}
|
|
86
|
+
|
|
87
|
+
return baseVariants[direction] || baseVariants.up
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
// Professional easing curve
|
|
91
|
+
const defaultTransition: Transition = {
|
|
92
|
+
duration: 0.5,
|
|
93
|
+
ease: [0.25, 0.46, 0.45, 0.94], // Custom cubic-bezier for smooth motion
|
|
52
94
|
}
|
|
53
95
|
|
|
54
96
|
const ScrollReveal = React.forwardRef<HTMLDivElement, ScrollRevealProps>(
|
|
@@ -56,58 +98,47 @@ const ScrollReveal = React.forwardRef<HTMLDivElement, ScrollRevealProps>(
|
|
|
56
98
|
children,
|
|
57
99
|
direction = "up",
|
|
58
100
|
delay = 0,
|
|
59
|
-
duration = 0.
|
|
101
|
+
duration = 0.5,
|
|
60
102
|
distance = 50,
|
|
61
|
-
threshold = 0.1
|
|
62
|
-
|
|
103
|
+
threshold = 0.3, // Increased from 0.1 for better visibility
|
|
104
|
+
once = true,
|
|
105
|
+
triggerOnce, // Backward compatibility
|
|
63
106
|
stagger = 0,
|
|
64
107
|
className,
|
|
65
108
|
variants,
|
|
66
109
|
animate = true,
|
|
67
110
|
style,
|
|
68
|
-
id
|
|
111
|
+
id,
|
|
112
|
+
viewport
|
|
69
113
|
}, ref) => {
|
|
70
|
-
|
|
71
|
-
const
|
|
72
|
-
const isInView = useInView(elementRef, {
|
|
73
|
-
amount: threshold,
|
|
74
|
-
once: triggerOnce
|
|
75
|
-
})
|
|
114
|
+
// Handle backward compatibility
|
|
115
|
+
const shouldTriggerOnce = triggerOnce !== undefined ? triggerOnce : once
|
|
76
116
|
|
|
77
|
-
//
|
|
78
|
-
const
|
|
117
|
+
// Get animation variants
|
|
118
|
+
const animationVariants = React.useMemo(() => {
|
|
79
119
|
if (variants) return variants
|
|
80
|
-
|
|
81
|
-
const baseVariants = defaultVariants[direction] || defaultVariants.up
|
|
82
|
-
|
|
83
|
-
return {
|
|
84
|
-
hidden: {
|
|
85
|
-
...baseVariants.hidden,
|
|
86
|
-
...(direction === "up" && { y: distance }),
|
|
87
|
-
...(direction === "down" && { y: -distance }),
|
|
88
|
-
...(direction === "left" && { x: distance }),
|
|
89
|
-
...(direction === "right" && { x: -distance })
|
|
90
|
-
},
|
|
91
|
-
visible: baseVariants.visible
|
|
92
|
-
}
|
|
120
|
+
return createDefaultVariants(direction, distance)
|
|
93
121
|
}, [direction, distance, variants])
|
|
94
122
|
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
controls.start("hidden")
|
|
102
|
-
}
|
|
103
|
-
}, [isInView, controls, triggerOnce, animate])
|
|
123
|
+
// Transition configuration
|
|
124
|
+
const transition = React.useMemo<Transition>(() => ({
|
|
125
|
+
...defaultTransition,
|
|
126
|
+
duration,
|
|
127
|
+
delay: delay + stagger,
|
|
128
|
+
}), [duration, delay, stagger])
|
|
104
129
|
|
|
105
|
-
|
|
130
|
+
// Viewport configuration
|
|
131
|
+
const viewportConfig = React.useMemo<UseInViewOptions>(() => ({
|
|
132
|
+
once: shouldTriggerOnce,
|
|
133
|
+
amount: threshold,
|
|
134
|
+
...viewport
|
|
135
|
+
}), [shouldTriggerOnce, threshold, viewport])
|
|
106
136
|
|
|
137
|
+
// If animations are disabled, render children in a regular div
|
|
107
138
|
if (!animate) {
|
|
108
139
|
return (
|
|
109
140
|
<div
|
|
110
|
-
ref={
|
|
141
|
+
ref={ref}
|
|
111
142
|
className={className}
|
|
112
143
|
style={style}
|
|
113
144
|
id={id}
|
|
@@ -117,17 +148,15 @@ const ScrollReveal = React.forwardRef<HTMLDivElement, ScrollRevealProps>(
|
|
|
117
148
|
)
|
|
118
149
|
}
|
|
119
150
|
|
|
151
|
+
// Render with Framer Motion using whileInView pattern
|
|
120
152
|
return (
|
|
121
153
|
<motion.div
|
|
122
|
-
ref={
|
|
123
|
-
variants={customVariants}
|
|
154
|
+
ref={ref}
|
|
124
155
|
initial="hidden"
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
ease: "easeOut"
|
|
130
|
-
}}
|
|
156
|
+
whileInView="visible"
|
|
157
|
+
viewport={viewportConfig}
|
|
158
|
+
variants={animationVariants}
|
|
159
|
+
transition={transition}
|
|
131
160
|
className={cn(className)}
|
|
132
161
|
style={style}
|
|
133
162
|
id={id}
|
|
@@ -140,35 +169,82 @@ const ScrollReveal = React.forwardRef<HTMLDivElement, ScrollRevealProps>(
|
|
|
140
169
|
|
|
141
170
|
ScrollReveal.displayName = "ScrollReveal"
|
|
142
171
|
|
|
143
|
-
|
|
172
|
+
/**
|
|
173
|
+
* ScrollRevealContainer Component
|
|
174
|
+
*
|
|
175
|
+
* Container for orchestrating staggered scroll reveal animations
|
|
176
|
+
* Uses Framer Motion's staggerChildren for better performance
|
|
177
|
+
*
|
|
178
|
+
* @example
|
|
179
|
+
* ```tsx
|
|
180
|
+
* <ScrollRevealContainer stagger={0.1}>
|
|
181
|
+
* <ScrollRevealItem>Item 1</ScrollRevealItem>
|
|
182
|
+
* <ScrollRevealItem>Item 2</ScrollRevealItem>
|
|
183
|
+
* </ScrollRevealContainer>
|
|
184
|
+
* ```
|
|
185
|
+
*/
|
|
186
|
+
|
|
144
187
|
interface ScrollRevealContainerProps {
|
|
188
|
+
/** ScrollRevealItem components */
|
|
145
189
|
children: React.ReactNode
|
|
190
|
+
/** Delay between child animations (seconds) */
|
|
146
191
|
stagger?: number
|
|
192
|
+
/** Additional CSS classes */
|
|
147
193
|
className?: string
|
|
194
|
+
/** Custom styles */
|
|
148
195
|
style?: React.CSSProperties
|
|
196
|
+
/** Element ID */
|
|
149
197
|
id?: string
|
|
198
|
+
/** Viewport threshold for trigger (0-1) */
|
|
199
|
+
threshold?: number
|
|
200
|
+
/** Trigger animation only once */
|
|
201
|
+
once?: boolean
|
|
202
|
+
/** Deprecated: Use 'once' instead */
|
|
203
|
+
triggerOnce?: boolean
|
|
204
|
+
/** Viewport options for intersection observer */
|
|
205
|
+
viewport?: UseInViewOptions
|
|
150
206
|
}
|
|
151
207
|
|
|
152
208
|
const ScrollRevealContainer = React.forwardRef<HTMLDivElement, ScrollRevealContainerProps>(
|
|
153
|
-
({
|
|
154
|
-
|
|
155
|
-
|
|
209
|
+
({
|
|
210
|
+
children,
|
|
211
|
+
stagger = 0.1,
|
|
212
|
+
className,
|
|
213
|
+
style,
|
|
214
|
+
id,
|
|
215
|
+
threshold = 0.3,
|
|
216
|
+
once = true,
|
|
217
|
+
triggerOnce,
|
|
218
|
+
viewport
|
|
219
|
+
}, ref) => {
|
|
220
|
+
// Handle backward compatibility
|
|
221
|
+
const shouldTriggerOnce = triggerOnce !== undefined ? triggerOnce : once
|
|
156
222
|
|
|
157
|
-
|
|
223
|
+
// Viewport configuration
|
|
224
|
+
const viewportConfig = React.useMemo<UseInViewOptions>(() => ({
|
|
225
|
+
once: shouldTriggerOnce,
|
|
226
|
+
amount: threshold,
|
|
227
|
+
...viewport
|
|
228
|
+
}), [shouldTriggerOnce, threshold, viewport])
|
|
229
|
+
|
|
230
|
+
// Container variants for staggered children
|
|
231
|
+
const containerVariants: Variants = {
|
|
232
|
+
hidden: {},
|
|
233
|
+
visible: {
|
|
234
|
+
transition: {
|
|
235
|
+
staggerChildren: stagger,
|
|
236
|
+
delayChildren: 0
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
}
|
|
158
240
|
|
|
159
241
|
return (
|
|
160
242
|
<motion.div
|
|
161
|
-
ref={
|
|
243
|
+
ref={ref}
|
|
162
244
|
initial="hidden"
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
visible: {
|
|
167
|
-
transition: {
|
|
168
|
-
staggerChildren: stagger
|
|
169
|
-
}
|
|
170
|
-
}
|
|
171
|
-
}}
|
|
245
|
+
whileInView="visible"
|
|
246
|
+
viewport={viewportConfig}
|
|
247
|
+
variants={containerVariants}
|
|
172
248
|
className={cn(className)}
|
|
173
249
|
style={style}
|
|
174
250
|
id={id}
|
|
@@ -181,15 +257,36 @@ const ScrollRevealContainer = React.forwardRef<HTMLDivElement, ScrollRevealConta
|
|
|
181
257
|
|
|
182
258
|
ScrollRevealContainer.displayName = "ScrollRevealContainer"
|
|
183
259
|
|
|
184
|
-
|
|
260
|
+
/**
|
|
261
|
+
* ScrollRevealItem Component
|
|
262
|
+
*
|
|
263
|
+
* Individual item within a ScrollRevealContainer
|
|
264
|
+
* Automatically inherits timing from parent container
|
|
265
|
+
*
|
|
266
|
+
* @example
|
|
267
|
+
* ```tsx
|
|
268
|
+
* <ScrollRevealItem direction="up">
|
|
269
|
+
* <Card>Item content</Card>
|
|
270
|
+
* </ScrollRevealItem>
|
|
271
|
+
* ```
|
|
272
|
+
*/
|
|
273
|
+
|
|
185
274
|
interface ScrollRevealItemProps {
|
|
275
|
+
/** Content to animate */
|
|
186
276
|
children: React.ReactNode
|
|
187
|
-
|
|
277
|
+
/** Animation direction */
|
|
278
|
+
direction?: "up" | "down" | "left" | "right" | "fade" | "scale" | "blur"
|
|
279
|
+
/** Animation duration in seconds */
|
|
188
280
|
duration?: number
|
|
281
|
+
/** Distance to animate from (pixels) */
|
|
189
282
|
distance?: number
|
|
283
|
+
/** Additional CSS classes */
|
|
190
284
|
className?: string
|
|
285
|
+
/** Custom animation variants */
|
|
191
286
|
variants?: Variants
|
|
287
|
+
/** Custom styles */
|
|
192
288
|
style?: React.CSSProperties
|
|
289
|
+
/** Element ID */
|
|
193
290
|
id?: string
|
|
194
291
|
}
|
|
195
292
|
|
|
@@ -197,38 +294,30 @@ const ScrollRevealItem = React.forwardRef<HTMLDivElement, ScrollRevealItemProps>
|
|
|
197
294
|
({
|
|
198
295
|
children,
|
|
199
296
|
direction = "up",
|
|
200
|
-
duration = 0.
|
|
297
|
+
duration = 0.5,
|
|
201
298
|
distance = 50,
|
|
202
299
|
className,
|
|
203
300
|
variants,
|
|
204
301
|
style,
|
|
205
302
|
id
|
|
206
303
|
}, ref) => {
|
|
207
|
-
|
|
304
|
+
// Get animation variants
|
|
305
|
+
const animationVariants = React.useMemo(() => {
|
|
208
306
|
if (variants) return variants
|
|
209
|
-
|
|
210
|
-
const baseVariants = defaultVariants[direction] || defaultVariants.up
|
|
211
|
-
|
|
212
|
-
return {
|
|
213
|
-
hidden: {
|
|
214
|
-
...baseVariants.hidden,
|
|
215
|
-
...(direction === "up" && { y: distance }),
|
|
216
|
-
...(direction === "down" && { y: -distance }),
|
|
217
|
-
...(direction === "left" && { x: distance }),
|
|
218
|
-
...(direction === "right" && { x: -distance })
|
|
219
|
-
},
|
|
220
|
-
visible: baseVariants.visible
|
|
221
|
-
}
|
|
307
|
+
return createDefaultVariants(direction, distance)
|
|
222
308
|
}, [direction, distance, variants])
|
|
223
309
|
|
|
310
|
+
// Transition configuration
|
|
311
|
+
const transition = React.useMemo<Transition>(() => ({
|
|
312
|
+
...defaultTransition,
|
|
313
|
+
duration,
|
|
314
|
+
}), [duration])
|
|
315
|
+
|
|
224
316
|
return (
|
|
225
317
|
<motion.div
|
|
226
318
|
ref={ref}
|
|
227
|
-
variants={
|
|
228
|
-
transition={
|
|
229
|
-
duration,
|
|
230
|
-
ease: "easeOut"
|
|
231
|
-
}}
|
|
319
|
+
variants={animationVariants}
|
|
320
|
+
transition={transition}
|
|
232
321
|
className={cn(className)}
|
|
233
322
|
style={style}
|
|
234
323
|
id={id}
|
|
@@ -242,4 +331,4 @@ const ScrollRevealItem = React.forwardRef<HTMLDivElement, ScrollRevealItemProps>
|
|
|
242
331
|
ScrollRevealItem.displayName = "ScrollRevealItem"
|
|
243
332
|
|
|
244
333
|
export { ScrollReveal, ScrollRevealContainer, ScrollRevealItem }
|
|
245
|
-
export type { ScrollRevealProps, ScrollRevealContainerProps, ScrollRevealItemProps }
|
|
334
|
+
export type { ScrollRevealProps, ScrollRevealContainerProps, ScrollRevealItemProps }
|
|
@@ -74,7 +74,7 @@ const TagsInput = React.forwardRef<HTMLInputElement, TagsInputProps>(
|
|
|
74
74
|
<div className="relative">
|
|
75
75
|
<div
|
|
76
76
|
className={cn(
|
|
77
|
-
"flex min-h-[2.5rem] w-full flex-wrap gap-2 rounded-md border border-input bg-background px-3 py-2 text-sm ring-offset-background",
|
|
77
|
+
"flex items-center min-h-[2.5rem] w-full flex-wrap gap-2 rounded-md border border-input bg-background px-3 py-2 text-sm ring-offset-background",
|
|
78
78
|
"dark:bg-zinc-950/50 dark:border-zinc-800",
|
|
79
79
|
"focus-within:outline-none focus-within:ring-2 focus-within:ring-ring focus-within:ring-offset-2",
|
|
80
80
|
disabled && "cursor-not-allowed opacity-50",
|