@moontra/moonui-pro 2.20.1 → 2.20.3

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.
Files changed (162) hide show
  1. package/dist/index.d.ts +691 -261
  2. package/dist/index.mjs +7418 -4934
  3. package/package.json +11 -5
  4. package/plugin/index.d.ts +86 -0
  5. package/plugin/index.js +308 -0
  6. package/scripts/postbuild.js +27 -0
  7. package/scripts/postinstall.js +176 -23
  8. package/src/__tests__/use-intersection-observer.test.tsx +0 -216
  9. package/src/__tests__/use-local-storage.test.tsx +0 -174
  10. package/src/__tests__/use-pro-access.test.tsx +0 -183
  11. package/src/components/advanced-chart/advanced-chart.test.tsx +0 -281
  12. package/src/components/advanced-chart/index.tsx +0 -1242
  13. package/src/components/advanced-forms/index.tsx +0 -426
  14. package/src/components/animated-button/index.tsx +0 -385
  15. package/src/components/calendar/event-dialog.tsx +0 -372
  16. package/src/components/calendar/index.tsx +0 -1073
  17. package/src/components/calendar-pro/index.tsx +0 -1697
  18. package/src/components/color-picker/index.tsx +0 -432
  19. package/src/components/credit-card-input/index.tsx +0 -406
  20. package/src/components/dashboard/dashboard-grid.tsx +0 -462
  21. package/src/components/dashboard/demo.tsx +0 -425
  22. package/src/components/dashboard/index.tsx +0 -1046
  23. package/src/components/dashboard/time-range-picker.tsx +0 -336
  24. package/src/components/dashboard/types.ts +0 -222
  25. package/src/components/dashboard/widgets/activity-feed.tsx +0 -344
  26. package/src/components/dashboard/widgets/chart-widget.tsx +0 -418
  27. package/src/components/dashboard/widgets/metric-card.tsx +0 -343
  28. package/src/components/data-table/data-table-bulk-actions.tsx +0 -204
  29. package/src/components/data-table/data-table-column-toggle.tsx +0 -169
  30. package/src/components/data-table/data-table-export.ts +0 -156
  31. package/src/components/data-table/data-table-filter-drawer.tsx +0 -448
  32. package/src/components/data-table/data-table.test.tsx +0 -187
  33. package/src/components/data-table/index.tsx +0 -845
  34. package/src/components/draggable-list/index.tsx +0 -100
  35. package/src/components/enhanced/badge.tsx +0 -191
  36. package/src/components/enhanced/button.tsx +0 -362
  37. package/src/components/enhanced/card.tsx +0 -266
  38. package/src/components/enhanced/dialog.tsx +0 -246
  39. package/src/components/enhanced/index.ts +0 -4
  40. package/src/components/error-boundary/index.tsx +0 -109
  41. package/src/components/file-upload/file-upload.test.tsx +0 -243
  42. package/src/components/file-upload/index.tsx +0 -1660
  43. package/src/components/floating-action-button/index.tsx +0 -206
  44. package/src/components/form-wizard/form-wizard-context.tsx +0 -307
  45. package/src/components/form-wizard/form-wizard-navigation.tsx +0 -118
  46. package/src/components/form-wizard/form-wizard-progress.tsx +0 -298
  47. package/src/components/form-wizard/form-wizard-step.tsx +0 -111
  48. package/src/components/form-wizard/index.tsx +0 -102
  49. package/src/components/form-wizard/types.ts +0 -76
  50. package/src/components/gesture-drawer/index.tsx +0 -551
  51. package/src/components/github-stars/github-api.ts +0 -426
  52. package/src/components/github-stars/hooks.ts +0 -516
  53. package/src/components/github-stars/index.tsx +0 -375
  54. package/src/components/github-stars/types.ts +0 -148
  55. package/src/components/github-stars/variants.tsx +0 -513
  56. package/src/components/health-check/index.tsx +0 -439
  57. package/src/components/hover-card-3d/index.tsx +0 -530
  58. package/src/components/index.ts +0 -128
  59. package/src/components/internal/index.ts +0 -78
  60. package/src/components/kanban/add-card-modal.tsx +0 -502
  61. package/src/components/kanban/card-detail-modal.tsx +0 -761
  62. package/src/components/kanban/index.ts +0 -13
  63. package/src/components/kanban/kanban.tsx +0 -1684
  64. package/src/components/kanban/types.ts +0 -168
  65. package/src/components/lazy-component/index.tsx +0 -823
  66. package/src/components/license-error/index.tsx +0 -29
  67. package/src/components/magnetic-button/index.tsx +0 -167
  68. package/src/components/memory-efficient-data/index.tsx +0 -1016
  69. package/src/components/moonui-quiz-form/index.tsx +0 -817
  70. package/src/components/optimized-image/index.tsx +0 -425
  71. package/src/components/performance-debugger/index.tsx +0 -589
  72. package/src/components/performance-monitor/index.tsx +0 -794
  73. package/src/components/phone-number-input/index.tsx +0 -338
  74. package/src/components/pinch-zoom/index.tsx +0 -566
  75. package/src/components/quiz-form/index.tsx +0 -479
  76. package/src/components/rich-text-editor/index-old-backup.tsx +0 -437
  77. package/src/components/rich-text-editor/index.tsx +0 -2324
  78. package/src/components/rich-text-editor/slash-commands-extension.ts +0 -220
  79. package/src/components/rich-text-editor/slash-commands.css +0 -35
  80. package/src/components/rich-text-editor/table-styles.css +0 -65
  81. package/src/components/sidebar/index.tsx +0 -865
  82. package/src/components/spotlight-card/index.tsx +0 -191
  83. package/src/components/swipeable-card/index.tsx +0 -100
  84. package/src/components/timeline/index.tsx +0 -1148
  85. package/src/components/ui/accordion.tsx +0 -73
  86. package/src/components/ui/alert-dialog.tsx +0 -141
  87. package/src/components/ui/alert.tsx +0 -141
  88. package/src/components/ui/aspect-ratio.tsx +0 -245
  89. package/src/components/ui/avatar.tsx +0 -153
  90. package/src/components/ui/badge.tsx +0 -228
  91. package/src/components/ui/breadcrumb.tsx +0 -214
  92. package/src/components/ui/button.tsx +0 -222
  93. package/src/components/ui/calendar.tsx +0 -387
  94. package/src/components/ui/card.tsx +0 -214
  95. package/src/components/ui/checkbox.tsx +0 -259
  96. package/src/components/ui/collapsible.tsx +0 -135
  97. package/src/components/ui/color-picker.tsx +0 -97
  98. package/src/components/ui/command.tsx +0 -225
  99. package/src/components/ui/dialog.tsx +0 -334
  100. package/src/components/ui/dropdown-menu.tsx +0 -218
  101. package/src/components/ui/gesture-drawer.tsx +0 -11
  102. package/src/components/ui/hover-card.tsx +0 -29
  103. package/src/components/ui/index.ts +0 -190
  104. package/src/components/ui/input.tsx +0 -222
  105. package/src/components/ui/label.tsx +0 -29
  106. package/src/components/ui/lightbox.tsx +0 -606
  107. package/src/components/ui/magnetic-button.tsx +0 -129
  108. package/src/components/ui/media-gallery.tsx +0 -612
  109. package/src/components/ui/pagination.tsx +0 -123
  110. package/src/components/ui/popover.tsx +0 -185
  111. package/src/components/ui/progress.tsx +0 -30
  112. package/src/components/ui/radio-group.tsx +0 -257
  113. package/src/components/ui/scroll-area.tsx +0 -47
  114. package/src/components/ui/select.tsx +0 -374
  115. package/src/components/ui/separator.tsx +0 -145
  116. package/src/components/ui/sheet.tsx +0 -139
  117. package/src/components/ui/skeleton.tsx +0 -20
  118. package/src/components/ui/slider.tsx +0 -354
  119. package/src/components/ui/spotlight-card.tsx +0 -119
  120. package/src/components/ui/switch.tsx +0 -86
  121. package/src/components/ui/table.tsx +0 -329
  122. package/src/components/ui/tabs.tsx +0 -198
  123. package/src/components/ui/textarea.tsx +0 -28
  124. package/src/components/ui/toast.tsx +0 -317
  125. package/src/components/ui/toggle.tsx +0 -119
  126. package/src/components/ui/tooltip.tsx +0 -151
  127. package/src/components/virtual-list/index.tsx +0 -668
  128. package/src/hooks/use-chart.ts +0 -205
  129. package/src/hooks/use-data-table.ts +0 -182
  130. package/src/hooks/use-docs-pro-access.ts +0 -13
  131. package/src/hooks/use-license-check.ts +0 -65
  132. package/src/hooks/use-subscription.ts +0 -19
  133. package/src/hooks/use-toast.ts +0 -15
  134. package/src/index.ts +0 -14
  135. package/src/lib/ai-providers.ts +0 -377
  136. package/src/lib/component-metadata.ts +0 -18
  137. package/src/lib/micro-interactions.ts +0 -255
  138. package/src/lib/paddle.ts +0 -17
  139. package/src/lib/utils.ts +0 -6
  140. package/src/patterns/login-form/index.tsx +0 -276
  141. package/src/patterns/login-form/types.ts +0 -67
  142. package/src/setupTests.ts +0 -41
  143. package/src/styles/advanced-chart.css +0 -239
  144. package/src/styles/calendar.css +0 -35
  145. package/src/styles/design-system.css +0 -363
  146. package/src/styles/index.css +0 -85
  147. package/src/styles/tailwind.css +0 -7
  148. package/src/styles/tokens.css +0 -455
  149. package/src/types/moonui.d.ts +0 -22
  150. package/src/types/next-auth.d.ts +0 -21
  151. package/src/use-intersection-observer.tsx +0 -154
  152. package/src/use-local-storage.tsx +0 -71
  153. package/src/use-paddle.ts +0 -138
  154. package/src/use-performance-optimizer.ts +0 -389
  155. package/src/use-pro-access.ts +0 -141
  156. package/src/use-scroll-animation.ts +0 -219
  157. package/src/use-subscription.ts +0 -37
  158. package/src/use-toast.ts +0 -32
  159. package/src/utils/chart-helpers.ts +0 -357
  160. package/src/utils/cn.ts +0 -6
  161. package/src/utils/data-processing.ts +0 -151
  162. package/src/utils/license-validator.tsx +0 -183
