@moontra/moonui 2.3.6 → 2.3.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/dist/index.d.mts +4 -1
- package/dist/index.d.ts +4 -1
- package/dist/index.global.js +1 -1
- package/dist/index.global.js.map +1 -1
- package/dist/index.js +11 -2
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +11 -2
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
- package/src/components/ui/badge.tsx +14 -2
- package/src/components/ui/pro-component-wrapper.tsx +0 -261
package/package.json
CHANGED
|
@@ -15,7 +15,9 @@ const badgeVariants = cva(
|
|
|
15
15
|
["inline-flex items-center justify-center gap-1.5",
|
|
16
16
|
"font-medium transition-colors duration-200",
|
|
17
17
|
"border focus:outline-none",
|
|
18
|
-
"focus-visible:ring-2 focus-visible:ring-offset-1"
|
|
18
|
+
"focus-visible:ring-2 focus-visible:ring-offset-1",
|
|
19
|
+
// Auto spacing between badges
|
|
20
|
+
"mr-2 mb-2 last:mr-0"],
|
|
19
21
|
{
|
|
20
22
|
variants: {
|
|
21
23
|
variant: {
|
|
@@ -106,6 +108,8 @@ export interface BadgeProps
|
|
|
106
108
|
leftIcon?: React.ReactNode;
|
|
107
109
|
rightIcon?: React.ReactNode;
|
|
108
110
|
variant?: 'primary' | 'secondary' | 'destructive' | 'outline' | 'success' | 'warning' | 'ghost' | 'pro' | 'admin';
|
|
111
|
+
/** Disable automatic spacing between badges */
|
|
112
|
+
noAutoSpacing?: boolean;
|
|
109
113
|
}
|
|
110
114
|
|
|
111
115
|
/**
|
|
@@ -121,6 +125,7 @@ export interface BadgeProps
|
|
|
121
125
|
* @param props.onRemove - Kaldırma işlevi
|
|
122
126
|
* @param props.leftIcon - Badge'in solunda görüntülenecek ikon
|
|
123
127
|
* @param props.rightIcon - Badge'in sağında görüntülenecek ikon
|
|
128
|
+
* @param props.noAutoSpacing - Otomatik spacing'i devre dışı bırak
|
|
124
129
|
*/
|
|
125
130
|
function Badge({
|
|
126
131
|
className,
|
|
@@ -133,6 +138,7 @@ function Badge({
|
|
|
133
138
|
onRemove,
|
|
134
139
|
leftIcon,
|
|
135
140
|
rightIcon,
|
|
141
|
+
noAutoSpacing,
|
|
136
142
|
children,
|
|
137
143
|
...props
|
|
138
144
|
}: BadgeProps) {
|
|
@@ -164,7 +170,13 @@ function Badge({
|
|
|
164
170
|
|
|
165
171
|
return (
|
|
166
172
|
<div
|
|
167
|
-
className={cn(
|
|
173
|
+
className={cn(
|
|
174
|
+
"moonui-theme",
|
|
175
|
+
badgeVariants({ variant, size, radius }),
|
|
176
|
+
// Remove auto-spacing if noAutoSpacing is true
|
|
177
|
+
noAutoSpacing && "mr-0 mb-0",
|
|
178
|
+
className
|
|
179
|
+
)}
|
|
168
180
|
data-removable={removable ? "" : undefined}
|
|
169
181
|
{...props}
|
|
170
182
|
>
|
|
@@ -1,261 +0,0 @@
|
|
|
1
|
-
"use client"
|
|
2
|
-
|
|
3
|
-
// Pro Component Wrapper - Simplified Version
|
|
4
|
-
// Development: CLI auth required
|
|
5
|
-
// Production: License key validation with 24h cache
|
|
6
|
-
|
|
7
|
-
import React, { useState, useEffect } from 'react'
|
|
8
|
-
import { cn } from '../../lib/utils'
|
|
9
|
-
import { Badge } from './badge'
|
|
10
|
-
import { Lock, Terminal, AlertCircle } from 'lucide-react'
|
|
11
|
-
|
|
12
|
-
interface ProComponentWrapperProps {
|
|
13
|
-
children: React.ReactNode
|
|
14
|
-
componentId: string
|
|
15
|
-
componentName?: string
|
|
16
|
-
className?: string
|
|
17
|
-
fallback?: React.ReactNode
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
interface LicenseCache {
|
|
21
|
-
timestamp: number
|
|
22
|
-
hasProAccess: boolean
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
const CACHE_KEY = 'moonui_license_cache'
|
|
26
|
-
const CACHE_DURATION = 24 * 60 * 60 * 1000 // 24 hours
|
|
27
|
-
|
|
28
|
-
export function ProComponentWrapper({
|
|
29
|
-
children,
|
|
30
|
-
componentId,
|
|
31
|
-
componentName,
|
|
32
|
-
className,
|
|
33
|
-
fallback
|
|
34
|
-
}: ProComponentWrapperProps) {
|
|
35
|
-
const [state, setState] = useState<{
|
|
36
|
-
hasAccess: boolean
|
|
37
|
-
loading: boolean
|
|
38
|
-
message?: string
|
|
39
|
-
}>({
|
|
40
|
-
hasAccess: false,
|
|
41
|
-
loading: true
|
|
42
|
-
})
|
|
43
|
-
|
|
44
|
-
useEffect(() => {
|
|
45
|
-
// Check if development environment
|
|
46
|
-
const isDevelopment = () => {
|
|
47
|
-
if (typeof window === 'undefined') return false
|
|
48
|
-
|
|
49
|
-
const isLocalhost =
|
|
50
|
-
window.location.hostname === 'localhost' ||
|
|
51
|
-
window.location.hostname === '127.0.0.1' ||
|
|
52
|
-
window.location.hostname.includes('.local')
|
|
53
|
-
|
|
54
|
-
const isDevPort =
|
|
55
|
-
window.location.port === '3000' ||
|
|
56
|
-
window.location.port === '3001' ||
|
|
57
|
-
window.location.port === '8080' ||
|
|
58
|
-
window.location.port === '5173'
|
|
59
|
-
|
|
60
|
-
// Must be localhost with dev port
|
|
61
|
-
return process.env.NODE_ENV === 'development' && isLocalhost && isDevPort
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
// DEVELOPMENT: Check CLI auth
|
|
65
|
-
if (isDevelopment()) {
|
|
66
|
-
const checkDevAuth = () => {
|
|
67
|
-
const cliToken = localStorage.getItem('moonui_cli_token')
|
|
68
|
-
const deviceId = localStorage.getItem('moonui_device_id')
|
|
69
|
-
|
|
70
|
-
if (!cliToken || !deviceId) {
|
|
71
|
-
setState({
|
|
72
|
-
hasAccess: false,
|
|
73
|
-
loading: false,
|
|
74
|
-
message: 'CLI authentication required'
|
|
75
|
-
})
|
|
76
|
-
return
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
// Token exists - allow access
|
|
80
|
-
setState({
|
|
81
|
-
hasAccess: true,
|
|
82
|
-
loading: false
|
|
83
|
-
})
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
checkDevAuth()
|
|
87
|
-
return
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
// PRODUCTION: Check license cache
|
|
91
|
-
const checkProdLicense = () => {
|
|
92
|
-
try {
|
|
93
|
-
// Check cache first
|
|
94
|
-
const cached = localStorage.getItem(CACHE_KEY)
|
|
95
|
-
if (cached) {
|
|
96
|
-
const data = JSON.parse(cached) as LicenseCache
|
|
97
|
-
const now = Date.now()
|
|
98
|
-
|
|
99
|
-
// Cache still valid (24 hours)
|
|
100
|
-
if (data.timestamp && (now - data.timestamp) < CACHE_DURATION) {
|
|
101
|
-
setState({
|
|
102
|
-
hasAccess: data.hasProAccess,
|
|
103
|
-
loading: false
|
|
104
|
-
})
|
|
105
|
-
return
|
|
106
|
-
}
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
// No valid cache - need license key
|
|
110
|
-
const licenseKey = process.env.NEXT_PUBLIC_MOONUI_LICENSE_KEY
|
|
111
|
-
|
|
112
|
-
if (!licenseKey) {
|
|
113
|
-
setState({
|
|
114
|
-
hasAccess: false,
|
|
115
|
-
loading: false,
|
|
116
|
-
message: 'No license key configured'
|
|
117
|
-
})
|
|
118
|
-
return
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
// Validate license async
|
|
122
|
-
validateLicense(licenseKey).then(result => {
|
|
123
|
-
// Save to cache
|
|
124
|
-
const cacheData: LicenseCache = {
|
|
125
|
-
timestamp: Date.now(),
|
|
126
|
-
hasProAccess: result.hasProAccess
|
|
127
|
-
}
|
|
128
|
-
localStorage.setItem(CACHE_KEY, JSON.stringify(cacheData))
|
|
129
|
-
|
|
130
|
-
setState({
|
|
131
|
-
hasAccess: result.hasProAccess,
|
|
132
|
-
loading: false
|
|
133
|
-
})
|
|
134
|
-
}).catch(error => {
|
|
135
|
-
console.error('License validation failed:', error)
|
|
136
|
-
|
|
137
|
-
// Try expired cache as fallback
|
|
138
|
-
const cached = localStorage.getItem(CACHE_KEY)
|
|
139
|
-
if (cached) {
|
|
140
|
-
const data = JSON.parse(cached) as LicenseCache
|
|
141
|
-
setState({
|
|
142
|
-
hasAccess: data.hasProAccess,
|
|
143
|
-
loading: false,
|
|
144
|
-
message: 'Using cached license'
|
|
145
|
-
})
|
|
146
|
-
} else {
|
|
147
|
-
setState({
|
|
148
|
-
hasAccess: false,
|
|
149
|
-
loading: false,
|
|
150
|
-
message: 'License validation failed'
|
|
151
|
-
})
|
|
152
|
-
}
|
|
153
|
-
})
|
|
154
|
-
|
|
155
|
-
} catch (error) {
|
|
156
|
-
console.error('License check error:', error)
|
|
157
|
-
setState({
|
|
158
|
-
hasAccess: false,
|
|
159
|
-
loading: false,
|
|
160
|
-
message: 'License check failed'
|
|
161
|
-
})
|
|
162
|
-
}
|
|
163
|
-
}
|
|
164
|
-
|
|
165
|
-
checkProdLicense()
|
|
166
|
-
}, [])
|
|
167
|
-
|
|
168
|
-
// Loading state
|
|
169
|
-
if (state.loading) {
|
|
170
|
-
return (
|
|
171
|
-
<div className={cn("animate-pulse bg-gray-200 dark:bg-gray-800 rounded-lg h-32", className)}>
|
|
172
|
-
<div className="flex items-center justify-center h-full">
|
|
173
|
-
<div className="text-sm text-gray-500">Loading...</div>
|
|
174
|
-
</div>
|
|
175
|
-
</div>
|
|
176
|
-
)
|
|
177
|
-
}
|
|
178
|
-
|
|
179
|
-
// Access granted
|
|
180
|
-
if (state.hasAccess) {
|
|
181
|
-
return <>{children}</>
|
|
182
|
-
}
|
|
183
|
-
|
|
184
|
-
// Development: Show CLI auth required
|
|
185
|
-
if (state.message === 'CLI authentication required') {
|
|
186
|
-
return (
|
|
187
|
-
<div className={cn("relative", className)}>
|
|
188
|
-
<div className="blur-sm grayscale opacity-60 pointer-events-none">
|
|
189
|
-
{fallback || children}
|
|
190
|
-
</div>
|
|
191
|
-
<div className="absolute inset-0 bg-gradient-to-br from-blue-500/10 via-transparent to-purple-500/10 border-2 border-dashed border-blue-400/30 rounded-lg flex items-center justify-center">
|
|
192
|
-
<div className="text-center space-y-3 p-6 bg-white/90 dark:bg-gray-900/90 rounded-lg">
|
|
193
|
-
<Badge variant="secondary" className="mb-2">
|
|
194
|
-
<Terminal className="w-3 h-3 mr-1" />
|
|
195
|
-
DEV AUTH REQUIRED
|
|
196
|
-
</Badge>
|
|
197
|
-
<h3 className="font-semibold">CLI Authentication Required</h3>
|
|
198
|
-
<p className="text-sm text-gray-600 dark:text-gray-400 max-w-xs">
|
|
199
|
-
Login with MoonUI CLI to use Pro components in development
|
|
200
|
-
</p>
|
|
201
|
-
<code className="block bg-black text-green-400 p-2 rounded text-xs font-mono">
|
|
202
|
-
npx moonui auth login
|
|
203
|
-
</code>
|
|
204
|
-
</div>
|
|
205
|
-
</div>
|
|
206
|
-
</div>
|
|
207
|
-
)
|
|
208
|
-
}
|
|
209
|
-
|
|
210
|
-
// Production: Show license required
|
|
211
|
-
return (
|
|
212
|
-
<div className={cn("relative", className)}>
|
|
213
|
-
<div className="blur-sm grayscale opacity-60 pointer-events-none">
|
|
214
|
-
{fallback || children}
|
|
215
|
-
</div>
|
|
216
|
-
<div className="absolute inset-0 bg-gradient-to-br from-amber-500/10 via-transparent to-orange-500/10 border-2 border-dashed border-amber-400/30 rounded-lg flex items-center justify-center">
|
|
217
|
-
<div className="text-center space-y-3 p-6 bg-white/90 dark:bg-gray-900/90 rounded-lg">
|
|
218
|
-
<Badge variant="destructive" className="mb-2">
|
|
219
|
-
<AlertCircle className="w-3 h-3 mr-1" />
|
|
220
|
-
LICENSE REQUIRED
|
|
221
|
-
</Badge>
|
|
222
|
-
<h3 className="font-semibold">{componentName || componentId}</h3>
|
|
223
|
-
<p className="text-sm text-gray-600 dark:text-gray-400 max-w-xs">
|
|
224
|
-
{state.message || 'Pro license required to use this component'}
|
|
225
|
-
</p>
|
|
226
|
-
<a
|
|
227
|
-
href="https://moonui.dev/pricing"
|
|
228
|
-
target="_blank"
|
|
229
|
-
rel="noopener noreferrer"
|
|
230
|
-
className="inline-block bg-gradient-to-r from-amber-500 to-orange-500 text-white px-4 py-2 rounded-lg text-sm font-medium hover:from-amber-600 hover:to-orange-600 transition-colors"
|
|
231
|
-
>
|
|
232
|
-
Get Pro License
|
|
233
|
-
</a>
|
|
234
|
-
</div>
|
|
235
|
-
</div>
|
|
236
|
-
</div>
|
|
237
|
-
)
|
|
238
|
-
}
|
|
239
|
-
|
|
240
|
-
// Validate license with API
|
|
241
|
-
async function validateLicense(licenseKey: string): Promise<{ hasProAccess: boolean }> {
|
|
242
|
-
const response = await fetch('/api/v1/license/validate', {
|
|
243
|
-
method: 'POST',
|
|
244
|
-
headers: {
|
|
245
|
-
'Content-Type': 'application/json'
|
|
246
|
-
},
|
|
247
|
-
body: JSON.stringify({
|
|
248
|
-
licenseKey,
|
|
249
|
-
domain: window.location.hostname
|
|
250
|
-
})
|
|
251
|
-
})
|
|
252
|
-
|
|
253
|
-
if (!response.ok) {
|
|
254
|
-
throw new Error('License validation failed')
|
|
255
|
-
}
|
|
256
|
-
|
|
257
|
-
const data = await response.json()
|
|
258
|
-
return {
|
|
259
|
-
hasProAccess: data.hasProAccess || false
|
|
260
|
-
}
|
|
261
|
-
}
|