braid-ui 1.0.99 → 1.0.101

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 (145) hide show
  1. package/README.md +327 -44
  2. package/dist/css/braid-ui-variables.css +88 -0
  3. package/dist/css/braid-ui.css +4702 -0
  4. package/dist/css/braid-ui.min.css +1 -0
  5. package/dist/index.cjs +4 -0
  6. package/dist/index.cjs.map +1 -0
  7. package/dist/index.d.cts +2027 -0
  8. package/dist/index.d.ts +2027 -0
  9. package/dist/index.js +4 -0
  10. package/dist/index.js.map +1 -0
  11. package/package.json +115 -55
  12. package/src/styles-only.css +121 -0
  13. package/src/{index.css → styles.css} +4 -10
  14. package/components.json +0 -20
  15. package/eslint.config.js +0 -29
  16. package/index.html +0 -24
  17. package/postcss.config.js +0 -6
  18. package/public/favicon.ico +0 -0
  19. package/public/placeholder.svg +0 -1
  20. package/public/robots.txt +0 -14
  21. package/src/App.css +0 -42
  22. package/src/App.tsx +0 -94
  23. package/src/components/MainLayout.tsx +0 -15
  24. package/src/components/alerts/AlertDocuments.tsx +0 -320
  25. package/src/components/alerts/AlertNotes.tsx +0 -185
  26. package/src/components/alerts/AlertTimeline.tsx +0 -79
  27. package/src/components/alerts/ContextSection.tsx +0 -155
  28. package/src/components/app-sidebar.tsx +0 -341
  29. package/src/components/form-sections/ACHBankCard.tsx +0 -78
  30. package/src/components/form-sections/ACHBasicInfoCard.tsx +0 -100
  31. package/src/components/form-sections/ACHTransferSection.tsx +0 -64
  32. package/src/components/form-sections/AddressForm.tsx +0 -94
  33. package/src/components/form-sections/BankAddressCard.tsx +0 -95
  34. package/src/components/form-sections/BankingDetailsCard.tsx +0 -46
  35. package/src/components/form-sections/BasicInfoCard.tsx +0 -103
  36. package/src/components/form-sections/BasicInfoSection.tsx +0 -34
  37. package/src/components/form-sections/BeneficiaryAddress.tsx +0 -19
  38. package/src/components/form-sections/BeneficiaryCard.tsx +0 -41
  39. package/src/components/form-sections/BeneficiaryDomesticWire.tsx +0 -23
  40. package/src/components/form-sections/BusinessProfileCard.tsx +0 -131
  41. package/src/components/form-sections/BusinessStatusCard.tsx +0 -53
  42. package/src/components/form-sections/ContactInfoCard.tsx +0 -63
  43. package/src/components/form-sections/CounterpartyBasicInfo.tsx +0 -101
  44. package/src/components/form-sections/CounterpartyProfileCard.tsx +0 -104
  45. package/src/components/form-sections/CounterpartyRecordsCard.tsx +0 -41
  46. package/src/components/form-sections/IntermediaryCard.tsx +0 -77
  47. package/src/components/form-sections/IntermediaryFI.tsx +0 -41
  48. package/src/components/form-sections/IntermediaryFIAddress.tsx +0 -14
  49. package/src/components/form-sections/OriginatorCard.tsx +0 -49
  50. package/src/components/form-sections/OriginatorFI.tsx +0 -42
  51. package/src/components/form-sections/OriginatorFIAddress.tsx +0 -14
  52. package/src/components/form-sections/PaymentInformationSection.tsx +0 -163
  53. package/src/components/form-sections/ReceiverCard.tsx +0 -94
  54. package/src/components/form-sections/WireTransferSection.tsx +0 -75
  55. package/src/components/layouts/list-page.tsx +0 -103
  56. package/src/components/transaction/ACHDetailsSection.tsx +0 -95
  57. package/src/components/transaction/WireDetailsSection.tsx +0 -112
  58. package/src/components/ui/account-card.tsx +0 -94
  59. package/src/components/ui/badge.tsx +0 -75
  60. package/src/components/ui/breadcrumb.tsx +0 -78
  61. package/src/components/ui/business-type-badge.tsx +0 -42
  62. package/src/components/ui/button.tsx +0 -56
  63. package/src/components/ui/calendar.tsx +0 -49
  64. package/src/components/ui/card.tsx +0 -223
  65. package/src/components/ui/container.tsx +0 -45
  66. package/src/components/ui/counterparty-type-badge.tsx +0 -53
  67. package/src/components/ui/data-grid.tsx +0 -99
  68. package/src/components/ui/data-table.tsx +0 -152
  69. package/src/components/ui/detail-page-layout.tsx +0 -83
  70. package/src/components/ui/dialog.tsx +0 -120
  71. package/src/components/ui/dropdown-menu.tsx +0 -82
  72. package/src/components/ui/editable-form-card.tsx +0 -106
  73. package/src/components/ui/editable-info-field.tsx +0 -67
  74. package/src/components/ui/enhanced-input.tsx +0 -78
  75. package/src/components/ui/enhanced-select.tsx +0 -101
  76. package/src/components/ui/enhanced-textarea.tsx +0 -64
  77. package/src/components/ui/entity-card.tsx +0 -140
  78. package/src/components/ui/form-card.tsx +0 -40
  79. package/src/components/ui/form-field.tsx +0 -50
  80. package/src/components/ui/form-input.tsx +0 -29
  81. package/src/components/ui/form-provider.tsx +0 -18
  82. package/src/components/ui/form-section.tsx +0 -66
  83. package/src/components/ui/form-select.tsx +0 -35
  84. package/src/components/ui/info-field.tsx +0 -36
  85. package/src/components/ui/json-viewer.tsx +0 -146
  86. package/src/components/ui/label.tsx +0 -24
  87. package/src/components/ui/metric-card.tsx +0 -80
  88. package/src/components/ui/page-layout.tsx +0 -183
  89. package/src/components/ui/popover.tsx +0 -29
  90. package/src/components/ui/responsive-grid.tsx +0 -46
  91. package/src/components/ui/separator.tsx +0 -31
  92. package/src/components/ui/sheet.tsx +0 -140
  93. package/src/components/ui/sidebar.tsx +0 -775
  94. package/src/components/ui/sonner.tsx +0 -29
  95. package/src/components/ui/stack.tsx +0 -77
  96. package/src/components/ui/status-badge.tsx +0 -68
  97. package/src/components/ui/tabs.tsx +0 -52
  98. package/src/components/ui/toast.tsx +0 -127
  99. package/src/components/ui/toaster.tsx +0 -33
  100. package/src/components/ui/tooltip.tsx +0 -28
  101. package/src/components/ui/use-toast.ts +0 -3
  102. package/src/components/ui-kit/dashboard-demo.tsx +0 -156
  103. package/src/components/ui-kit/pattern-library.tsx +0 -248
  104. package/src/components/ui-kit/showcase.tsx +0 -211
  105. package/src/hooks/use-mobile.tsx +0 -19
  106. package/src/hooks/use-toast.ts +0 -191
  107. package/src/hooks/useEditState.ts +0 -70
  108. package/src/hooks/useFormWithEditState.ts +0 -115
  109. package/src/lib/constants.ts +0 -25
  110. package/src/lib/mock-data/alert-data.ts +0 -275
  111. package/src/lib/mock-data/banking-data.ts +0 -72
  112. package/src/lib/mock-data/business-data.ts +0 -71
  113. package/src/lib/mock-data/counterparty-data.ts +0 -70
  114. package/src/lib/mock-data/index.ts +0 -5
  115. package/src/lib/mock-data/transaction-data.ts +0 -283
  116. package/src/lib/mock-data/wire-data.ts +0 -103
  117. package/src/lib/mock-data.tsx +0 -180
  118. package/src/lib/schemas/banking-schemas.ts +0 -30
  119. package/src/lib/schemas/business-schemas.ts +0 -36
  120. package/src/lib/schemas/counterparty-schemas.ts +0 -43
  121. package/src/lib/schemas/index.ts +0 -5
  122. package/src/lib/schemas/wire-schemas.ts +0 -44
  123. package/src/lib/utils.ts +0 -6
  124. package/src/main.tsx +0 -10
  125. package/src/pages/Cases.tsx +0 -16
  126. package/src/pages/Dashboard.tsx +0 -16
  127. package/src/pages/NotFound.tsx +0 -27
  128. package/src/pages/TransactionHistory.tsx +0 -532
  129. package/src/pages/UIKit.tsx +0 -51
  130. package/src/pages/alerts/AlertDetail.tsx +0 -193
  131. package/src/pages/alerts/Alerts.tsx +0 -373
  132. package/src/pages/business/Business.tsx +0 -48
  133. package/src/pages/business/Create.tsx +0 -173
  134. package/src/pages/counterparty/Create.tsx +0 -48
  135. package/src/pages/counterparty/DomesticWire.tsx +0 -78
  136. package/src/pages/counterparty/Manage.tsx +0 -79
  137. package/src/pages/transactions/NewTransaction.tsx +0 -527
  138. package/src/pages/transactions/TransactionDetail.tsx +0 -192
  139. package/src/vite-env.d.ts +0 -1
  140. package/tailwind.config.ts +0 -124
  141. package/tsconfig.app.json +0 -30
  142. package/tsconfig.json +0 -19
  143. package/tsconfig.node.json +0 -22
  144. package/vite.config.ts +0 -22
  145. /package/{src/assets/braid-logo.png → dist/braid-logo-343BOQZ2.png} +0 -0
