@moontra/moonui-pro 2.18.1 → 2.18.2
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/dist/index.mjs +447 -433
- package/package.json +1 -1
- package/src/components/github-stars/hooks.ts +19 -6
- package/src/components/github-stars/index.tsx +65 -57
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@moontra/moonui-pro",
|
|
3
|
-
"version": "2.18.
|
|
3
|
+
"version": "2.18.2",
|
|
4
4
|
"description": "Premium React components for MoonUI - Advanced UI library with 50+ pro components including performance, interactive, and gesture components",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.mjs",
|
|
@@ -57,16 +57,29 @@ export function useGitHubData({
|
|
|
57
57
|
const errorCountRef = useRef<number>(0) // Hata sayısını takip et
|
|
58
58
|
const maxErrorCount = 2 // Maksimum hata sayısı
|
|
59
59
|
|
|
60
|
+
// checkMilestones fonksiyonunu ref olarak sakla - bu şekilde her render'da yeniden oluşturulmaz
|
|
61
|
+
const milestonesRef = useRef(milestones)
|
|
62
|
+
const onMilestoneReachedRef = useRef(onMilestoneReached)
|
|
63
|
+
|
|
64
|
+
// Ref'leri güncelle
|
|
65
|
+
useEffect(() => {
|
|
66
|
+
milestonesRef.current = milestones
|
|
67
|
+
}, [milestones])
|
|
68
|
+
|
|
69
|
+
useEffect(() => {
|
|
70
|
+
onMilestoneReachedRef.current = onMilestoneReached
|
|
71
|
+
}, [onMilestoneReached])
|
|
72
|
+
|
|
60
73
|
const checkMilestones = useCallback((repos: GitHubRepository[]) => {
|
|
61
|
-
if (!
|
|
74
|
+
if (!onMilestoneReachedRef.current) return
|
|
62
75
|
|
|
63
76
|
repos.forEach(repo => {
|
|
64
77
|
const previousStars = previousStarsRef.current.get(repo.full_name) || 0
|
|
65
78
|
const currentStars = repo.stargazers_count
|
|
66
79
|
|
|
67
|
-
|
|
80
|
+
milestonesRef.current.forEach(milestone => {
|
|
68
81
|
if (previousStars < milestone && currentStars >= milestone) {
|
|
69
|
-
|
|
82
|
+
onMilestoneReachedRef.current?.({
|
|
70
83
|
count: milestone,
|
|
71
84
|
reached: true,
|
|
72
85
|
date: new Date().toISOString(),
|
|
@@ -77,7 +90,7 @@ export function useGitHubData({
|
|
|
77
90
|
|
|
78
91
|
previousStarsRef.current.set(repo.full_name, currentStars)
|
|
79
92
|
})
|
|
80
|
-
}, [
|
|
93
|
+
}, []) // Boş dependency array - fonksiyon asla yeniden oluşturulmaz
|
|
81
94
|
|
|
82
95
|
const fetchData = useCallback(async () => {
|
|
83
96
|
// Hata limiti aşıldıysa istek yapma
|
|
@@ -226,11 +239,11 @@ export function useGitHubData({
|
|
|
226
239
|
}, [
|
|
227
240
|
username,
|
|
228
241
|
repository,
|
|
229
|
-
repositories,
|
|
242
|
+
repositories?.join(','), // Array'i string'e çevir ki referans değişmesin
|
|
230
243
|
token,
|
|
231
244
|
sortBy,
|
|
232
245
|
maxItems,
|
|
233
|
-
checkMilestones,
|
|
246
|
+
checkMilestones, // Artık stable
|
|
234
247
|
onDataUpdate,
|
|
235
248
|
onError,
|
|
236
249
|
])
|
|
@@ -62,6 +62,27 @@ const GitHubStarsInternal: React.FC<GitHubStarsProps> = ({
|
|
|
62
62
|
}) => {
|
|
63
63
|
const { notify } = useGitHubNotifications(enableNotifications)
|
|
64
64
|
|
|
65
|
+
// onMilestoneReached callback'ini memoize et
|
|
66
|
+
const handleMilestoneReached = React.useCallback((milestone: any) => {
|
|
67
|
+
// Handle milestone reached
|
|
68
|
+
if (celebrateAt?.includes(milestone.count)) {
|
|
69
|
+
// Trigger celebration animation
|
|
70
|
+
confetti({
|
|
71
|
+
particleCount: 100,
|
|
72
|
+
spread: 70,
|
|
73
|
+
origin: { y: 0.6 },
|
|
74
|
+
})
|
|
75
|
+
|
|
76
|
+
// Show notification
|
|
77
|
+
notify(`🎉 Milestone Reached!`, {
|
|
78
|
+
body: `${milestone.count} stars achieved!`,
|
|
79
|
+
tag: `milestone-${milestone.count}`,
|
|
80
|
+
})
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
onMilestoneReached?.(milestone)
|
|
84
|
+
}, [celebrateAt, notify, onMilestoneReached])
|
|
85
|
+
|
|
65
86
|
const {
|
|
66
87
|
repos,
|
|
67
88
|
stats,
|
|
@@ -81,29 +102,11 @@ const GitHubStarsInternal: React.FC<GitHubStarsProps> = ({
|
|
|
81
102
|
maxItems,
|
|
82
103
|
onError,
|
|
83
104
|
onDataUpdate,
|
|
84
|
-
onMilestoneReached:
|
|
85
|
-
// Handle milestone reached
|
|
86
|
-
if (celebrateAt?.includes(milestone.count)) {
|
|
87
|
-
// Trigger celebration animation
|
|
88
|
-
confetti({
|
|
89
|
-
particleCount: 100,
|
|
90
|
-
spread: 70,
|
|
91
|
-
origin: { y: 0.6 },
|
|
92
|
-
})
|
|
93
|
-
|
|
94
|
-
// Show notification
|
|
95
|
-
notify(`🎉 Milestone Reached!`, {
|
|
96
|
-
body: `${milestone.count} stars achieved!`,
|
|
97
|
-
tag: `milestone-${milestone.count}`,
|
|
98
|
-
})
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
onMilestoneReached?.(milestone)
|
|
102
|
-
},
|
|
105
|
+
onMilestoneReached: handleMilestoneReached,
|
|
103
106
|
milestones,
|
|
104
107
|
})
|
|
105
108
|
|
|
106
|
-
const handleExport = (format: "json" | "csv") => {
|
|
109
|
+
const handleExport = React.useCallback((format: "json" | "csv") => {
|
|
107
110
|
if (!enableExport) return
|
|
108
111
|
|
|
109
112
|
const timestamp = new Date().toISOString().split("T")[0]
|
|
@@ -116,7 +119,47 @@ const GitHubStarsInternal: React.FC<GitHubStarsProps> = ({
|
|
|
116
119
|
} else {
|
|
117
120
|
exportAsCSV(repos, `github-stars-${username}-${timestamp}.csv`)
|
|
118
121
|
}
|
|
119
|
-
}
|
|
122
|
+
}, [enableExport, repos, stats, username])
|
|
123
|
+
|
|
124
|
+
// handleDetailedExport fonksiyonunu memoize et
|
|
125
|
+
const handleDetailedExport = React.useCallback((e: React.MouseEvent) => {
|
|
126
|
+
if (!enableExport) return
|
|
127
|
+
|
|
128
|
+
// Show export dropdown
|
|
129
|
+
const dropdown = document.createElement("div")
|
|
130
|
+
dropdown.className = "absolute z-50 mt-2 w-48 rounded-md shadow-lg bg-popover border"
|
|
131
|
+
dropdown.innerHTML = `
|
|
132
|
+
<div class="py-1">
|
|
133
|
+
<button class="w-full text-left px-4 py-2 text-sm hover:bg-accent" data-format="json">
|
|
134
|
+
Export as JSON
|
|
135
|
+
</button>
|
|
136
|
+
<button class="w-full text-left px-4 py-2 text-sm hover:bg-accent" data-format="csv">
|
|
137
|
+
Export as CSV
|
|
138
|
+
</button>
|
|
139
|
+
</div>
|
|
140
|
+
`
|
|
141
|
+
|
|
142
|
+
dropdown.addEventListener("click", (e) => {
|
|
143
|
+
const target = e.target as HTMLElement
|
|
144
|
+
const format = target.getAttribute("data-format")
|
|
145
|
+
if (format === "json" || format === "csv") {
|
|
146
|
+
handleExport(format)
|
|
147
|
+
dropdown.remove()
|
|
148
|
+
}
|
|
149
|
+
})
|
|
150
|
+
|
|
151
|
+
document.body.appendChild(dropdown)
|
|
152
|
+
|
|
153
|
+
// Position dropdown
|
|
154
|
+
const rect = (e.target as HTMLElement).getBoundingClientRect()
|
|
155
|
+
dropdown.style.top = `${rect.bottom + window.scrollY}px`
|
|
156
|
+
dropdown.style.left = `${rect.left + window.scrollX}px`
|
|
157
|
+
|
|
158
|
+
// Remove on outside click
|
|
159
|
+
setTimeout(() => {
|
|
160
|
+
document.addEventListener("click", () => dropdown.remove(), { once: true })
|
|
161
|
+
}, 0)
|
|
162
|
+
}, [enableExport, handleExport])
|
|
120
163
|
|
|
121
164
|
// Loading state
|
|
122
165
|
if (loading) {
|
|
@@ -201,42 +244,7 @@ const GitHubStarsInternal: React.FC<GitHubStarsProps> = ({
|
|
|
201
244
|
return (
|
|
202
245
|
<DetailedVariant
|
|
203
246
|
{...baseProps}
|
|
204
|
-
onExport={
|
|
205
|
-
// Show export dropdown
|
|
206
|
-
const dropdown = document.createElement("div")
|
|
207
|
-
dropdown.className = "absolute z-50 mt-2 w-48 rounded-md shadow-lg bg-popover border"
|
|
208
|
-
dropdown.innerHTML = `
|
|
209
|
-
<div class="py-1">
|
|
210
|
-
<button class="w-full text-left px-4 py-2 text-sm hover:bg-accent" data-format="json">
|
|
211
|
-
Export as JSON
|
|
212
|
-
</button>
|
|
213
|
-
<button class="w-full text-left px-4 py-2 text-sm hover:bg-accent" data-format="csv">
|
|
214
|
-
Export as CSV
|
|
215
|
-
</button>
|
|
216
|
-
</div>
|
|
217
|
-
`
|
|
218
|
-
|
|
219
|
-
dropdown.addEventListener("click", (e) => {
|
|
220
|
-
const target = e.target as HTMLElement
|
|
221
|
-
const format = target.getAttribute("data-format")
|
|
222
|
-
if (format === "json" || format === "csv") {
|
|
223
|
-
handleExport(format)
|
|
224
|
-
dropdown.remove()
|
|
225
|
-
}
|
|
226
|
-
})
|
|
227
|
-
|
|
228
|
-
document.body.appendChild(dropdown)
|
|
229
|
-
|
|
230
|
-
// Position dropdown
|
|
231
|
-
const rect = (e.target as HTMLElement).getBoundingClientRect()
|
|
232
|
-
dropdown.style.top = `${rect.bottom + window.scrollY}px`
|
|
233
|
-
dropdown.style.left = `${rect.left + window.scrollX}px`
|
|
234
|
-
|
|
235
|
-
// Remove on outside click
|
|
236
|
-
setTimeout(() => {
|
|
237
|
-
document.addEventListener("click", () => dropdown.remove(), { once: true })
|
|
238
|
-
}, 0)
|
|
239
|
-
}}
|
|
247
|
+
onExport={handleDetailedExport}
|
|
240
248
|
/>
|
|
241
249
|
)
|
|
242
250
|
case "card":
|