@moontra/moonui-pro 2.5.0 → 2.5.1

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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@moontra/moonui-pro",
3
- "version": "2.5.0",
3
+ "version": "2.5.1",
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",
@@ -7,7 +7,8 @@ import { Widget } from './types'
7
7
  import { MetricCard } from './widgets/metric-card'
8
8
  import { ChartWidget } from './widgets/chart-widget'
9
9
  import { ActivityFeed } from './widgets/activity-feed'
10
- import GridLayout, { Layout, Layouts } from 'react-grid-layout'
10
+ import { Responsive, WidthProvider, Layout, Layouts } from 'react-grid-layout'
11
+ const ResponsiveGridLayout = WidthProvider(Responsive)
11
12
  import 'react-grid-layout/css/styles.css'
12
13
  import 'react-resizable/css/styles.css'
13
14
  import {
@@ -45,31 +46,114 @@ export function DashboardGrid({
45
46
  className,
46
47
  glassmorphism = false,
47
48
  breakpoints = { lg: 1200, md: 996, sm: 768, xs: 480, xxs: 0 },
48
- cols = { lg: 12, md: 10, sm: 6, xs: 4, xxs: 2 },
49
- rowHeight = 60,
50
- margin = [16, 16],
49
+ cols = { lg: 12, md: 8, sm: 4, xs: 2, xxs: 1 },
50
+ rowHeight = 80,
51
+ margin = [16, 24],
51
52
  containerPadding = [0, 0]
52
53
  }: DashboardGridProps) {
53
54
  const [layouts, setLayouts] = React.useState<Layouts>({})
54
55
  const [currentBreakpoint, setCurrentBreakpoint] = React.useState('lg')
55
56
  const [lockedWidgets, setLockedWidgets] = React.useState<Set<string>>(new Set())
56
57
  const [fullscreenWidget, setFullscreenWidget] = React.useState<string | null>(null)
58
+ const [containerWidth, setContainerWidth] = React.useState(1200)
59
+ const containerRef = React.useRef<HTMLDivElement>(null)
60
+ const [compactType, setCompactType] = React.useState<'vertical' | 'horizontal' | null>('vertical')
57
61
 
58
- // Layout oluştur
59
- const generateLayout = (): Layout[] => {
60
- return widgets.map((widget) => ({
62
+ // Container genişliğini ölç ve breakpoint'i güncelle
63
+ React.useEffect(() => {
64
+ const updateWidth = () => {
65
+ if (containerRef.current) {
66
+ const width = containerRef.current.offsetWidth
67
+ setContainerWidth(width)
68
+
69
+ // Breakpoint'i manuel olarak belirle
70
+ if (width < 480) {
71
+ setCurrentBreakpoint('xxs')
72
+ } else if (width < 768) {
73
+ setCurrentBreakpoint('xs')
74
+ } else if (width < 996) {
75
+ setCurrentBreakpoint('sm')
76
+ } else if (width < 1200) {
77
+ setCurrentBreakpoint('md')
78
+ } else {
79
+ setCurrentBreakpoint('lg')
80
+ }
81
+ }
82
+ }
83
+
84
+ updateWidth()
85
+ window.addEventListener('resize', updateWidth)
86
+ return () => window.removeEventListener('resize', updateWidth)
87
+ }, [])
88
+
89
+ // Responsive layout oluştur
90
+ const generateResponsiveLayouts = (): Layouts => {
91
+ const baseLayout = widgets.map((widget, index) => ({
61
92
  i: widget.id,
62
- x: widget.position.x,
63
- y: widget.position.y,
64
- w: widget.size.w,
65
- h: widget.size.h,
66
- minW: widget.size.minW || 2,
67
- maxW: widget.size.maxW || 12,
68
- minH: widget.size.minH || 2,
69
- maxH: widget.size.maxH || 8,
93
+ x: widget.position?.x ?? (index * 3) % 12,
94
+ y: widget.position?.y ?? Math.floor((index * 3) / 12) * 3,
95
+ w: widget.size?.w ?? 3,
96
+ h: widget.size?.h ?? 3,
97
+ minW: widget.size?.minW || 2,
98
+ maxW: widget.size?.maxW || 12,
99
+ minH: widget.size?.minH || 2,
100
+ maxH: widget.size?.maxH || 8,
70
101
  isDraggable: editMode && !lockedWidgets.has(widget.id) && widget.permissions?.canMove !== false,
71
102
  isResizable: editMode && !lockedWidgets.has(widget.id) && widget.permissions?.canResize !== false,
72
103
  }))
104
+
105
+ // Farklı breakpoint'ler için layout'ları ayarla
106
+ const sortedLayout = [...baseLayout].sort((a, b) => {
107
+ if (a.y === b.y) return a.x - b.x;
108
+ return a.y - b.y;
109
+ });
110
+
111
+ return {
112
+ lg: baseLayout,
113
+ md: sortedLayout.map((item, index) => {
114
+ const cols = 8;
115
+ const maxW = Math.min(item.w, 4);
116
+ const row = Math.floor(index / 2);
117
+ const col = (index % 2) * 4;
118
+ return {
119
+ ...item,
120
+ w: maxW,
121
+ x: col,
122
+ y: row * 3,
123
+ h: Math.min(item.h, 3)
124
+ };
125
+ }),
126
+ sm: sortedLayout.map((item, index) => {
127
+ const maxW = Math.min(item.w, 4);
128
+ return {
129
+ ...item,
130
+ w: maxW,
131
+ x: 0,
132
+ y: index * 3,
133
+ h: Math.min(item.h, 3)
134
+ };
135
+ }),
136
+ xs: sortedLayout.map((item, index) => ({
137
+ ...item,
138
+ w: 2, // Full width on mobile
139
+ x: 0,
140
+ y: index * 2,
141
+ h: Math.min(item.h, 2)
142
+ })),
143
+ xxs: sortedLayout.map((item, index) => ({
144
+ ...item,
145
+ w: 1, // Full width on extra small
146
+ x: 0,
147
+ y: index * 2,
148
+ h: Math.min(item.h, 2)
149
+ }))
150
+ }
151
+ }
152
+
153
+ // Layout oluştur (geriye uyumluluk için)
154
+ const generateLayout = (): Layout[] => {
155
+ const responsiveLayouts = generateResponsiveLayouts()
156
+ return responsiveLayouts[currentBreakpoint as keyof Layouts] || responsiveLayouts.lg
73
157
  }
74
158
 
75
159
  // Widget kilit durumunu değiştir
@@ -134,6 +218,27 @@ export function DashboardGrid({
134
218
  onAction={(action, data) => onWidgetAction?.(widget.id, action, data)}
135
219
  />
136
220
  )
221
+
222
+ case 'table':
223
+ case 'map':
224
+ case 'calendar':
225
+ case 'progress':
226
+ case 'comparison':
227
+ // Bu widget tipleri için geçici olarak basit bir görünüm
228
+ return (
229
+ <div className={cn(
230
+ "h-full p-4 rounded-lg border",
231
+ glassmorphism ? "bg-background/60 backdrop-blur-md border-white/10" : "bg-card"
232
+ )}>
233
+ <h3 className="font-semibold mb-2">{widget.title}</h3>
234
+ {widget.description && (
235
+ <p className="text-sm text-muted-foreground mb-4">{widget.description}</p>
236
+ )}
237
+ <div className="flex items-center justify-center h-32 text-muted-foreground">
238
+ <span className="text-sm">{widget.type} widget content</span>
239
+ </div>
240
+ </div>
241
+ )
137
242
 
138
243
  default:
139
244
  return (
@@ -248,8 +353,11 @@ export function DashboardGrid({
248
353
  )
249
354
  }
250
355
 
356
+ // Mobile kontrolü
357
+ const isMobile = currentBreakpoint === 'xs' || currentBreakpoint === 'xxs' || currentBreakpoint === 'sm';
358
+
251
359
  return (
252
- <div className={cn("w-full", className)}>
360
+ <div ref={containerRef} className={cn("w-full relative", className)}>
253
361
  <AnimatePresence>
254
362
  {fullscreenWidget ? (
255
363
  // Fullscreen widget
@@ -263,34 +371,61 @@ export function DashboardGrid({
263
371
  .filter(w => w.id === fullscreenWidget)
264
372
  .map(renderWidget)}
265
373
  </motion.div>
374
+ ) : isMobile ? (
375
+ // Mobile layout - Grid Layout yerine normal flex kullan
376
+ <div className="space-y-6">
377
+ {widgets.map(widget => (
378
+ <motion.div
379
+ key={widget.id}
380
+ initial={{ opacity: 0, y: 20 }}
381
+ animate={{ opacity: 1, y: 0 }}
382
+ transition={{ duration: 0.3 }}
383
+ className="w-full"
384
+ >
385
+ {renderWidget(widget)}
386
+ </motion.div>
387
+ ))}
388
+ </div>
266
389
  ) : (
267
- // Grid layout
268
- <GridLayout
390
+ // Desktop Grid layout
391
+ <ResponsiveGridLayout
269
392
  className="layout"
270
- layout={generateLayout()}
271
- cols={cols[currentBreakpoint as keyof typeof cols] || cols.lg}
272
- rowHeight={rowHeight}
273
- width={1200}
274
- margin={margin}
275
- containerPadding={containerPadding}
276
- onLayoutChange={(layout) => {
393
+ layouts={layouts.lg ? layouts : generateResponsiveLayouts()}
394
+ breakpoints={breakpoints}
395
+ cols={cols}
396
+ rowHeight={currentBreakpoint === 'xs' || currentBreakpoint === 'xxs' ? 60 : currentBreakpoint === 'sm' ? 70 : rowHeight}
397
+ margin={currentBreakpoint === 'xs' || currentBreakpoint === 'xxs' ? [12, 20] : margin}
398
+ containerPadding={currentBreakpoint === 'xs' || currentBreakpoint === 'xxs' ? [8, 8] : containerPadding}
399
+ onLayoutChange={(layout, allLayouts) => {
400
+ setLayouts(allLayouts)
277
401
  onLayoutChange?.(layout)
278
402
  }}
279
403
  onBreakpointChange={(breakpoint) => {
280
404
  setCurrentBreakpoint(breakpoint)
405
+ // Dar alanlarda compact type'ı değiştir
406
+ if (breakpoint === 'xs' || breakpoint === 'xxs' || breakpoint === 'sm') {
407
+ setCompactType('vertical')
408
+ } else {
409
+ setCompactType('vertical')
410
+ }
281
411
  }}
282
412
  draggableHandle=".drag-handle"
283
413
  isDraggable={editMode}
284
414
  isResizable={editMode}
285
- compactType="vertical"
415
+ compactType={compactType}
286
416
  preventCollision={false}
417
+ useCSSTransforms={true}
418
+ transformScale={1}
419
+ isDroppable={true}
420
+ autoSize={true}
421
+ verticalCompact={true}
287
422
  >
288
423
  {widgets.map(widget => (
289
424
  <div key={widget.id}>
290
425
  {renderWidget(widget)}
291
426
  </div>
292
427
  ))}
293
- </GridLayout>
428
+ </ResponsiveGridLayout>
294
429
  )}
295
430
  </AnimatePresence>
296
431
 
@@ -3,6 +3,9 @@
3
3
  import React from 'react'
4
4
  import { Dashboard } from './index'
5
5
  import { Widget, MetricData, ChartData, ActivityItem } from './types'
6
+ import { MetricCard } from './widgets/metric-card'
7
+ import { ChartWidget } from './widgets/chart-widget'
8
+ import { ActivityFeed } from './widgets/activity-feed'
6
9
  import {
7
10
  Users,
8
11
  DollarSign,
@@ -259,6 +259,11 @@ export function Dashboard({
259
259
  const [refreshing, setRefreshing] = React.useState(false)
260
260
  const [notifications, setNotifications] = React.useState<number>(3)
261
261
 
262
+ // initialWidgets değiştiğinde state'i güncelle
263
+ React.useEffect(() => {
264
+ setWidgets(initialWidgets)
265
+ }, [initialWidgets])
266
+
262
267
  // WebSocket bağlantısı (real-time için)
263
268
  React.useEffect(() => {
264
269
  if (!realtime) return
@@ -308,7 +313,9 @@ export function Dashboard({
308
313
  const applyTemplate = (template: DashboardTemplate) => {
309
314
  const newWidgets = template.widgets.map((w, index) => ({
310
315
  ...w,
311
- id: `widget-${Date.now()}-${index}`
316
+ id: `widget-${Date.now()}-${index}`,
317
+ position: w.position || { x: (index * 3) % 12, y: Math.floor((index * 3) / 12) * 3 },
318
+ size: w.size || { w: 3, h: 3 }
312
319
  }))
313
320
 
314
321
  setWidgets(newWidgets as Widget[])
@@ -739,4 +746,5 @@ export function Dashboard({
739
746
  )
740
747
  }
741
748
 
749
+ export type { Widget, MetricData, ChartData, ActivityItem, ProgressData, ComparisonData } from './types'
742
750
  export default Dashboard
@@ -160,7 +160,9 @@ export function TimeRangePicker({
160
160
  "w-auto p-0",
161
161
  glassmorphism && "bg-background/95 backdrop-blur-md border-white/10"
162
162
  )}
163
- align="start"
163
+ align="end"
164
+ side="bottom"
165
+ sideOffset={4}
164
166
  >
165
167
  <motion.div
166
168
  initial={{ opacity: 0, y: -10 }}
@@ -120,8 +120,8 @@ export interface Widget {
120
120
  type: WidgetType
121
121
  title: string
122
122
  description?: string
123
- size: WidgetSize
124
- position: WidgetPosition
123
+ size?: WidgetSize
124
+ position?: WidgetPosition
125
125
  data?: any
126
126
  config?: any
127
127
  loading?: boolean
@@ -81,4 +81,7 @@ export * from "./performance-monitor"
81
81
  export * from "./file-upload"
82
82
 
83
83
  // Data Table
84
- export * from "./data-table"
84
+ export * from "./data-table"
85
+
86
+ // Sidebar
87
+ export * from "./sidebar"