@pattern-stack/frontend-patterns 0.0.4 → 0.0.6

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 (86) hide show
  1. package/dist/atoms/composed/SalesPanel/SalesPanel.d.ts +19 -0
  2. package/dist/atoms/composed/SalesPanel/SalesPanel.d.ts.map +1 -0
  3. package/dist/atoms/composed/SalesPanel/index.d.ts +2 -0
  4. package/dist/atoms/composed/SalesPanel/index.d.ts.map +1 -0
  5. package/dist/atoms/composed/SalesPanel/mockSalesData.d.ts +63 -0
  6. package/dist/atoms/composed/SalesPanel/mockSalesData.d.ts.map +1 -0
  7. package/dist/atoms/composed/index.d.ts +1 -0
  8. package/dist/atoms/composed/index.d.ts.map +1 -1
  9. package/dist/atoms/types/entity-config.d.ts +117 -0
  10. package/dist/atoms/types/entity-config.d.ts.map +1 -0
  11. package/dist/atoms/types/index.d.ts +2 -0
  12. package/dist/atoms/types/index.d.ts.map +1 -1
  13. package/dist/atoms/types/navigation.d.ts +30 -0
  14. package/dist/atoms/types/navigation.d.ts.map +1 -0
  15. package/dist/atoms/ui/ErrorBoundary.d.ts +1 -1
  16. package/dist/atoms/ui/button.d.ts +1 -1
  17. package/dist/atoms/utils/icon-resolver.d.ts +72 -0
  18. package/dist/atoms/utils/icon-resolver.d.ts.map +1 -0
  19. package/dist/atoms/utils/metric-engine.d.ts +30 -0
  20. package/dist/atoms/utils/metric-engine.d.ts.map +1 -0
  21. package/dist/atoms/utils/utils.d.ts +2 -0
  22. package/dist/atoms/utils/utils.d.ts.map +1 -1
  23. package/dist/features/auth/components/ProtectedRoute.d.ts +1 -1
  24. package/dist/frontend-patterns.css +1 -1
  25. package/dist/index.es.js +402 -14
  26. package/dist/index.es.js.map +1 -1
  27. package/dist/index.js +402 -14
  28. package/dist/index.js.map +1 -1
  29. package/dist/molecules/layout/DashboardWithSidePanel/DashboardWithSidePanel.d.ts +16 -0
  30. package/dist/molecules/layout/DashboardWithSidePanel/DashboardWithSidePanel.d.ts.map +1 -0
  31. package/dist/molecules/layout/DashboardWithSidePanel/index.d.ts +2 -0
  32. package/dist/molecules/layout/DashboardWithSidePanel/index.d.ts.map +1 -0
  33. package/dist/molecules/layout/NavigationContext.d.ts +15 -0
  34. package/dist/molecules/layout/NavigationContext.d.ts.map +1 -0
  35. package/dist/molecules/layout/Sidebar.d.ts.map +1 -1
  36. package/dist/molecules/layout/SidebarButton/SidebarButton.d.ts +2 -0
  37. package/dist/molecules/layout/SidebarButton/SidebarButton.d.ts.map +1 -1
  38. package/dist/molecules/layout/index.d.ts +3 -0
  39. package/dist/molecules/layout/index.d.ts.map +1 -1
  40. package/dist/templates/factory.d.ts +2 -1
  41. package/dist/templates/factory.d.ts.map +1 -1
  42. package/dist/templates/index.d.ts.map +1 -1
  43. package/package.json +7 -3
  44. package/src/App.tsx +11 -1
  45. package/src/__tests__/atoms/composed/databadge.test.tsx +106 -0
  46. package/src/__tests__/atoms/composed/statcard.test.tsx +133 -0
  47. package/src/__tests__/atoms/utils/icon-resolver.test.tsx +140 -0
  48. package/src/atoms/composed/SalesPanel/SalesPanel.tsx +116 -0
  49. package/src/atoms/composed/SalesPanel/index.ts +1 -0
  50. package/src/atoms/composed/SalesPanel/mockSalesData.ts +151 -0
  51. package/src/atoms/composed/index.ts +1 -0
  52. package/src/atoms/types/entity-config.ts +127 -0
  53. package/src/atoms/types/index.ts +3 -1
  54. package/src/atoms/types/navigation.ts +43 -0
  55. package/src/atoms/utils/icon-resolver.tsx +54 -0
  56. package/src/atoms/utils/metric-engine.ts +236 -0
  57. package/src/atoms/utils/utils.ts +4 -2
  58. package/src/molecules/layout/DashboardWithSidePanel/DashboardWithSidePanel.tsx +42 -0
  59. package/src/molecules/layout/DashboardWithSidePanel/index.ts +1 -0
  60. package/src/molecules/layout/NavigationContext.tsx +63 -0
  61. package/src/molecules/layout/Sidebar.tsx +10 -23
  62. package/src/molecules/layout/SidebarButton/SidebarButton.tsx +32 -10
  63. package/src/molecules/layout/index.ts +4 -1
  64. package/src/organisms/entity/CategoryBreakdownPanel.tsx +427 -0
  65. package/src/organisms/entity/EntityListPanel.tsx +339 -0
  66. package/src/organisms/entity/MetricsOverviewPanel.tsx +236 -0
  67. package/src/organisms/entity/TrendAnalysisPanel.tsx +337 -0
  68. package/src/organisms/entity/index.ts +4 -0
  69. package/src/organisms/index.ts +5 -1
  70. package/src/pages/AdminShowcase/AdminDashboardShowcase.tsx +77 -75
  71. package/src/pages/AdminShowcase/SalesPerformanceDashboard.tsx +158 -0
  72. package/src/pages/AdminShowcase/index.tsx +2 -1
  73. package/src/pages/EntityShowcase/EntityManagementShowcase.tsx +137 -0
  74. package/src/pages/EntityShowcase/EntityPerformanceShowcase.tsx +117 -0
  75. package/src/pages/EntityShowcase/index.ts +2 -0
  76. package/src/pages/EntityTemplateExample.tsx +229 -0
  77. package/src/pages/TestEntityTemplate.tsx +40 -0
  78. package/src/pages/index.ts +2 -1
  79. package/src/templates/entity/EntityManagementTemplate.tsx +430 -0
  80. package/src/templates/entity/EntityPerformanceDashboardTemplate.tsx +277 -0
  81. package/src/templates/entity/configs/financial-config.ts +141 -0
  82. package/src/templates/entity/configs/index.ts +1 -0
  83. package/src/templates/entity/index.ts +3 -0
  84. package/src/templates/factory.tsx +14 -7
  85. package/src/templates/financial/FinancialDashboardTemplate.tsx +326 -0
  86. package/src/templates/index.ts +4 -0
