@moontra/moonui 2.0.8 → 2.0.9
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/package.json +9 -2
- package/src/__tests__/use-intersection-observer.test.tsx +216 -0
- package/src/__tests__/use-local-storage.test.tsx +174 -0
- package/src/__tests__/use-pro-access.test.tsx +183 -0
- package/src/components/ui/__tests__/accordion.test.tsx +571 -0
- package/src/components/ui/__tests__/alert.test.tsx +484 -0
- package/src/components/ui/__tests__/aspect-ratio.test.tsx +492 -0
- package/src/components/ui/__tests__/avatar.test.tsx +382 -0
- package/src/components/ui/__tests__/badge.test.tsx +364 -0
- package/src/components/ui/__tests__/breadcrumb.test.tsx +687 -0
- package/src/components/ui/__tests__/button.test.tsx +91 -0
- package/src/components/ui/__tests__/card.test.tsx +104 -0
- package/src/components/ui/__tests__/checkbox.test.tsx +591 -0
- package/src/components/ui/__tests__/collapsible.test.tsx +592 -0
- package/src/components/ui/__tests__/color-picker.test.tsx +365 -0
- package/src/components/ui/__tests__/command.test.tsx +677 -0
- package/src/components/ui/__tests__/data-table.test.tsx +256 -0
- package/src/components/ui/__tests__/date-picker.test.tsx +320 -0
- package/src/components/ui/__tests__/dialog.test.tsx +764 -0
- package/src/components/ui/__tests__/input.test.tsx +318 -0
- package/src/components/ui/__tests__/label.test.tsx +103 -0
- package/src/components/ui/__tests__/popover.test.tsx +637 -0
- package/src/components/ui/__tests__/progress.test.tsx +382 -0
- package/src/components/ui/__tests__/radio-group.test.tsx +555 -0
- package/src/components/ui/__tests__/select.test.tsx +705 -0
- package/src/components/ui/__tests__/skeleton.test.tsx +253 -0
- package/src/components/ui/__tests__/slider.test.tsx +493 -0
- package/src/components/ui/__tests__/switch.test.tsx +372 -0
- package/src/components/ui/__tests__/table.test.tsx +824 -0
- package/src/components/ui/__tests__/tabs.test.tsx +887 -0
- package/src/components/ui/__tests__/toast.test.tsx +458 -0
- package/src/components/ui/__tests__/tooltip.test.tsx +583 -0
- package/src/components/ui/accordion.tsx +63 -0
- package/src/components/ui/alert.tsx +130 -0
- package/src/components/ui/aspect-ratio.tsx +72 -0
- package/src/components/ui/avatar.tsx +135 -0
- package/src/components/ui/badge.tsx +225 -0
- package/src/components/ui/breadcrumb.tsx +207 -0
- package/src/components/ui/button.stories.tsx +162 -0
- package/src/components/ui/button.tsx +221 -0
- package/src/components/ui/calendar.tsx +262 -0
- package/src/components/ui/card.stories.tsx +208 -0
- package/src/components/ui/card.tsx +141 -0
- package/src/components/ui/checkbox.tsx +256 -0
- package/src/components/ui/collapsible.tsx +129 -0
- package/src/components/ui/color-picker.tsx +664 -0
- package/src/components/ui/command.tsx +218 -0
- package/src/components/ui/data-table.stories.tsx +509 -0
- package/src/components/ui/data-table.tsx +623 -0
- package/src/components/ui/date-picker.stories.tsx +321 -0
- package/src/components/ui/date-picker.tsx +603 -0
- package/src/components/ui/dialog.tsx +332 -0
- package/src/components/ui/dropdown-menu.tsx +200 -0
- package/src/components/ui/file-upload.tsx +400 -0
- package/src/components/ui/github-stars.tsx +201 -0
- package/src/components/ui/index.ts +12 -0
- package/src/components/ui/input.stories.tsx +255 -0
- package/src/components/ui/input.tsx +219 -0
- package/src/components/ui/label.tsx +26 -0
- package/src/components/ui/locked-component.tsx +215 -0
- package/src/components/ui/moon-logo.tsx +97 -0
- package/src/components/ui/pagination.tsx +116 -0
- package/src/components/ui/popover.tsx +183 -0
- package/src/components/ui/progress.tsx +182 -0
- package/src/components/ui/radio-group.tsx +243 -0
- package/src/components/ui/select.tsx +273 -0
- package/src/components/ui/separator.tsx +140 -0
- package/src/components/ui/simple-editor.tsx +652 -0
- package/src/components/ui/skeleton.tsx +351 -0
- package/src/components/ui/slider.tsx +351 -0
- package/src/components/ui/switch.tsx +83 -0
- package/src/components/ui/table.tsx +322 -0
- package/src/components/ui/tabs.tsx +195 -0
- package/src/components/ui/textarea.tsx +46 -0
- package/src/components/ui/toast.tsx +313 -0
- package/src/components/ui/toggle.tsx +47 -0
- package/src/components/ui/tooltip.tsx +152 -0
- package/src/docs/theme-system.md +1194 -0
- package/src/index.tsx +39 -0
- package/src/lib/micro-interactions.ts +255 -0
- package/src/lib/theme.tsx +398 -0
- package/src/lib/utils.ts +69 -0
- package/src/styles/design-system.css +365 -0
- package/src/styles/index.css +4 -0
- package/src/styles/tailwind.css +6 -0
- package/src/styles/tokens.css +453 -0
- package/src/use-intersection-observer.tsx +154 -0
- package/src/use-local-storage.tsx +71 -0
- package/src/use-paddle.ts +138 -0
- package/src/use-performance-optimizer.ts +379 -0
- package/src/use-pro-access.ts +141 -0
- package/src/use-scroll-animation.ts +221 -0
- package/src/use-subscription.ts +37 -0
- package/src/use-toast.ts +32 -0
|
@@ -0,0 +1,221 @@
|
|
|
1
|
+
'use client'
|
|
2
|
+
|
|
3
|
+
import { useEffect, useRef, useState } from 'react'
|
|
4
|
+
import { useInView, useScroll, useTransform } from 'framer-motion'
|
|
5
|
+
|
|
6
|
+
interface UseScrollAnimationOptions {
|
|
7
|
+
threshold?: number
|
|
8
|
+
triggerOnce?: boolean
|
|
9
|
+
rootMargin?: string
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export function useScrollAnimation(options: UseScrollAnimationOptions = {}) {
|
|
13
|
+
const ref = useRef<HTMLElement>(null)
|
|
14
|
+
const isInView = useInView(ref, {
|
|
15
|
+
threshold: options.threshold || 0.1,
|
|
16
|
+
once: options.triggerOnce ?? true,
|
|
17
|
+
margin: options.rootMargin || '-100px',
|
|
18
|
+
})
|
|
19
|
+
|
|
20
|
+
return { ref, isInView }
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export function useScrollProgress() {
|
|
24
|
+
const { scrollYProgress } = useScroll()
|
|
25
|
+
return scrollYProgress
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export function useScrollBasedAnimation() {
|
|
29
|
+
const { scrollY } = useScroll()
|
|
30
|
+
const y = useTransform(scrollY, [0, 300], [0, -50])
|
|
31
|
+
const opacity = useTransform(scrollY, [0, 300], [1, 0])
|
|
32
|
+
const scale = useTransform(scrollY, [0, 300], [1, 0.8])
|
|
33
|
+
|
|
34
|
+
return { y, opacity, scale, scrollY }
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
export function useParallaxScroll(speed: number = 0.5) {
|
|
38
|
+
const ref = useRef<HTMLElement>(null)
|
|
39
|
+
const { scrollYProgress } = useScroll({
|
|
40
|
+
target: ref,
|
|
41
|
+
offset: ['start end', 'end start']
|
|
42
|
+
})
|
|
43
|
+
|
|
44
|
+
const y = useTransform(scrollYProgress, [0, 1], [`-${speed * 100}%`, `${speed * 100}%`])
|
|
45
|
+
|
|
46
|
+
return { ref, y }
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
export function useScrollDirection() {
|
|
50
|
+
const [scrollDirection, setScrollDirection] = useState<'up' | 'down'>('down')
|
|
51
|
+
const [scrollY, setScrollY] = useState(0)
|
|
52
|
+
|
|
53
|
+
useEffect(() => {
|
|
54
|
+
let ticking = false
|
|
55
|
+
|
|
56
|
+
const updateScrollDirection = () => {
|
|
57
|
+
const newScrollY = window.scrollY
|
|
58
|
+
|
|
59
|
+
if (Math.abs(newScrollY - scrollY) < 5) {
|
|
60
|
+
ticking = false
|
|
61
|
+
return
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
setScrollDirection(newScrollY > scrollY ? 'down' : 'up')
|
|
65
|
+
setScrollY(newScrollY)
|
|
66
|
+
ticking = false
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
const handleScroll = () => {
|
|
70
|
+
if (!ticking) {
|
|
71
|
+
requestAnimationFrame(updateScrollDirection)
|
|
72
|
+
ticking = true
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
window.addEventListener('scroll', handleScroll)
|
|
77
|
+
return () => window.removeEventListener('scroll', handleScroll)
|
|
78
|
+
}, [scrollY])
|
|
79
|
+
|
|
80
|
+
return { scrollDirection, scrollY }
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
export function useScrollToElement() {
|
|
84
|
+
const scrollToElement = (elementId: string, offset: number = 0) => {
|
|
85
|
+
const element = document.getElementById(elementId)
|
|
86
|
+
if (element) {
|
|
87
|
+
const elementPosition = element.offsetTop - offset
|
|
88
|
+
window.scrollTo({
|
|
89
|
+
top: elementPosition,
|
|
90
|
+
behavior: 'smooth'
|
|
91
|
+
})
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
return { scrollToElement }
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
interface UseInfiniteScrollOptions {
|
|
99
|
+
threshold?: number
|
|
100
|
+
rootMargin?: string
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
export function useInfiniteScroll(
|
|
104
|
+
callback: () => void,
|
|
105
|
+
options: UseInfiniteScrollOptions = {}
|
|
106
|
+
) {
|
|
107
|
+
const ref = useRef<HTMLElement>(null)
|
|
108
|
+
const isInView = useInView(ref, {
|
|
109
|
+
threshold: options.threshold || 0.1,
|
|
110
|
+
margin: options.rootMargin || '100px',
|
|
111
|
+
})
|
|
112
|
+
|
|
113
|
+
useEffect(() => {
|
|
114
|
+
if (isInView) {
|
|
115
|
+
callback()
|
|
116
|
+
}
|
|
117
|
+
}, [isInView, callback])
|
|
118
|
+
|
|
119
|
+
return ref
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
export function useScrollBasedScale() {
|
|
123
|
+
const ref = useRef<HTMLElement>(null)
|
|
124
|
+
const { scrollYProgress } = useScroll({
|
|
125
|
+
target: ref,
|
|
126
|
+
offset: ['start end', 'end start']
|
|
127
|
+
})
|
|
128
|
+
|
|
129
|
+
const scale = useTransform(scrollYProgress, [0, 0.5, 1], [0.8, 1, 0.8])
|
|
130
|
+
const opacity = useTransform(scrollYProgress, [0, 0.2, 0.8, 1], [0, 1, 1, 0])
|
|
131
|
+
|
|
132
|
+
return { ref, scale, opacity }
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
export function useScrollBasedRotation() {
|
|
136
|
+
const ref = useRef<HTMLElement>(null)
|
|
137
|
+
const { scrollYProgress } = useScroll({
|
|
138
|
+
target: ref,
|
|
139
|
+
offset: ['start end', 'end start']
|
|
140
|
+
})
|
|
141
|
+
|
|
142
|
+
const rotate = useTransform(scrollYProgress, [0, 1], [0, 360])
|
|
143
|
+
|
|
144
|
+
return { ref, rotate }
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
export function useScrollTriggeredCounter(
|
|
148
|
+
endValue: number,
|
|
149
|
+
duration: number = 2000
|
|
150
|
+
) {
|
|
151
|
+
const [count, setCount] = useState(0)
|
|
152
|
+
const [isVisible, setIsVisible] = useState(false)
|
|
153
|
+
const ref = useRef<HTMLElement>(null)
|
|
154
|
+
|
|
155
|
+
const isInView = useInView(ref, {
|
|
156
|
+
threshold: 0.5,
|
|
157
|
+
once: true
|
|
158
|
+
})
|
|
159
|
+
|
|
160
|
+
useEffect(() => {
|
|
161
|
+
if (isInView && !isVisible) {
|
|
162
|
+
setIsVisible(true)
|
|
163
|
+
let startTime: number
|
|
164
|
+
|
|
165
|
+
const animate = (currentTime: number) => {
|
|
166
|
+
if (!startTime) startTime = currentTime
|
|
167
|
+
const elapsed = currentTime - startTime
|
|
168
|
+
const progress = Math.min(elapsed / duration, 1)
|
|
169
|
+
|
|
170
|
+
// Easing function for smooth animation
|
|
171
|
+
const easeOutQuart = 1 - Math.pow(1 - progress, 4)
|
|
172
|
+
setCount(Math.floor(easeOutQuart * endValue))
|
|
173
|
+
|
|
174
|
+
if (progress < 1) {
|
|
175
|
+
requestAnimationFrame(animate)
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
requestAnimationFrame(animate)
|
|
180
|
+
}
|
|
181
|
+
}, [isInView, endValue, duration, isVisible])
|
|
182
|
+
|
|
183
|
+
return { ref, count }
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
export function useScrollBasedBlur() {
|
|
187
|
+
const { scrollY } = useScroll()
|
|
188
|
+
const blur = useTransform(scrollY, [0, 300], [0, 10])
|
|
189
|
+
|
|
190
|
+
return blur
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
export function useScrollSnapPoints(snapPoints: number[]) {
|
|
194
|
+
const [currentSnap, setCurrentSnap] = useState(0)
|
|
195
|
+
|
|
196
|
+
useEffect(() => {
|
|
197
|
+
const handleScroll = () => {
|
|
198
|
+
const scrollPosition = window.scrollY
|
|
199
|
+
const closest = snapPoints.reduce((prev, curr, index) => {
|
|
200
|
+
return Math.abs(curr - scrollPosition) < Math.abs(snapPoints[prev] - scrollPosition)
|
|
201
|
+
? index
|
|
202
|
+
: prev
|
|
203
|
+
}, 0)
|
|
204
|
+
setCurrentSnap(closest)
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
window.addEventListener('scroll', handleScroll)
|
|
208
|
+
return () => window.removeEventListener('scroll', handleScroll)
|
|
209
|
+
}, [snapPoints])
|
|
210
|
+
|
|
211
|
+
const scrollToSnap = (index: number) => {
|
|
212
|
+
if (index >= 0 && index < snapPoints.length) {
|
|
213
|
+
window.scrollTo({
|
|
214
|
+
top: snapPoints[index],
|
|
215
|
+
behavior: 'smooth'
|
|
216
|
+
})
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
return { currentSnap, scrollToSnap }
|
|
221
|
+
}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { useSession } from "next-auth/react";
|
|
2
|
+
|
|
3
|
+
export function useSubscription() {
|
|
4
|
+
const { data: session, status } = useSession();
|
|
5
|
+
|
|
6
|
+
const isLoading = status === "loading";
|
|
7
|
+
const isAuthenticated = status === "authenticated";
|
|
8
|
+
|
|
9
|
+
// Admin kullanıcılar her zaman pro erişime sahip
|
|
10
|
+
const isAdmin = session?.user?.role === "admin";
|
|
11
|
+
|
|
12
|
+
// Pro abonelik kontrolü
|
|
13
|
+
const hasProAccess = isAdmin || session?.user?.subscription?.status === "active";
|
|
14
|
+
const subscriptionPlan = session?.user?.subscription?.plan || (isAdmin ? "lifetime" : "free");
|
|
15
|
+
|
|
16
|
+
// Debug bilgisi
|
|
17
|
+
if (process.env.NODE_ENV === 'development') {
|
|
18
|
+
console.log('🔍 useSubscription Debug:', {
|
|
19
|
+
email: session?.user?.email,
|
|
20
|
+
role: session?.user?.role,
|
|
21
|
+
isAdmin,
|
|
22
|
+
subscription: session?.user?.subscription,
|
|
23
|
+
hasProAccess,
|
|
24
|
+
subscriptionPlan,
|
|
25
|
+
status
|
|
26
|
+
});
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
return {
|
|
30
|
+
isLoading,
|
|
31
|
+
isAuthenticated,
|
|
32
|
+
isAdmin,
|
|
33
|
+
hasProAccess,
|
|
34
|
+
subscriptionPlan,
|
|
35
|
+
subscription: session?.user?.subscription,
|
|
36
|
+
};
|
|
37
|
+
}
|
package/src/use-toast.ts
ADDED
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
// Toast hook - şimdilik basit bir implementasyon
|
|
2
|
+
// Gerçek implementasyonda Toaster component'i ile entegre olacak
|
|
3
|
+
|
|
4
|
+
interface ToastOptions {
|
|
5
|
+
title: string;
|
|
6
|
+
description?: string;
|
|
7
|
+
variant?: 'default' | 'destructive';
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export function toast(options: ToastOptions) {
|
|
11
|
+
// Şimdilik console'a yazdıralım
|
|
12
|
+
// Gerçek implementasyonda toast notification gösterilecek
|
|
13
|
+
console.log('Toast:', options);
|
|
14
|
+
|
|
15
|
+
// Browser'da alert gösterelim (geçici çözüm)
|
|
16
|
+
if (typeof window !== 'undefined') {
|
|
17
|
+
const message = options.description
|
|
18
|
+
? `${options.title}\n\n${options.description}`
|
|
19
|
+
: options.title;
|
|
20
|
+
|
|
21
|
+
// Variant'a göre stil belirle
|
|
22
|
+
if (options.variant === 'destructive') {
|
|
23
|
+
console.error(message);
|
|
24
|
+
} else {
|
|
25
|
+
console.log(message);
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
export const useToast = () => {
|
|
31
|
+
return { toast };
|
|
32
|
+
};
|