@@ -1,35 +0,0 @@
1
- import * as React from "react"
2
- import { Controller, useFormContext, FieldPath, FieldValues } from "react-hook-form"
3
- import { EnhancedSelect } from "@/components/ui/enhanced-select"
4
-
5
- interface FormSelectProps<T extends FieldValues = FieldValues> {
6
- name: FieldPath<T>
7
- label?: string
8
- hint?: string
9
- placeholder?: string
10
- options: { value: string; label: string; disabled?: boolean }[]
11
- disabled?: boolean
12
- }
13
-
14
- export const FormSelect = <T extends FieldValues = FieldValues>({
15
- name,
16
- ...props
17
- }: FormSelectProps<T>) => {
18
- const { control, formState } = useFormContext<T>()
19
- const error = formState.errors[name]?.message as string | undefined
20
-
21
- return (
22
- <Controller
23
- name={name}
24
- control={control}
25
- render={({ field }) => (
26
- <EnhancedSelect
27
- {...props}
28
- value={field.value}
29
- onValueChange={field.onChange}
30
- error={error}
31
- />
32
- )}
33
- />
34
- )
35
- }
@@ -1,36 +0,0 @@
1
- interface InfoFieldProps {
2
- label?: string
3
- value: string | React.ReactNode
4
- layout?: 'vertical' | 'horizontal' | 'compact'
5
- className?: string
6
- }
7
-
8
- import React from "react"
9
-
10
- export const InfoField = ({ label, value, layout = 'vertical', className }: InfoFieldProps) => {
11
- if (layout === 'horizontal') {
12
- return (
13
- <div className={`flex items-start gap-3 ${className || ''}`}>
14
- {label && <p className="text-sm font-medium text-muted-foreground flex-shrink-0 max-w-[50%]">{label}</p>}
15
- <div className="text-sm text-foreground flex-1 min-w-0 break-words">{value}</div>
16
- </div>
17
- )
18
- }
19
-
20
- if (layout === 'compact') {
21
- return (
22
- <div className={`flex items-center gap-2 ${className || ''}`}>
23
- {label && <p className="text-xs font-medium text-muted-foreground">{label}:</p>}
24
- <div className="text-xs text-foreground">{value}</div>
25
- </div>
26
- )
27
- }
28
-
29
- // Default vertical layout
30
- return (
31
- <div className={className}>
32
- {label && <p className="text-sm font-medium text-muted-foreground">{label}</p>}
33
- <div className={`text-sm text-foreground ${label ? 'mt-1' : ''}`}>{value}</div>
34
- </div>
35
- )
36
- }
@@ -1,146 +0,0 @@
1
- import { useState } from "react"
2
- import { ChevronDown, ChevronRight, Copy, Check } from "lucide-react"
3
- import { Button } from "./button"
4
- import { cn } from "@/lib/utils"
5
-
6
- interface JsonViewerProps {
7
- data: any
8
- className?: string
9
- compact?: boolean
10
- maxHeight?: string
11
- }
12
-
13
- export const JsonViewer = ({ data, className, compact = false, maxHeight = "60vh" }: JsonViewerProps) => {
14
- const [copied, setCopied] = useState(false)
15
-
16
- const handleCopy = () => {
17
- navigator.clipboard.writeText(JSON.stringify(data, null, 2))
18
- setCopied(true)
19
- setTimeout(() => setCopied(false), 2000)
20
- }
21
-
22
- return (
23
- <div className={cn("relative", className)}>
24
- <div className={cn("absolute z-10", compact ? "right-1 top-1" : "right-2 top-2")}>
25
- <Button
26
- variant="outline"
27
- size={compact ? "sm" : "sm"}
28
- onClick={handleCopy}
29
- className={cn("gap-2", compact && "h-7 text-xs px-2")}
30
- >
31
- {copied ? (
32
- <>
33
- <Check className="h-3 w-3" />
34
- {!compact && "Copied"}
35
- </>
36
- ) : (
37
- <>
38
- <Copy className="h-3 w-3" />
39
- {!compact && "Copy JSON"}
40
- </>
41
- )}
42
- </Button>
43
- </div>
44
- <div
45
- className={cn(
46
- "overflow-auto bg-muted/30 rounded-lg border font-mono",
47
- compact ? "max-h-[300px] p-2 text-xs" : `max-h-[${maxHeight}] p-4 text-xs`
48
- )}
49
- style={{ maxHeight: compact ? "300px" : maxHeight }}
50
- >
51
- <JsonNode data={data} name="root" depth={0} compact={compact} />
52
- </div>
53
- </div>
54
- )
55
- }
56
-
57
- interface JsonNodeProps {
58
- data: any
59
- name: string
60
- depth: number
61
- compact?: boolean
62
- }
63
-
64
- const JsonNode = ({ data, name, depth, compact = false }: JsonNodeProps) => {
65
- const [isExpanded, setIsExpanded] = useState(compact ? depth < 1 : depth < 2)
66
-
67
- const indent = compact ? depth * 12 : depth * 16
68
-
69
- if (data === null) {
70
- return (
71
- <div style={{ paddingLeft: indent }} className="text-muted-foreground">
72
- <span className="text-primary">{name}</span>: <span className="text-orange-500">null</span>
73
- </div>
74
- )
75
- }
76
-
77
- if (typeof data !== "object") {
78
- const valueClass =
79
- typeof data === "string" ? "text-green-600 dark:text-green-400" :
80
- typeof data === "number" ? "text-blue-600 dark:text-blue-400" :
81
- typeof data === "boolean" ? "text-orange-500" :
82
- "text-foreground"
83
-
84
- return (
85
- <div style={{ paddingLeft: indent }}>
86
- <span className="text-primary">{name}</span>:{" "}
87
- <span className={valueClass}>
88
- {typeof data === "string" ? `"${data}"` : String(data)}
89
- </span>
90
- </div>
91
- )
92
- }
93
-
94
- const isArray = Array.isArray(data)
95
- const entries = isArray ? data : Object.entries(data)
96
- const isEmpty = entries.length === 0
97
-
98
- return (
99
- <div style={{ paddingLeft: indent }}>
100
- <div
101
- className="flex items-center gap-1 cursor-pointer hover:bg-muted/50 rounded"
102
- onClick={() => !isEmpty && setIsExpanded(!isExpanded)}
103
- >
104
- {!isEmpty && (
105
- isExpanded ? (
106
- <ChevronDown className="h-3 w-3 text-muted-foreground" />
107
- ) : (
108
- <ChevronRight className="h-3 w-3 text-muted-foreground" />
109
- )
110
- )}
111
- <span className="text-primary">{name}</span>
112
- <span className="text-muted-foreground">
113
- {isArray ? "[" : "{"}
114
- {!isExpanded && !isEmpty && "..."}
115
- {isEmpty && (isArray ? "]" : "}")}
116
- </span>
117
- </div>
118
- {isExpanded && !isEmpty && (
119
- <div>
120
- {isArray
121
- ? data.map((item: any, index: number) => (
122
- <JsonNode
123
- key={index}
124
- data={item}
125
- name={String(index)}
126
- depth={depth + 1}
127
- compact={compact}
128
- />
129
- ))
130
- : Object.entries(data).map(([key, value]) => (
131
- <JsonNode
132
- key={key}
133
- data={value}
134
- name={key}
135
- depth={depth + 1}
136
- compact={compact}
137
- />
138
- ))}
139
- <div style={{ paddingLeft: indent }} className="text-muted-foreground">
140
- {isArray ? "]" : "}"}
141
- </div>
142
- </div>
143
- )}
144
- </div>
145
- )
146
- }
@@ -1,24 +0,0 @@
1
- import * as React from "react"
2
- import * as LabelPrimitive from "@radix-ui/react-label"
3
- import { cva, type VariantProps } from "class-variance-authority"
4
-
5
- import { cn } from "@/lib/utils"
6
-
7
- const labelVariants = cva(
8
- "text-sm font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70"
9
- )
10
-
11
- const Label = React.forwardRef<
12
- React.ElementRef<typeof LabelPrimitive.Root>,
13
- React.ComponentPropsWithoutRef<typeof LabelPrimitive.Root> &
14
- VariantProps<typeof labelVariants>
15
- >(({ className, ...props }, ref) => (
16
- <LabelPrimitive.Root
17
- ref={ref}
18
- className={cn(labelVariants(), className)}
19
- {...props}
20
- />
21
- ))
22
- Label.displayName = LabelPrimitive.Root.displayName
23
-
24
- export { Label }
@@ -1,80 +0,0 @@
1
- import * as React from "react"
2
- import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card"
3
- import { Badge } from "@/components/ui/badge"
4
- import { cn } from "@/lib/utils"
5
- import { TrendingUp, TrendingDown, Minus } from "lucide-react"
6
-
7
- interface MetricCardProps {
8
- title: string
9
- value: string | number
10
- description?: string
11
- trend?: {
12
- value: number
13
- label: string
14
- direction: "up" | "down" | "neutral"
15
- }
16
- icon?: React.ReactNode
17
- variant?: "default" | "success" | "warning" | "destructive"
18
- className?: string
19
- }
20
-
21
- const variantStyles = {
22
- default: "",
23
- success: "border-success/20 bg-success/5",
24
- warning: "border-warning/20 bg-warning/5",
25
- destructive: "border-destructive/20 bg-destructive/5"
26
- }
27
-
28
- const trendIcons = {
29
- up: TrendingUp,
30
- down: TrendingDown,
31
- neutral: Minus
32
- }
33
-
34
- const trendColors = {
35
- up: "success",
36
- down: "destructive",
37
- neutral: "secondary"
38
- } as const
39
-
40
- export const MetricCard = React.forwardRef<HTMLDivElement, MetricCardProps>(
41
- ({ title, value, description, trend, icon, variant = "default", className }, ref) => {
42
- const TrendIcon = trend ? trendIcons[trend.direction] : null
43
-
44
- return (
45
- <Card
46
- ref={ref}
47
- className={cn(variantStyles[variant], className)}
48
- >
49
- <CardHeader className="flex flex-row items-center justify-between space-y-0 pb-2">
50
- <CardTitle className="text-sm font-medium text-muted-foreground">
51
- {title}
52
- </CardTitle>
53
- {icon && (
54
- <div className="text-muted-foreground">
55
- {icon}
56
- </div>
57
- )}
58
- </CardHeader>
59
- <CardContent>
60
- <div className="text-2xl font-bold text-foreground">{value}</div>
61
- {(description || trend) && (
62
- <div className="flex items-center justify-between mt-2">
63
- {description && (
64
- <p className="text-xs text-muted-foreground">{description}</p>
65
- )}
66
- {trend && TrendIcon && (
67
- <Badge variant={trendColors[trend.direction]} className="text-xs">
68
- <TrendIcon className="w-3 h-3 mr-1" />
69
- {trend.value > 0 ? "+" : ""}{trend.value}% {trend.label}
70
- </Badge>
71
- )}
72
- </div>
73
- )}
74
- </CardContent>
75
- </Card>
76
- )
77
- }
78
- )
79
-
80
- MetricCard.displayName = "MetricCard"
@@ -1,183 +0,0 @@
1
- import * as React from "react"
2
- import { cn } from "@/lib/utils"
3
-
4
- export interface PageAction {
5
- label: string
6
- variant?: "default" | "secondary" | "destructive" | "outline" | "ghost"
7
- onClick: () => void
8
- icon?: React.ComponentType<{ className?: string }>
9
- }
10
-
11
- export interface PageCard {
12
- component: React.ComponentType<any>
13
- key: string
14
- expandOnEdit?: boolean
15
- props?: Record<string, any>
16
- }
17
-
18
- interface PageLayoutProps {
19
- title: string
20
- description?: string
21
- children?: React.ReactNode
22
- actions?: PageAction[]
23
- cards?: PageCard[]
24
- mode?: "simple" | "detail" | "cards"
25
- maxWidth?: "sm" | "md" | "lg" | "xl" | "2xl" | "full"
26
- gridCols?: 1 | 2 | 3 | 4
27
- responsive?: boolean
28
- className?: string
29
- }
30
-
31
- const maxWidthClasses = {
32
- sm: "max-w-2xl",
33
- md: "max-w-4xl",
34
- lg: "max-w-6xl",
35
- xl: "max-w-7xl",
36
- "2xl": "max-w-screen-2xl",
37
- full: "max-w-none"
38
- }
39
-
40
- const getGridClasses = (gridCols: number, responsive: boolean) => {
41
- const colsMap = {
42
- 1: "grid-cols-1",
43
- 2: "grid-cols-2",
44
- 3: "grid-cols-3",
45
- 4: "grid-cols-4"
46
- }
47
-
48
- if (!responsive) {
49
- return colsMap[gridCols as keyof typeof colsMap] || "grid-cols-1"
50
- }
51
-
52
- // Responsive grid classes
53
- switch (gridCols) {
54
- case 1:
55
- return "grid-cols-1"
56
- case 2:
57
- return "grid-cols-1 lg:grid-cols-2"
58
- case 3:
59
- return "grid-cols-1 md:grid-cols-2 lg:grid-cols-3"
60
- case 4:
61
- return "grid-cols-1 md:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4"
62
- default:
63
- return "grid-cols-1 lg:grid-cols-2"
64
- }
65
- }
66
-
67
- export const PageLayout = React.forwardRef<HTMLDivElement, PageLayoutProps>(
68
- ({
69
- title,
70
- description,
71
- children,
72
- actions = [],
73
- cards = [],
74
- mode = "simple",
75
- maxWidth = "xl",
76
- gridCols = 2,
77
- responsive = true,
78
- className
79
- }, ref) => {
80
- const [editingCards, setEditingCards] = React.useState<Set<string>>(new Set())
81
-
82
- const toggleEdit = (cardKey: string) => {
83
- setEditingCards(prev => {
84
- const next = new Set(prev)
85
- if (next.has(cardKey)) {
86
- next.delete(cardKey)
87
- } else {
88
- next.add(cardKey)
89
- }
90
- return next
91
- })
92
- }
93
-
94
- return (
95
- <div ref={ref} className="flex flex-col h-screen bg-gradient-subtle">
96
- {/* Sticky Header */}
97
- <div className={cn(
98
- "sticky top-0 z-10 bg-gradient-subtle border-b border-border/40",
99
- "container mx-auto px-4 pt-8 pb-4",
100
- maxWidthClasses[maxWidth]
101
- )}>
102
- <div className="flex items-start justify-between">
103
- <div>
104
- <h1 className="text-3xl font-bold text-foreground mb-2">
105
- {title}
106
- </h1>
107
- {description && (
108
- <p className="text-muted-foreground">
109
- {description}
110
- </p>
111
- )}
112
- </div>
113
-
114
- {actions.length > 0 && (
115
- <div className="flex items-center gap-2">
116
- {actions.map((action, index) => {
117
- const Icon = action.icon
118
- return (
119
- <button
120
- key={index}
121
- onClick={action.onClick}
122
- className={cn(
123
- "inline-flex items-center gap-2 px-4 py-2 rounded-md text-sm font-medium transition-colors",
124
- {
125
- "bg-primary text-primary-foreground hover:bg-primary/90": action.variant === "default" || !action.variant,
126
- "bg-secondary text-secondary-foreground hover:bg-secondary/80": action.variant === "secondary",
127
- "bg-destructive text-destructive-foreground hover:bg-destructive/90": action.variant === "destructive",
128
- "border border-input bg-background hover:bg-accent hover:text-accent-foreground": action.variant === "outline",
129
- "hover:bg-accent hover:text-accent-foreground": action.variant === "ghost"
130
- }
131
- )}
132
- >
133
- {Icon && <Icon className="h-4 w-4" />}
134
- {action.label}
135
- </button>
136
- )
137
- })}
138
- </div>
139
- )}
140
- </div>
141
- </div>
142
-
143
- {/* Scrollable Content */}
144
- <div className="flex-1 overflow-y-auto">
145
- <div className={cn(
146
- "container mx-auto px-4 py-6",
147
- maxWidthClasses[maxWidth],
148
- className
149
- )}>
150
- {mode === "cards" && cards.length > 0 ? (
151
- <div className={cn("grid gap-6", getGridClasses(gridCols, responsive))}>
152
- {cards.map((card) => {
153
- const isEditing = editingCards.has(card.key)
154
- const shouldExpand = card.expandOnEdit && isEditing
155
-
156
- return (
157
- <div
158
- key={card.key}
159
- className={cn(
160
- "transition-all duration-300",
161
- shouldExpand && (gridCols > 1 ? "col-span-full" : "")
162
- )}
163
- >
164
- <card.component
165
- {...card.props}
166
- isEditing={isEditing}
167
- onToggleEdit={() => toggleEdit(card.key)}
168
- />
169
- </div>
170
- )
171
- })}
172
- </div>
173
- ) : (
174
- children
175
- )}
176
- </div>
177
- </div>
178
- </div>
179
- )
180
- }
181
- )
182
-
183
- PageLayout.displayName = "PageLayout"
@@ -1,29 +0,0 @@
1
- import * as React from "react"
2
- import * as PopoverPrimitive from "@radix-ui/react-popover"
3
-
4
- import { cn } from "@/lib/utils"
5
-
6
- const Popover = PopoverPrimitive.Root
7
-
8
- const PopoverTrigger = PopoverPrimitive.Trigger
9
-
10
- const PopoverContent = React.forwardRef<
11
- React.ElementRef<typeof PopoverPrimitive.Content>,
12
- React.ComponentPropsWithoutRef<typeof PopoverPrimitive.Content>
13
- >(({ className, align = "center", sideOffset = 4, ...props }, ref) => (
14
- <PopoverPrimitive.Portal>
15
- <PopoverPrimitive.Content
16
- ref={ref}
17
- align={align}
18
- sideOffset={sideOffset}
19
- className={cn(
20
- "z-50 w-72 rounded-md border bg-popover p-4 text-popover-foreground shadow-md outline-none data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2",
21
- className
22
- )}
23
- {...props}
24
- />
25
- </PopoverPrimitive.Portal>
26
- ))
27
- PopoverContent.displayName = PopoverPrimitive.Content.displayName
28
-
29
- export { Popover, PopoverTrigger, PopoverContent }
@@ -1,46 +0,0 @@
1
- import * as React from "react"
2
- import { cn } from "@/lib/utils"
3
-
4
- interface ResponsiveGridProps {
5
- children: React.ReactNode
6
- type?: "cards" | "forms" | "data" | "custom"
7
- gap?: "sm" | "md" | "lg" | "xl"
8
- editMode?: boolean
9
- className?: string
10
- }
11
-
12
- const typeClasses = {
13
- cards: "grid-cols-1 md:grid-cols-2 lg:grid-cols-3",
14
- forms: "grid-cols-1 lg:grid-cols-2",
15
- data: "grid-cols-1 md:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4",
16
- custom: ""
17
- }
18
-
19
- const gapClasses = {
20
- sm: "gap-3",
21
- md: "gap-4",
22
- lg: "gap-6",
23
- xl: "gap-8"
24
- }
25
-
26
- export const ResponsiveGrid = React.forwardRef<HTMLDivElement, ResponsiveGridProps>(
27
- ({ children, type = "cards", gap = "md", editMode = false, className }, ref) => {
28
- const gridClasses = editMode ? "grid-cols-1" : typeClasses[type]
29
-
30
- return (
31
- <div
32
- ref={ref}
33
- className={cn(
34
- "grid",
35
- gridClasses,
36
- gapClasses[gap],
37
- className
38
- )}
39
- >
40
- {children}
41
- </div>
42
- )
43
- }
44
- )
45
-
46
- ResponsiveGrid.displayName = "ResponsiveGrid"
@@ -1,31 +0,0 @@
1
- "use client"
2
-
3
- import * as React from "react"
4
- import * as SeparatorPrimitive from "@radix-ui/react-separator"
5
-
6
- import { cn } from "@/lib/utils"
7
-
8
- const Separator = React.forwardRef<
9
- React.ElementRef<typeof SeparatorPrimitive.Root>,
10
- React.ComponentPropsWithoutRef<typeof SeparatorPrimitive.Root>
11
- >(
12
- (
13
- { className, orientation = "horizontal", decorative = true, ...props },
14
- ref
15
- ) => (
16
- <SeparatorPrimitive.Root
17
- ref={ref}
18
- decorative={decorative}
19
- orientation={orientation}
20
- className={cn(
21
- "shrink-0 bg-border",
22
- orientation === "horizontal" ? "h-[1px] w-full" : "h-full w-[1px]",
23
- className
24
- )}
25
- {...props}
26
- />
27
- )
28
- )
29
- Separator.displayName = SeparatorPrimitive.Root.displayName
30
-
31
- export { Separator }