package/dist/index.es.js CHANGED
@@ -6,19 +6,18 @@ import { clsx } from "clsx";
6
6
  import { twMerge } from "tailwind-merge";
7
7
  import * as React from "react";
8
8
  import React__default, { useRef, useState, useEffect, Component, createContext, useContext, useMemo, useId, useCallback } from "react";
9
+ import { jsx, jsxs, Fragment } from "react/jsx-runtime";
10
+ import { Menu, HelpCircle, Info, AlertCircle, Check, ArrowDown, ArrowUp, ArrowLeft, ArrowRight, ChevronUp, ChevronLeft, ChevronDown, ChevronRight, Music, Video, Image, Folder, File, Flag, Tag, Bookmark, Heart, Star, MapPin, Clock, Calendar, Phone, Mail, Unlock, Lock, Share, Upload, Download, Eye, Trash2, Edit, Plus, Search, Bell, Settings, Home, Layout, TrendingUp, Database, BarChart3, Users, Shield, X, Palette, Circle, Loader2, Target, ExternalLink, TrendingDown, Minus, FileX, Sparkles, User, Sun, Moon, UserCircle, LogOut, ChevronsUpDown, AreaChart, LineChart, CheckCircle, AlertTriangle, Square, Waves, Zap, TreePine, Sunset, Building2, DollarSign, ShoppingCart, MoreHorizontal, Filter, Activity, RefreshCw, FileText, History, Save, Copy, Grid3X3, Layers, XCircle } from "lucide-react";
9
11
  import { cva } from "class-variance-authority";
10
12
  import axios from "axios";
11
13
  import { useQuery, useQueryClient, useMutation, QueryClient, QueryClientProvider } from "@tanstack/react-query";
12
- import { jsxs, jsx, Fragment } from "react/jsx-runtime";
13
14
  import { Slot } from "@radix-ui/react-slot";
14
15
  import * as LabelPrimitive from "@radix-ui/react-label";
15
16
  import * as AvatarPrimitive from "@radix-ui/react-avatar";
16
17
  import * as DropdownMenuPrimitive from "@radix-ui/react-dropdown-menu";