@@ -1,516 +0,0 @@
1
- import { useState, useEffect, useCallback, useRef } from "react"
2
- import {
3
- GitHubRepository,
4
- GitHubStats,
5
- RateLimitInfo,
6
- StarHistory,
7
- Milestone,
8
- } from "./types"
9
- import {
10
- fetchUserRepositories,
11
- fetchRepository,
12
- fetchContributorsCount,
13
- fetchStarHistory,
14
- calculateStats,
15
- getRateLimitInfo,
16
- clearCache,
17
- } from "./github-api"
18
-
19
- interface UseGitHubDataOptions {
20
- username?: string
21
- repository?: string
22
- repositories?: string[]
23
- token?: string
24
- autoRefresh?: boolean
25
- refreshInterval?: number
26
- sortBy?: string
27
- maxItems?: number
28
- onError?: (error: Error) => void
29
- onDataUpdate?: (stats: GitHubStats) => void
30
- onMilestoneReached?: (milestone: Milestone) => void
31
- milestones?: number[]
32
- // For docs mode optimizations
33
- docsMode?: boolean
34
- mockDataFallback?: boolean
35
- forceMockData?: boolean // Force mock data instead of API
36
- }
37
-
38
- export function useGitHubData({
39
- username,
40
- repository,
41
- repositories,
42
- token,
43
- autoRefresh = false,
44
- refreshInterval = 300000,
45
- sortBy = "stars",
46
- maxItems,
47
- onError,
48
- onDataUpdate,
49
- onMilestoneReached,
50
- milestones = [10, 50, 100, 500, 1000, 5000, 10000],
51
- docsMode = false,
52
- mockDataFallback = true,
53
- forceMockData = false,
54
- }: UseGitHubDataOptions) {
55
- // Docs mode detection
56
- const isDocsMode = docsMode || (typeof window !== "undefined" &&
57
- (window.location.pathname.includes("/docs/") ||
58
- window.location.pathname.includes("/components/")))
59
-
60
- // Disable autoRefresh in docs mode
61
- const effectiveAutoRefresh = isDocsMode ? false : autoRefresh
62
- const [repos, setRepos] = useState<GitHubRepository[]>([])
63
- const [stats, setStats] = useState<GitHubStats | null>(null)
64
- const [loading, setLoading] = useState(true)
65
- const [error, setError] = useState<string | null>(null)
66
- const [rateLimitInfo, setRateLimitInfo] = useState<RateLimitInfo | null>(null)
67
- const [lastUpdated, setLastUpdated] = useState<Date | null>(null)
68
-
69
- const refreshTimeoutRef = useRef<NodeJS.Timeout | undefined>(undefined)
70
- const previousStarsRef = useRef<Map<string, number>>(new Map())
71
- const errorCountRef = useRef<number>(0) // Hata sayısını takip et
72
- const maxErrorCount = isDocsMode ? 1 : 2 // Fewer retries in docs mode
73
- const hasInitialFetchedRef = useRef(false) // İlk fetch yapıldı mı?
74
- const docsDataCacheRef = useRef<GitHubRepository[] | null>(null) // Docs mode cache
75
-
76
- // Store checkMilestones function as ref - this way it won't be recreated on every render
77
- const milestonesRef = useRef(milestones)
78
- const onMilestoneReachedRef = useRef(onMilestoneReached)
79
-
80
- // Ref'leri güncelle
81
- useEffect(() => {
82
- milestonesRef.current = milestones
83
- }, [milestones])
84
-
85
- useEffect(() => {
86
- onMilestoneReachedRef.current = onMilestoneReached
87
- }, [onMilestoneReached])
88
-
89
- const checkMilestones = useCallback((repos: GitHubRepository[]) => {
90
- if (!onMilestoneReachedRef.current) return
91
-
92
- repos.forEach(repo => {
93
- const previousStars = previousStarsRef.current.get(repo.full_name) || 0
94
- const currentStars = repo.stargazers_count
95
-
96
- milestonesRef.current.forEach(milestone => {
97
- if (previousStars < milestone && currentStars >= milestone) {
98
- onMilestoneReachedRef.current?.({
99
- count: milestone,
100
- reached: true,
101
- date: new Date().toISOString(),
102
- celebration: true,
103
- })
104
- }
105
- })
106
-
107
- previousStarsRef.current.set(repo.full_name, currentStars)
108
- })
109
- }, []) // Boş dependency array - fonksiyon asla yeniden oluşturulmaz
110
-
111
- const fetchData = useCallback(async () => {
112
- // If forceMockData is true, always return mock data
113
- if (forceMockData) {
114
- console.log("[Mock Mode] Using mock data")
115
- const mockData = getMockGitHubData(username, repository, repositories)
116
- setRepos(mockData)
117
- const calculatedStats = calculateStats(mockData)
118
- setStats(calculatedStats)
119
- setError(null)
120
- setLoading(false)
121
- return
122
- }
123
-
124
- // Docs modunda ve daha önce fetch yapıldıysa, cache'den döndür
125
- if (isDocsMode && hasInitialFetchedRef.current && docsDataCacheRef.current) {
126
- console.log("[Docs Mode] Returning cached data, skipping API request")
127
- setRepos(docsDataCacheRef.current)
128
- const calculatedStats = calculateStats(docsDataCacheRef.current)
129
- setStats(calculatedStats)
130
- setLoading(false)
131
- return
132
- }
133
-
134
- // Hata limiti aşıldıysa istek yapma
135
- if (errorCountRef.current >= maxErrorCount) {
136
- console.warn("Maximum error count reached. Stopping requests.")
137
-
138
- // Show mock data if in docs mode and mockDataFallback is active
139
- if (isDocsMode && mockDataFallback) {
140
- const mockData = getMockGitHubData(username, repository, repositories)
141
- setRepos(mockData)
142
- const calculatedStats = calculateStats(mockData)
143
- setStats(calculatedStats)
144
- setError(null)
145
- } else {
146
- setError("Maximum retry limit exceeded. Please check your configuration.")
147
- }
148
-
149
- setLoading(false)
150
- return
151
- }
152
-
153
- // Don't make requests if required info is missing
154
- const hasValidInput =
155
- (username && repository) || // Tek repository modu
156
- (username && repositories && repositories.length > 0) || // Çoklu repository modu
157
- (repositories && repositories.length > 0 && repositories.every(r => r.includes('/'))) || // Full path repositories
158
- username // Kullanıcının tüm repositoryleri
159
-
160
- if (!hasValidInput) {
161
- console.warn("No valid input provided. Skipping API request.")
162
- setLoading(false)
163
- setError(null)
164
- setRepos([])
165
- setStats(null)
166
- return
167
- }
168
-
169
- try {
170
- setLoading(true)
171
- setError(null)
172
-
173
- // Check rate limit first
174
- try {
175
- const rateLimit = await getRateLimitInfo(token)
176
- setRateLimitInfo(rateLimit)
177
-
178
- if (rateLimit.remaining < 10) {
179
- console.warn(`Low GitHub API rate limit: ${rateLimit.remaining} requests remaining`)
180
- }
181
- } catch (error) {
182
- console.error("Failed to fetch rate limit:", error)
183
- }
184
-
185
- let fetchedRepos: GitHubRepository[] = []
186
-
187
- // Single repository mode
188
- if (repository && username) {
189
- const repo = await fetchRepository(username, repository, token)
190
- fetchedRepos = [repo]
191
- }
192
- // Multiple specific repositories with full paths
193
- else if (repositories && repositories.length > 0 && repositories.every(r => r.includes('/'))) {
194
- const repoPromises = repositories.map(fullPath => {
195
- const [owner, name] = fullPath.split('/')
196
- return fetchRepository(owner, name, token)
197
- })
198
- fetchedRepos = await Promise.all(repoPromises)
199
- }
200
- // Multiple specific repositories with username
201
- else if (repositories && repositories.length > 0 && username) {
202
- const repoPromises = repositories.map(repoName =>
203
- fetchRepository(username, repoName, token)
204
- )
205
- fetchedRepos = await Promise.all(repoPromises)
206
- }
207
- // All user repositories
208
- else if (username) {
209
- fetchedRepos = await fetchUserRepositories(username, token, {
210
- sort: sortBy,
211
- per_page: 100,
212
- })
213
- }
214
-
215
- // Sort repositories
216
- fetchedRepos.sort((a, b) => {
217
- switch (sortBy) {
218
- case "stars":
219
- return b.stargazers_count - a.stargazers_count
220
- case "forks":
221
- return b.forks_count - a.forks_count
222
- case "updated":
223
- return new Date(b.updated_at).getTime() - new Date(a.updated_at).getTime()
224
- case "created":
225
- return new Date(b.created_at).getTime() - new Date(a.created_at).getTime()
226
- case "name":
227
- return a.name.localeCompare(b.name)
228
- case "issues":
229
- return b.open_issues_count - a.open_issues_count
230
- default:
231
- return 0
232
- }
233
- })
234
-
235
- // Limit results
236
- if (maxItems && maxItems > 0) {
237
- fetchedRepos = fetchedRepos.slice(0, maxItems)
238
- }
239
-
240
- // Fetch additional data for detailed view
241
- const enhancedRepos = await Promise.all(
242
- fetchedRepos.map(async repo => {
243
- try {
244
- const contributorsCount = await fetchContributorsCount(
245
- repo.owner.login,
246
- repo.name,
247
- token
248
- )
249
- return { ...repo, contributors_count: contributorsCount }
250
- } catch (error) {
251
- console.error(`Failed to fetch contributors for ${repo.full_name}:`, error)
252
- return repo
253
- }
254
- })
255
- )
256
-
257
- setRepos(enhancedRepos)
258
-
259
- // Calculate statistics
260
- const calculatedStats = calculateStats(enhancedRepos)
261
- setStats(calculatedStats)
262
-
263
- // Check milestones
264
- checkMilestones(enhancedRepos)
265
-
266
- // Notify data update
267
- if (onDataUpdate) {
268
- onDataUpdate(calculatedStats)
269
- }
270
-
271
- setLastUpdated(new Date())
272
- // Reset error counter on success
273
- errorCountRef.current = 0
274
-
275
- // Cache successful data in docs mode
276
- if (isDocsMode) {
277
- hasInitialFetchedRef.current = true
278
- docsDataCacheRef.current = enhancedRepos
279
- }
280
- } catch (err) {
281
- const errorMessage = err instanceof Error ? err.message : "Failed to fetch data"
282
- setError(errorMessage)
283
-
284
- // Hata sayacını artır
285
- errorCountRef.current += 1
286
- console.error(`GitHub API error (${errorCountRef.current}/${maxErrorCount}):`, errorMessage)
287
-
288
- // Show mock data if in docs mode and mockDataFallback is active
289
- if (isDocsMode && mockDataFallback && !hasInitialFetchedRef.current) {
290
- console.warn("[Docs Mode] API failed, using mock data")
291
- const mockData = getMockGitHubData(username, repository, repositories)
292
- setRepos(mockData)
293
- const calculatedStats = calculateStats(mockData)
294
- setStats(calculatedStats)
295
- setError(null)
296
- hasInitialFetchedRef.current = true
297
- docsDataCacheRef.current = mockData
298
- } else if (onError) {
299
- onError(err instanceof Error ? err : new Error(errorMessage))
300
- }
301
- } finally {
302
- setLoading(false)
303
- }
304
- }, [
305
- username,
306
- repository,
307
- repositories?.join(','), // Convert array to string to keep reference stable
308
- token,
309
- sortBy,
310
- maxItems,
311
- checkMilestones, // Now stable
312
- onDataUpdate,
313
- onError,
314
- isDocsMode,
315
- mockDataFallback,
316
- forceMockData,
317
- ])
318
-
319
- // Initial fetch
320
- useEffect(() => {
321
- // Only fetch if there's valid input
322
- const hasValidInput =
323
- (username && repository) ||
324
- (username && repositories && repositories.length > 0) ||
325
- (repositories && repositories.length > 0 && repositories.every(r => r.includes('/'))) ||
326
- username
327
-
328
- if (hasValidInput) {
329
- fetchData()
330
- } else {
331
- setLoading(false)
332
- }
333
- }, [fetchData])
334
-
335
- // Auto-refresh
336
- useEffect(() => {
337
- // Completely disable auto-refresh in docs mode
338
- if (!effectiveAutoRefresh) return
339
-
340
- const scheduleRefresh = () => {
341
- refreshTimeoutRef.current = setTimeout(() => {
342
- fetchData()
343
- scheduleRefresh()
344
- }, refreshInterval)
345
- }
346
-
347
- scheduleRefresh()
348
-
349
- return () => {
350
- if (refreshTimeoutRef.current) {
351
- clearTimeout(refreshTimeoutRef.current)
352
- }
353
- }
354
- }, [effectiveAutoRefresh, refreshInterval, fetchData])
355
-
356
- const refresh = useCallback(() => {
357
- // Limit refresh in docs mode
358
- if (isDocsMode && hasInitialFetchedRef.current) {
359
- console.warn("[Docs Mode] Refresh disabled after initial fetch")
360
- return Promise.resolve()
361
- }
362
-
363
- // Hata limiti aşıldıysa refresh yapma
364
- if (errorCountRef.current >= maxErrorCount) {
365
- console.warn("Cannot refresh: maximum error count reached")
366
- return Promise.resolve()
367
- }
368
-
369
- clearCache()
370
- return fetchData()
371
- }, [fetchData, isDocsMode])
372
-
373
- return {
374
- repos,
375
- stats,
376
- loading,
377
- error,
378
- rateLimitInfo,
379
- lastUpdated,
380
- refresh,
381
- }
382
- }
383
-
384
- // Hook for star history
385
- export function useStarHistory(
386
- owner: string,
387
- repo: string,
388
- token?: string
389
- ) {
390
- const [history, setHistory] = useState<StarHistory[]>([])
391
- const [loading, setLoading] = useState(true)
392
- const [error, setError] = useState<string | null>(null)
393
-
394
- useEffect(() => {
395
- const fetchHistory = async () => {
396
- try {
397
- setLoading(true)
398
- setError(null)
399
- const data = await fetchStarHistory(owner, repo, token)
400
- setHistory(data)
401
- } catch (err) {
402
- setError(err instanceof Error ? err.message : "Failed to fetch star history")
403
- } finally {
404
- setLoading(false)
405
- }
406
- }
407
-
408
- if (owner && repo) {
409
- fetchHistory()
410
- }
411
- }, [owner, repo, token])
412
-
413
- return { history, loading, error }
414
- }
415
-
416
- // Hook for notifications
417
- export function useGitHubNotifications(enabled: boolean = true) {
418
- const [permission, setPermission] = useState<NotificationPermission>("default")
419
-
420
- useEffect(() => {
421
- if (!enabled || typeof window === "undefined" || !("Notification" in window)) {
422
- return
423
- }
424
-
425
- setPermission(Notification.permission)
426
-
427
- if (Notification.permission === "default") {
428
- Notification.requestPermission().then(setPermission)
429
- }
430
- }, [enabled])
431
-
432
- const notify = useCallback(
433
- (title: string, options?: NotificationOptions) => {
434
- if (!enabled || permission !== "granted") return
435
-
436
- try {
437
- new Notification(title, {
438
- icon: "/icon-192x192.png",
439
- badge: "/icon-192x192.png",
440
- ...options,
441
- })
442
- } catch (error) {
443
- console.error("Failed to show notification:", error)
444
- }
445
- },
446
- [enabled, permission]
447
- )
448
-
449
- return { permission, notify }
450
- }
451
-
452
- // Mock data generator for docs mode
453
- function getMockGitHubData(
454
- username?: string,
455
- repository?: string,
456
- repositories?: string[]
457
- ): GitHubRepository[] {
458
- const defaultRepos: GitHubRepository[] = [
459
- {
460
- id: 1,
461
- name: repository || "awesome-project",
462
- full_name: `${username || "moonui"}/${repository || "awesome-project"}`,
463
- description: "An amazing open source project with great features",
464
- html_url: `https://github.com/${username || "moonui"}/${repository || "awesome-project"}`,
465
- homepage: "https://awesome-project.dev",
466
- stargazers_count: 12453,
467
- watchers_count: 543,
468
- forks_count: 2341,
469
- language: "TypeScript",
470
- topics: ["react", "ui", "components", "typescript"],
471
- created_at: "2022-01-15T10:30:00Z",
472
- updated_at: new Date().toISOString(),
473
- pushed_at: new Date().toISOString(),
474
- size: 4567,
475
- open_issues_count: 23,
476
- license: {
477
- key: "mit",
478
- name: "MIT License",
479
- spdx_id: "MIT",
480
- url: "https://api.github.com/licenses/mit",
481
- },
482
- owner: {
483
- login: username || "moonui",
484
- avatar_url: `https://github.com/${username || "moonui"}.png`,
485
- html_url: `https://github.com/${username || "moonui"}`,
486
- type: "Organization",
487
- },
488
- contributors_count: 89,
489
- },
490
- ]
491
-
492
- if (repositories && repositories.length > 0) {
493
- return repositories.map((repo, index) => {
494
- const [owner, name] = repo.includes('/') ? repo.split('/') : [username || "moonui", repo]
495
- return {
496
- ...defaultRepos[0],
497
- id: index + 1,
498
- name: name,
499
- full_name: `${owner}/${name}`,
500
- html_url: `https://github.com/${owner}/${name}`,
501
- stargazers_count: Math.floor(Math.random() * 20000) + 1000,
502
- forks_count: Math.floor(Math.random() * 3000) + 100,
503
- watchers_count: Math.floor(Math.random() * 1000) + 50,
504
- language: ["TypeScript", "JavaScript", "Python", "Go", "Rust"][index % 5],
505
- owner: {
506
- login: owner,
507
- avatar_url: `https://github.com/${owner}.png`,
508
- html_url: `https://github.com/${owner}`,
509
- type: "Organization",
510
- },
511
- }
512
- })
513
- }
514
-
515
- return defaultRepos
516
- }