17
- import { ChevronRight, Check, Circle, Loader2, ArrowRight, TrendingUp, TrendingDown, Minus, FileX, AlertCircle, Search, Database, Sparkles, Mail, Lock, Shield, User, Sun, Moon, UserCircle, Settings, LogOut, X, ChevronsUpDown, ChevronUp, ChevronDown, ChevronLeft, Clock, Calendar, BarChart3, AreaChart, LineChart, Upload, Image, File, CheckCircle, Info, AlertTriangle, Home, Palette, Square, Waves, Zap, TreePine, Sunset, Building2, Users, DollarSign, ShoppingCart, Menu, MoreHorizontal, Plus, Filter, Download, Activity, RefreshCw, Eye, Edit, Trash2, FileText, History, ArrowLeft, Save, Copy, ExternalLink, Grid3X3, Layers, XCircle } from "lucide-react";
18
18
  import { createPortal } from "react-dom";
19
19
  import { useLocation, useNavigate, useSearchParams, Outlet, BrowserRouter, Routes, Route } from "react-router-dom";
20
20
  import { createRoot } from "react-dom/client";
21
- import "@tanstack/react-query-devtools";
22
21
  const APP_NAME = "Design System Showcase";
23
22
  const API_ENDPOINTS = {
24
23
  HEALTH: "/health"
@@ -244,6 +243,240 @@ const tooltipContent = {
244
243
  profile: "Profile",
245
244
  account: "Account settings"
246
245
  };
246
+ class MetricCalculationEngine {
247
+ static calculateMetric(config, data, previousData) {
248
+ const currentValue = this.aggregateValue(config, data);
249
+ const previousValue = previousData ? this.aggregateValue(config, previousData) : void 0;
250
+ const trend = this.calculateTrend(currentValue, previousValue);
251
+ const formattedValue = this.formatValue(currentValue, config.format, config.type);
252
+ const target = typeof config.target === "function" ? config.target(data) : config.target;
253
+ return {
254
+ current: currentValue,
255
+ previous: previousValue,
256
+ trend,
257
+ target,
258
+ formattedValue
259
+ };
260
+ }
261
+ static aggregateValue(config, data) {
262
+ if (!data.length) return 0;
263
+ const values = data.map((item) => {
264
+ const value = this.extractValue(item, config.key);
265
+ return typeof value === "number" ? value : 0;
266
+ }).filter((value) => !isNaN(value));
267
+ if (!values.length) return 0;
268
+ switch (config.aggregation || "sum") {
269
+ case "sum":
270
+ return values.reduce((sum, value) => sum + value, 0);
271
+ case "avg":
272
+ return values.reduce((sum, value) => sum + value, 0) / values.length;
273
+ case "count":
274
+ return values.length;
275
+ case "min":
276
+ return Math.min(...values);
277
+ case "max":
278
+ return Math.max(...values);
279
+ default:
280
+ return values.reduce((sum, value) => sum + value, 0);
281
+ }
282
+ }
283
+ static extractValue(item, key) {
284
+ return key.split(".").reduce((obj, k) => obj == null ? void 0 : obj[k], item);
285
+ }
286
+ static calculateTrend(current, previous) {
287
+ if (previous === void 0 || previous === 0) return "neutral";
288
+ const change = (current - previous) / Math.abs(previous) * 100;
289
+ if (change > 1) return "up";
290
+ if (change < -1) return "down";
291
+ return "neutral";
292
+ }
293
+ static formatValue(value, format, type) {
294
+ let formatted = value;
295
+ if ((format == null ? void 0 : format.decimals) !== void 0) {
296
+ formatted = Number(value.toFixed(format.decimals));
297
+ }
298
+ let result = formatted.toString();
299
+ if ((format == null ? void 0 : format.thousands) !== false && Math.abs(formatted) >= 1e3) {
300
+ result = formatted.toLocaleString();
301
+ }
302
+ switch (type) {
303
+ case "currency":
304
+ result = new Intl.NumberFormat("en-US", {
305
+ style: "currency",
306
+ currency: "USD",
307
+ minimumFractionDigits: (format == null ? void 0 : format.decimals) ?? 2,
308
+ maximumFractionDigits: (format == null ? void 0 : format.decimals) ?? 2
309
+ }).format(formatted);
310
+ break;
311
+ case "percentage":
312
+ result = `${formatted.toFixed((format == null ? void 0 : format.decimals) ?? 1)}%`;
313
+ break;
314
+ case "duration":
315
+ result = this.formatDuration(formatted);
316
+ break;
317
+ case "ratio":
318
+ result = `${formatted.toFixed((format == null ? void 0 : format.decimals) ?? 2)}:1`;
319
+ break;
320
+ default:
321
+ if (format == null ? void 0 : format.prefix) result = format.prefix + result;
322
+ if (format == null ? void 0 : format.suffix) result = result + format.suffix;
323
+ }
324
+ return result;
325
+ }
326
+ static formatDuration(minutes) {
327
+ const hours = Math.floor(minutes / 60);
328
+ const mins = Math.floor(minutes % 60);
329
+ if (hours > 0) {
330
+ return `${hours}h ${mins}m`;
331
+ }
332
+ return `${mins}m`;
333
+ }
334
+ static calculateTrendData(config, data, dateField = "date", periods = 12) {
335
+ const groupedData = this.groupByPeriod(data, dateField);
336
+ const sortedDates = Object.keys(groupedData).sort();
337
+ return sortedDates.slice(-periods).map((date) => ({
338
+ date,
339
+ value: this.aggregateValue(config, groupedData[date]),
340
+ label: this.formatDateLabel(date)
341
+ }));
342
+ }
343
+ static groupByPeriod(data, dateField) {
344
+ return data.reduce((groups, item) => {
345
+ const date = this.extractValue(item, dateField);
346
+ if (!date) return groups;
347
+ const period = new Date(date).toISOString().split("T")[0];
348
+ if (!groups[period]) groups[period] = [];
349
+ groups[period].push(item);
350
+ return groups;
351
+ }, {});
352
+ }
353
+ static formatDateLabel(dateString) {
354
+ const date = new Date(dateString);
355
+ return date.toLocaleDateString("en-US", {
356
+ month: "short",
357
+ day: "numeric"
358
+ });
359
+ }
360
+ static calculateCategoryBreakdown(data, categoryField, valueField, maxCategories = 8) {
361
+ const groups = data.reduce((acc, item) => {
362
+ const category = String(this.extractValue(item, categoryField) || "Unknown");
363
+ const value = this.extractValue(item, valueField) || 0;
364
+ if (!acc[category]) acc[category] = 0;
365
+ acc[category] += typeof value === "number" ? value : 0;
366
+ return acc;
367
+ }, {});
368
+ const total = Object.values(groups).reduce((sum, value) => sum + value, 0);
369
+ let categories = Object.entries(groups).map(([category, value]) => ({
370
+ category,
371
+ value,
372
+ percentage: total > 0 ? value / total * 100 : 0
373
+ })).sort((a, b) => b.value - a.value);
374
+ if (categories.length > maxCategories) {
375
+ const topCategories = categories.slice(0, maxCategories - 1);
376
+ const otherValue = categories.slice(maxCategories - 1).reduce((sum, cat) => sum + cat.value, 0);
377
+ topCategories.push({
378
+ category: "Other",
379
+ value: otherValue,
380
+ percentage: total > 0 ? otherValue / total * 100 : 0
381
+ });
382
+ categories = topCategories;
383
+ }
384
+ return categories;
385
+ }
386
+ static detectInsights(metrics, thresholds = {}) {
387
+ const insights = [];
388
+ for (const [key, metric] of Object.entries(metrics)) {
389
+ const threshold = thresholds[key];
390
+ if (metric.target && metric.current < metric.target * 0.8) {
391
+ insights.push({
392
+ type: "negative",
393
+ message: `${key} is significantly below target`,
394
+ value: metric.current
395
+ });
396
+ }
397
+ if (metric.trend === "up" && metric.previous && metric.current > metric.previous * 1.2) {
398
+ insights.push({
399
+ type: "positive",
400
+ message: `${key} showing strong growth`,
401
+ value: metric.current
402
+ });
403
+ }
404
+ if (threshold && metric.current >= threshold.critical) {
405
+ insights.push({
406
+ type: "negative",
407
+ message: `${key} has reached critical threshold`,
408
+ value: metric.current
409
+ });
410
+ }
411
+ }
412
+ return insights.slice(0, 5);
413
+ }
414
+ }
415
+ const iconMap = {
416
+ Palette,
417
+ Menu,
418
+ X,
419
+ Shield,
420
+ Users,
421
+ BarChart3,
422
+ Database,
423
+ TrendingUp,
424
+ Layout,
425
+ Home,
426
+ Settings,
427
+ Bell,
428
+ Search,
429
+ Plus,
430
+ Edit,
431
+ Trash2,
432
+ Eye,
433
+ Download,
434
+ Upload,
435
+ Share,
436
+ Lock,
437
+ Unlock,
438
+ Mail,
439
+ Phone,
440
+ Calendar,
441
+ Clock,
442
+ MapPin,
443
+ Star,
444
+ Heart,
445
+ Bookmark,
446
+ Tag,
447
+ Flag,
448
+ File,
449
+ Folder,
450
+ Image,
451
+ Video,
452
+ Music,
453
+ ChevronRight,
454
+ ChevronDown,
455
+ ChevronLeft,
456
+ ChevronUp,
457
+ ArrowRight,
458
+ ArrowLeft,
459
+ ArrowUp,
460
+ ArrowDown,
461
+ Check,
462
+ AlertCircle,
463
+ Info,
464
+ HelpCircle
465
+ };
466
+ const Icon = ({ name, className = "w-5 h-5", size, ...props }) => {
467
+ const IconComponent = iconMap[name];
468
+ if (!IconComponent) {
469
+ console.warn(`Icon "${name}" not found. Using default Menu icon.`);
470
+ return /* @__PURE__ */ jsx(Menu, { className, size, ...props });
471
+ }
472
+ return /* @__PURE__ */ jsx(IconComponent, { className, size, ...props });
473
+ };
474
+ const getIcon = (name) => {
475
+ return iconMap[name] || Menu;
476
+ };
477
+ const isValidIcon = (name) => {
478
+ return name in iconMap;
479
+ };
247
480
  function cn(...inputs) {
248
481
  return twMerge(clsx(inputs));
249
482
  }
@@ -1265,6 +1498,83 @@ const DataBadge = ({
1265
1498
  }
1266
1499
  return badge;
1267
1500
  };
1501
+ const getStageStatus = (stage) => {
1502
+ switch (stage) {
1503
+ case "Closed Won":
1504
+ return "success";
1505
+ case "Negotiation":
1506
+ return "warning";
1507
+ case "Proposal Sent":
1508
+ return "info";
1509
+ case "Qualified":
1510
+ return "info";
1511
+ case "Discovery":
1512
+ return "neutral";
1513
+ default:
1514
+ return "neutral";
1515
+ }
1516
+ };
1517
+ const SalesPanel = ({
1518
+ sales,
1519
+ onSaleClick,
1520
+ onClose
1521
+ }) => {
1522
+ const topDeals = sales.slice(0, 5);
1523
+ const totalValue = sales.reduce((sum, sale) => sum + sale.amount, 0);
1524
+ return /* @__PURE__ */ jsxs("div", { className: "fixed right-0 top-16 h-[calc(100vh-4rem)] w-72 bg-background border-l border-border shadow-lg flex flex-col z-30", children: [
1525
+ /* @__PURE__ */ jsx("div", { className: "p-3 border-b border-border", children: /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between", children: [
1526
+ /* @__PURE__ */ jsxs("h3", { className: "font-medium flex items-center gap-2", children: [
1527
+ /* @__PURE__ */ jsx(Target, { className: "w-4 h-4" }),
1528
+ "Pipeline"
1529
+ ] }),
1530
+ onClose && /* @__PURE__ */ jsx(Button, { variant: "ghost", size: "sm", onClick: onClose, children: "×" })
1531
+ ] }) }),
1532
+ /* @__PURE__ */ jsx("div", { className: "p-3 border-b border-border", children: /* @__PURE__ */ jsxs("div", { className: "space-y-2", children: [
1533
+ /* @__PURE__ */ jsxs("div", { className: "flex justify-between", children: [
1534
+ /* @__PURE__ */ jsx("span", { className: "text-sm text-muted-foreground", children: "Total Value" }),
1535
+ /* @__PURE__ */ jsxs("span", { className: "font-semibold text-green-600", children: [
1536
+ "$",
1537
+ totalValue.toLocaleString()
1538
+ ] })
1539
+ ] }),
1540
+ /* @__PURE__ */ jsxs("div", { className: "flex justify-between", children: [
1541
+ /* @__PURE__ */ jsx("span", { className: "text-sm text-muted-foreground", children: "Active Deals" }),
1542
+ /* @__PURE__ */ jsx("span", { className: "font-semibold", children: sales.length })
1543
+ ] })
1544
+ ] }) }),
1545
+ /* @__PURE__ */ jsxs("div", { className: "flex-1 overflow-auto p-3", children: [
1546
+ /* @__PURE__ */ jsx("h4", { className: "text-sm font-medium mb-3", children: "Recent Opportunities" }),
1547
+ /* @__PURE__ */ jsx("div", { className: "space-y-2", children: topDeals.map((sale) => /* @__PURE__ */ jsxs(
1548
+ "div",
1549
+ {
1550
+ className: "p-2 border border-border rounded-md hover:bg-muted/50 cursor-pointer transition-colors",
1551
+ onClick: () => onSaleClick == null ? void 0 : onSaleClick(sale),
1552
+ children: [
1553
+ /* @__PURE__ */ jsxs("div", { className: "flex justify-between items-start mb-1", children: [
1554
+ /* @__PURE__ */ jsxs("div", { className: "flex-1 min-w-0", children: [
1555
+ /* @__PURE__ */ jsx("p", { className: "text-sm font-medium truncate", children: sale.customer }),
1556
+ /* @__PURE__ */ jsx("p", { className: "text-xs text-muted-foreground truncate", children: sale.product })
1557
+ ] }),
1558
+ /* @__PURE__ */ jsx("div", { className: "text-right ml-2", children: /* @__PURE__ */ jsxs("p", { className: "text-sm font-semibold text-green-600", children: [
1559
+ "$",
1560
+ sale.amount.toLocaleString()
1561
+ ] }) })
1562
+ ] }),
1563
+ /* @__PURE__ */ jsxs("div", { className: "flex justify-between items-center", children: [
1564
+ /* @__PURE__ */ jsx(DataBadge, { variant: "status", status: getStageStatus(sale.stage), children: sale.stage }),
1565
+ /* @__PURE__ */ jsx("span", { className: "text-xs text-muted-foreground", children: sale.salesperson })
1566
+ ] })
1567
+ ]
1568
+ },
1569
+ sale.id
1570
+ )) })
1571
+ ] }),
1572
+ /* @__PURE__ */ jsx("div", { className: "p-3 border-t border-border", children: /* @__PURE__ */ jsxs(Button, { variant: "outline", size: "sm", className: "w-full", children: [
1573
+ /* @__PURE__ */ jsx(ExternalLink, { className: "w-4 h-4 mr-2" }),
1574
+ "View All Deals"
1575
+ ] }) })
1576
+ ] });
1577
+ };
1268
1578
  const StatCard = ({
1269
1579
  title,
1270
1580
  value,
@@ -5529,6 +5839,42 @@ const useSidebar = () => {
5529
5839
  }
5530
5840
  return context;
5531
5841
  };
5842
+ const NavigationContext = createContext(void 0);
5843
+ const defaultShowcaseNavigation = [
5844
+ { value: "showcase", label: "Showcase", icon: "Palette", path: "/showcase", category: 5 },
5845
+ { value: "admin-dashboard", label: "Admin Dashboard", icon: "Shield", path: "/admin/dashboard", category: 2 },
5846
+ { value: "admin-users", label: "User Management", icon: "Users", path: "/admin/users", category: 3 },
5847
+ { value: "admin-sales", label: "Sales Dashboard", icon: "TrendingUp", path: "/admin/sales", category: 4 },
5848
+ { value: "entity-performance", label: "Performance Dashboard", icon: "BarChart3", path: "/entity/performance", category: 6 },
5849
+ { value: "entity-management", label: "Entity Management", icon: "Database", path: "/entity/management", category: 7 },
5850
+ { value: "entity-template", label: "Template Example", icon: "Layout", path: "/entity/template-example", category: 1 }
5851
+ ];
5852
+ const NavigationProvider = ({ children, initialNavigation }) => {
5853
+ const [navigation, setNavigation] = React__default.useState(
5854
+ initialNavigation || {
5855
+ items: defaultShowcaseNavigation,
5856
+ showDefaultNavigation: true,
5857
+ defaultExpanded: true
5858
+ }
5859
+ );
5860
+ return /* @__PURE__ */ jsx(NavigationContext.Provider, { value: { navigation, setNavigation }, children });
5861
+ };
5862
+ const useNavigation = () => {
5863
+ const context = useContext(NavigationContext);
5864
+ if (context === void 0) {
5865
+ throw new Error("useNavigation must be used within a NavigationProvider");
5866
+ }
5867
+ return context;
5868
+ };
5869
+ const getNavigationItems = (config) => {
5870
+ if (config.items.length > 0) {
5871
+ return config.items;
5872
+ }
5873
+ if (config.showDefaultNavigation !== false) {
5874
+ return defaultShowcaseNavigation;
5875
+ }
5876
+ return [];
5877
+ };
5532
5878
  const SidebarButton = ({
5533
5879
  icon,
5534
5880
  label,
@@ -5536,13 +5882,16 @@ const SidebarButton = ({
5536
5882
  category = 1,
5537
5883
  expanded = false,
5538
5884
  onClick,
5539
- className
5885
+ className,
5886
+ badge,
5887
+ disabled = false
5540
5888
  }) => {
5541
5889
  return /* @__PURE__ */ jsxs(
5542
5890
  Button,
5543
5891
  {
5544
5892
  variant: active ? "secondary" : "ghost",
5545
5893
  onClick,
5894
+ disabled,
5546
5895
  tooltip: !expanded ? label : void 0,
5547
5896
  className: cn(
5548
5897
  "relative w-full justify-start gap-3 h-12",
@@ -5576,12 +5925,19 @@ const SidebarButton = ({
5576
5925
  "text-sm font-medium flex-1 text-left",
5577
5926
  active ? `text-category-${category}` : "text-foreground"
5578
5927
  ), children: label }),
5579
- active && /* @__PURE__ */ jsx("div", { className: cn(
5928
+ badge ? /* @__PURE__ */ jsx("span", { className: cn(
5929
+ "px-2 py-0.5 text-xs font-medium rounded-full flex-shrink-0",
5930
+ "bg-primary/10 text-primary"
5931
+ ), children: badge }) : active && /* @__PURE__ */ jsx("div", { className: cn(
5580
5932
  "w-2 h-2 rounded-full flex-shrink-0",
5581
5933
  `bg-category-${category}`
5582
5934
  ) })
5583
5935
  ] }),
5584
- !expanded && active && /* @__PURE__ */ jsx("div", { className: "absolute -top-1 -right-1", children: /* @__PURE__ */ jsx("div", { className: cn(
5936
+ !expanded && (badge || active) && /* @__PURE__ */ jsx("div", { className: "absolute -top-1 -right-1", children: badge ? /* @__PURE__ */ jsx("span", { className: cn(
5937
+ "px-1.5 py-0.5 text-xs font-bold rounded-full",
5938
+ "bg-primary text-primary-foreground",
5939
+ "ring-2 ring-background"
5940
+ ), children: badge }) : active && /* @__PURE__ */ jsx("div", { className: cn(
5585
5941
  "w-2.5 h-2.5 rounded-full",
5586
5942
  `bg-category-${category}`,
5587
5943
  "ring-2 ring-background"
@@ -5592,14 +5948,11 @@ const SidebarButton = ({
5592
5948
  };
5593
5949
  const Sidebar = ({ className }) => {
5594
5950
  const { isExpanded, toggleSidebar } = useSidebar();
5951
+ const { navigation } = useNavigation();
5595
5952
  const location = useLocation();
5596
5953
  const navigate = useNavigate();
5597
5954
  const [searchParams] = useSearchParams();
5598
- const items = [
5599
- { value: "showcase", label: "Showcase", icon: /* @__PURE__ */ jsx(Palette, { className: "w-5 h-5" }), path: "/showcase", category: 5 },
5600
- { value: "admin-dashboard", label: "Admin Dashboard", icon: /* @__PURE__ */ jsx(Shield, { className: "w-5 h-5" }), path: "/admin/dashboard", category: 2 },
5601
- { value: "admin-users", label: "User Management", icon: /* @__PURE__ */ jsx(Users, { className: "w-5 h-5" }), path: "/admin/users", category: 3 }
5602
- ];
5955
+ const items = getNavigationItems(navigation);
5603
5956
  const handleNavigation = (path) => {
5604
5957
  if (path.includes("?")) {
5605
5958
  const [basePath, query] = path.split("?");
@@ -5655,12 +6008,14 @@ const Sidebar = ({ className }) => {
5655
6008
  return /* @__PURE__ */ jsx(
5656
6009
  SidebarButton,
5657
6010
  {
5658
- icon: item.icon,
6011
+ icon: /* @__PURE__ */ jsx(Icon, { name: item.icon, className: "w-5 h-5" }),
5659
6012
  label: item.label,
5660
6013
  active: isActive,
5661
6014
  category: item.category,
5662
6015
  expanded: isExpanded,
5663
- onClick: () => handleNavigation(item.path)
6016
+ onClick: () => handleNavigation(item.path),
6017
+ badge: item.badge,
6018
+ disabled: item.disabled
5664
6019
  },
5665
6020
  item.value
5666
6021
  );
@@ -5726,6 +6081,28 @@ const AppLayout = () => {
5726
6081
  )
5727
6082
  ] });
5728
6083
  };
6084
+ const DashboardWithSidePanel = ({
6085
+ children,
6086
+ sidePanel,
6087
+ showSidePanel = false,
6088
+ sidePanelWidth = 72,
6089
+ className
6090
+ }) => {
6091
+ const marginClass = `pr-${sidePanelWidth}`;
6092
+ return /* @__PURE__ */ jsxs("div", { className: cn("relative h-full", className), children: [
6093
+ /* @__PURE__ */ jsx(
6094
+ "div",
6095
+ {
6096
+ className: cn(
6097
+ "transition-all duration-300",
6098
+ showSidePanel ? marginClass : ""
6099
+ ),
6100
+ children
6101
+ }
6102
+ ),
6103
+ showSidePanel && sidePanel
6104
+ ] });
6105
+ };
5729
6106
  const SectionHeader = ({
5730
6107
  title,
5731
6108
  description,
@@ -7748,6 +8125,7 @@ function createReactApp(config) {
7748
8125
  enableQuery = true,
7749
8126
  enableRouting = true,
7750
8127
  auth,
8128
+ navigation,
7751
8129
  customProviders = []
7752
8130
  } = appConfig;
7753
8131
  const queryClient = new QueryClient({
@@ -7782,7 +8160,7 @@ function createReactApp(config) {
7782
8160
  tree = /* @__PURE__ */ jsx(Provider, { children: tree }, Provider.name);
7783
8161
  });
7784
8162
  if (enableRouting) {
7785
- tree = /* @__PURE__ */ jsx(SidebarProvider, { children: tree });
8163
+ tree = /* @__PURE__ */ jsx(NavigationProvider, { initialNavigation: navigation, children: /* @__PURE__ */ jsx(SidebarProvider, { children: tree }) });
7786
8164
  }
7787
8165
  if (enableAuth) {
7788
8166
  tree = /* @__PURE__ */ jsx(AuthProvider, { config: auth, children: tree });
@@ -10049,6 +10427,7 @@ export {
10049
10427
  DashboardCard,
10050
10428
  DashboardGrid,
10051
10429
  DashboardTemplate,
10430
+ DashboardWithSidePanel,
10052
10431
  DataBadge,
10053
10432
  DataDetailTemplate,
10054
10433
  DataTable,
@@ -10076,14 +10455,17 @@ export {
10076
10455
  FormField,
10077
10456
  FormGroup,
10078
10457
  GlobalSearch,
10458
+ Icon,
10079
10459
  IconBadge,
10080
10460
  Input,
10081
10461
  Label,
10082
10462
  Loading,
10083
10463
  LoginForm,
10084
10464
  LogoutButton,
10465
+ MetricCalculationEngine,
10085
10466
  Modal,
10086
10467
  NavMenu,
10468
+ NavigationProvider,
10087
10469
  PageTemplate,
10088
10470
  Pagination,
10089
10471
  PaletteSwitcher,
@@ -10091,6 +10473,7 @@ export {
10091
10473
  ProtectedRoute,
10092
10474
  RESPONSIVE_CHART_HEIGHTS,
10093
10475
  ROUTES,
10476
+ SalesPanel,
10094
10477
  SearchInput,
10095
10478
  SectionHeader,
10096
10479
  Select,
@@ -10099,6 +10482,7 @@ export {
10099
10482
  SelectTrigger,
10100
10483
  SelectValue,
10101
10484
  ShowcaseSection,
10485
+ Sidebar,
10102
10486
  SidebarButton,
10103
10487
  SidebarProvider,
10104
10488
  Skeleton,
@@ -10134,7 +10518,10 @@ export {
10134
10518
  getAnimationClasses,
10135
10519
  getChartHeight,
10136
10520
  getContainerHeightClass,
10521
+ getIcon,
10522
+ getNavigationItems,
10137
10523
  interactionVariants,
10524
+ isValidIcon,
10138
10525
  legacyPatterns,
10139
10526
  setGlobalAuthService,
10140
10527
  tooltipContent,
@@ -10144,6 +10531,7 @@ export {
10144
10531
  useCreateExample,
10145
10532
  useDeleteExample,
10146
10533
  useGetExample,
10534
+ useNavigation,
10147
10535
  usePermissions,
10148
10536
  useSidebar,
10149
10537
  useTextOverflow,