@djangocfg/ext-payments 1.0.13 → 1.0.17
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/config.cjs +5 -8
- package/dist/config.js +5 -8
- package/dist/hooks.cjs +1 -1
- package/dist/hooks.js +1 -1
- package/dist/index.cjs +1085 -1107
- package/dist/index.d.cts +480 -41
- package/dist/index.d.ts +480 -41
- package/dist/index.js +1037 -1093
- package/package.json +13 -16
- package/src/api/generated/ext_payments/CLAUDE.md +7 -3
- package/src/api/generated/ext_payments/_utils/fetchers/ext_payments__payments.ts +237 -5
- package/src/api/generated/ext_payments/_utils/hooks/ext_payments__payments.ts +71 -3
- package/src/api/generated/ext_payments/_utils/schemas/PaginatedWithdrawalListList.schema.ts +24 -0
- package/src/api/generated/ext_payments/_utils/schemas/PaymentCreateRequest.schema.ts +21 -0
- package/src/api/generated/ext_payments/_utils/schemas/WithdrawalCreateRequest.schema.ts +21 -0
- package/src/api/generated/ext_payments/_utils/schemas/WithdrawalDetail.schema.ts +42 -0
- package/src/api/generated/ext_payments/_utils/schemas/WithdrawalList.schema.ts +29 -0
- package/src/api/generated/ext_payments/_utils/schemas/index.ts +5 -0
- package/src/api/generated/ext_payments/enums.ts +36 -0
- package/src/api/generated/ext_payments/ext_payments__payments/client.ts +58 -5
- package/src/api/generated/ext_payments/ext_payments__payments/models.ts +141 -0
- package/src/api/generated/ext_payments/schema.json +579 -3
- package/src/components/ActivityItem.tsx +118 -0
- package/src/components/ActivityList.tsx +93 -0
- package/src/components/AddFundsSheet.tsx +258 -0
- package/src/components/BalanceHero.tsx +102 -0
- package/src/components/PaymentSheet.tsx +290 -0
- package/src/components/ResponsiveSheet.tsx +151 -0
- package/src/components/WithdrawSheet.tsx +329 -0
- package/src/components/index.ts +18 -0
- package/src/contexts/WalletContext.tsx +355 -0
- package/src/contexts/index.ts +12 -45
- package/src/index.ts +6 -18
- package/src/contexts/BalancesContext.tsx +0 -63
- package/src/contexts/CurrenciesContext.tsx +0 -64
- package/src/contexts/OverviewContext.tsx +0 -173
- package/src/contexts/PaymentsContext.tsx +0 -122
- package/src/contexts/PaymentsExtensionProvider.tsx +0 -56
- package/src/contexts/README.md +0 -201
- package/src/contexts/RootPaymentsContext.tsx +0 -66
- package/src/contexts/types.ts +0 -40
- package/src/hooks/index.ts +0 -20
- package/src/layouts/PaymentsLayout/PaymentsLayout.tsx +0 -90
- package/src/layouts/PaymentsLayout/components/CreatePaymentDialog.tsx +0 -274
- package/src/layouts/PaymentsLayout/components/PaymentDetailsDialog.tsx +0 -287
- package/src/layouts/PaymentsLayout/components/index.ts +0 -2
- package/src/layouts/PaymentsLayout/events.ts +0 -47
- package/src/layouts/PaymentsLayout/index.ts +0 -16
- package/src/layouts/PaymentsLayout/types.ts +0 -6
- package/src/layouts/PaymentsLayout/views/overview/components/BalanceCard.tsx +0 -121
- package/src/layouts/PaymentsLayout/views/overview/components/RecentPayments.tsx +0 -139
- package/src/layouts/PaymentsLayout/views/overview/components/index.ts +0 -2
- package/src/layouts/PaymentsLayout/views/overview/index.tsx +0 -21
- package/src/layouts/PaymentsLayout/views/payments/components/PaymentsList.tsx +0 -279
- package/src/layouts/PaymentsLayout/views/payments/components/index.ts +0 -1
- package/src/layouts/PaymentsLayout/views/payments/index.tsx +0 -18
- package/src/layouts/PaymentsLayout/views/transactions/components/TransactionsList.tsx +0 -260
- package/src/layouts/PaymentsLayout/views/transactions/components/index.ts +0 -1
- package/src/layouts/PaymentsLayout/views/transactions/index.tsx +0 -18
|
@@ -0,0 +1,290 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Payment Sheet (Apple-style)
|
|
3
|
+
*
|
|
4
|
+
* Responsive: Dialog on desktop, Drawer on mobile
|
|
5
|
+
* Shows payment details with QR code and address
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
'use client';
|
|
9
|
+
|
|
10
|
+
import { useEffect, useState, useMemo } from 'react';
|
|
11
|
+
import {
|
|
12
|
+
AlertCircle,
|
|
13
|
+
CheckCircle2,
|
|
14
|
+
Clock,
|
|
15
|
+
ExternalLink,
|
|
16
|
+
RefreshCw,
|
|
17
|
+
XCircle,
|
|
18
|
+
} from 'lucide-react';
|
|
19
|
+
import moment from 'moment';
|
|
20
|
+
import useSWR from 'swr';
|
|
21
|
+
|
|
22
|
+
import {
|
|
23
|
+
Button,
|
|
24
|
+
CopyButton,
|
|
25
|
+
Skeleton,
|
|
26
|
+
TokenIcon,
|
|
27
|
+
ResponsiveSheet,
|
|
28
|
+
ResponsiveSheetContent,
|
|
29
|
+
ResponsiveSheetDescription,
|
|
30
|
+
ResponsiveSheetHeader,
|
|
31
|
+
ResponsiveSheetTitle,
|
|
32
|
+
} from '@djangocfg/ui-core';
|
|
33
|
+
import { cn } from '@djangocfg/ui-core/lib';
|
|
34
|
+
|
|
35
|
+
import { useWallet } from '../contexts/WalletContext';
|
|
36
|
+
import type { PaymentDetail } from '../api/generated/ext_payments/_utils/schemas';
|
|
37
|
+
|
|
38
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
39
|
+
// Props
|
|
40
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
41
|
+
|
|
42
|
+
interface PaymentSheetProps {
|
|
43
|
+
paymentId: string | null;
|
|
44
|
+
open: boolean;
|
|
45
|
+
onOpenChange: (open: boolean) => void;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
49
|
+
// Status Config
|
|
50
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
51
|
+
|
|
52
|
+
const statusConfig: Record<string, { icon: any; color: string; bg: string; label: string; animate?: boolean }> = {
|
|
53
|
+
pending: {
|
|
54
|
+
icon: Clock,
|
|
55
|
+
color: 'text-yellow-500',
|
|
56
|
+
bg: 'bg-yellow-500/10',
|
|
57
|
+
label: 'Waiting for payment',
|
|
58
|
+
},
|
|
59
|
+
confirming: {
|
|
60
|
+
icon: RefreshCw,
|
|
61
|
+
color: 'text-blue-500',
|
|
62
|
+
bg: 'bg-blue-500/10',
|
|
63
|
+
label: 'Confirming',
|
|
64
|
+
animate: true,
|
|
65
|
+
},
|
|
66
|
+
completed: {
|
|
67
|
+
icon: CheckCircle2,
|
|
68
|
+
color: 'text-green-500',
|
|
69
|
+
bg: 'bg-green-500/10',
|
|
70
|
+
label: 'Completed',
|
|
71
|
+
},
|
|
72
|
+
failed: {
|
|
73
|
+
icon: XCircle,
|
|
74
|
+
color: 'text-red-500',
|
|
75
|
+
bg: 'bg-red-500/10',
|
|
76
|
+
label: 'Failed',
|
|
77
|
+
},
|
|
78
|
+
expired: {
|
|
79
|
+
icon: AlertCircle,
|
|
80
|
+
color: 'text-muted-foreground',
|
|
81
|
+
bg: 'bg-muted',
|
|
82
|
+
label: 'Expired',
|
|
83
|
+
},
|
|
84
|
+
};
|
|
85
|
+
|
|
86
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
87
|
+
// Component
|
|
88
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
89
|
+
|
|
90
|
+
export function PaymentSheet({ paymentId, open, onOpenChange }: PaymentSheetProps) {
|
|
91
|
+
const { getPaymentDetails } = useWallet();
|
|
92
|
+
const [timeLeft, setTimeLeft] = useState<string>('');
|
|
93
|
+
|
|
94
|
+
// Fetch payment details when sheet is open
|
|
95
|
+
const { data: payment, isLoading, error, mutate } = useSWR<PaymentDetail>(
|
|
96
|
+
open && paymentId ? ['payment-details', paymentId] : null,
|
|
97
|
+
() => getPaymentDetails(paymentId!),
|
|
98
|
+
{ refreshInterval: 10000 }
|
|
99
|
+
);
|
|
100
|
+
|
|
101
|
+
// Calculate time left
|
|
102
|
+
useEffect(() => {
|
|
103
|
+
if (!payment?.expires_at) return;
|
|
104
|
+
|
|
105
|
+
const updateTimeLeft = () => {
|
|
106
|
+
const now = moment();
|
|
107
|
+
const expires = moment.utc(payment.expires_at!);
|
|
108
|
+
const diff = expires.diff(now);
|
|
109
|
+
|
|
110
|
+
if (diff <= 0) {
|
|
111
|
+
setTimeLeft('Expired');
|
|
112
|
+
return;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
const duration = moment.duration(diff);
|
|
116
|
+
const hours = Math.floor(duration.asHours());
|
|
117
|
+
const minutes = duration.minutes();
|
|
118
|
+
const seconds = duration.seconds();
|
|
119
|
+
|
|
120
|
+
setTimeLeft(`${hours}h ${minutes}m ${seconds}s`);
|
|
121
|
+
};
|
|
122
|
+
|
|
123
|
+
updateTimeLeft();
|
|
124
|
+
const interval = setInterval(updateTimeLeft, 1000);
|
|
125
|
+
return () => clearInterval(interval);
|
|
126
|
+
}, [payment?.expires_at]);
|
|
127
|
+
|
|
128
|
+
// Map status
|
|
129
|
+
const status = useMemo(() => {
|
|
130
|
+
const s = payment?.status?.toLowerCase();
|
|
131
|
+
if (s === 'completed' || s === 'success' || s === 'finished') return 'completed';
|
|
132
|
+
if (s === 'confirming' || s === 'partially_paid') return 'confirming';
|
|
133
|
+
if (s === 'expired') return 'expired';
|
|
134
|
+
if (s === 'failed' || s === 'error' || s === 'cancelled') return 'failed';
|
|
135
|
+
return 'pending';
|
|
136
|
+
}, [payment?.status]);
|
|
137
|
+
|
|
138
|
+
const config = statusConfig[status];
|
|
139
|
+
const StatusIcon = config.icon;
|
|
140
|
+
|
|
141
|
+
// QR code URL
|
|
142
|
+
const qrCodeUrl = payment?.pay_address
|
|
143
|
+
? `https://api.qrserver.com/v1/create-qr-code/?size=200x200&data=${encodeURIComponent(payment.pay_address)}`
|
|
144
|
+
: null;
|
|
145
|
+
|
|
146
|
+
const isPending = status === 'pending';
|
|
147
|
+
|
|
148
|
+
return (
|
|
149
|
+
<ResponsiveSheet open={open} onOpenChange={onOpenChange}>
|
|
150
|
+
<ResponsiveSheetContent className="sm:max-w-lg">
|
|
151
|
+
<ResponsiveSheetHeader>
|
|
152
|
+
<ResponsiveSheetTitle>Payment Details</ResponsiveSheetTitle>
|
|
153
|
+
<ResponsiveSheetDescription>
|
|
154
|
+
{isPending ? 'Send cryptocurrency to complete payment' : 'Payment information'}
|
|
155
|
+
</ResponsiveSheetDescription>
|
|
156
|
+
</ResponsiveSheetHeader>
|
|
157
|
+
|
|
158
|
+
<div className="p-4 sm:p-0 sm:mt-4 overflow-y-auto max-h-[70vh]">
|
|
159
|
+
{isLoading && (
|
|
160
|
+
<div className="space-y-6">
|
|
161
|
+
<div className="flex items-center justify-center">
|
|
162
|
+
<Skeleton className="h-48 w-48 rounded-xl" />
|
|
163
|
+
</div>
|
|
164
|
+
<Skeleton className="h-12 w-full" />
|
|
165
|
+
<Skeleton className="h-24 w-full" />
|
|
166
|
+
</div>
|
|
167
|
+
)}
|
|
168
|
+
|
|
169
|
+
{error && (
|
|
170
|
+
<div className="flex flex-col items-center justify-center py-12">
|
|
171
|
+
<XCircle className="h-12 w-12 text-destructive mb-4" />
|
|
172
|
+
<p className="text-sm text-muted-foreground mb-4">Failed to load payment</p>
|
|
173
|
+
<Button onClick={() => mutate()}>Try Again</Button>
|
|
174
|
+
</div>
|
|
175
|
+
)}
|
|
176
|
+
|
|
177
|
+
{payment && !isLoading && (
|
|
178
|
+
<div className="space-y-6">
|
|
179
|
+
{/* Status Badge */}
|
|
180
|
+
<div className={cn('flex items-center gap-3 p-4 rounded-xl', config.bg)}>
|
|
181
|
+
<StatusIcon className={cn('h-6 w-6', config.color, config.animate && 'animate-spin')} />
|
|
182
|
+
<div className="flex-1">
|
|
183
|
+
<div className="font-semibold">{config.label}</div>
|
|
184
|
+
{isPending && timeLeft && (
|
|
185
|
+
<div className="text-sm text-muted-foreground">
|
|
186
|
+
Expires in {timeLeft}
|
|
187
|
+
</div>
|
|
188
|
+
)}
|
|
189
|
+
</div>
|
|
190
|
+
</div>
|
|
191
|
+
|
|
192
|
+
{/* Amount */}
|
|
193
|
+
<div className="bg-muted rounded-xl p-4 space-y-3">
|
|
194
|
+
<div className="flex items-center justify-between">
|
|
195
|
+
<span className="text-muted-foreground">Amount to send</span>
|
|
196
|
+
<div className="flex items-center gap-2">
|
|
197
|
+
<TokenIcon symbol={payment.currency_code} size={24} />
|
|
198
|
+
<span className="font-mono font-bold text-lg">
|
|
199
|
+
{payment.pay_amount} {payment.currency_code}
|
|
200
|
+
</span>
|
|
201
|
+
</div>
|
|
202
|
+
</div>
|
|
203
|
+
<div className="flex items-center justify-between text-sm">
|
|
204
|
+
<span className="text-muted-foreground">Equivalent</span>
|
|
205
|
+
<span className="font-semibold">${parseFloat(payment.amount_usd).toFixed(2)} USD</span>
|
|
206
|
+
</div>
|
|
207
|
+
{payment.currency_network && (
|
|
208
|
+
<div className="flex items-center justify-between text-sm pt-2 border-t">
|
|
209
|
+
<span className="text-muted-foreground">Network</span>
|
|
210
|
+
<span className="font-medium">{payment.currency_network}</span>
|
|
211
|
+
</div>
|
|
212
|
+
)}
|
|
213
|
+
</div>
|
|
214
|
+
|
|
215
|
+
{/* QR Code */}
|
|
216
|
+
{qrCodeUrl && isPending && (
|
|
217
|
+
<div className="flex justify-center p-6 bg-white rounded-xl">
|
|
218
|
+
<img src={qrCodeUrl} alt="Payment QR Code" className="w-48 h-48" />
|
|
219
|
+
</div>
|
|
220
|
+
)}
|
|
221
|
+
|
|
222
|
+
{/* Payment Address */}
|
|
223
|
+
{payment.pay_address && isPending && (
|
|
224
|
+
<div className="space-y-2">
|
|
225
|
+
<label className="text-sm font-medium">Payment Address</label>
|
|
226
|
+
<div className="flex items-center gap-2">
|
|
227
|
+
<div className="flex-1 p-3 bg-muted rounded-xl font-mono text-sm break-all">
|
|
228
|
+
{payment.pay_address}
|
|
229
|
+
</div>
|
|
230
|
+
<CopyButton value={payment.pay_address} variant="outline" className="shrink-0" />
|
|
231
|
+
</div>
|
|
232
|
+
</div>
|
|
233
|
+
)}
|
|
234
|
+
|
|
235
|
+
{/* Transaction Hash (if completed) */}
|
|
236
|
+
{payment.transaction_hash && (
|
|
237
|
+
<div className="space-y-2">
|
|
238
|
+
<label className="text-sm font-medium">Transaction Hash</label>
|
|
239
|
+
<div className="p-3 bg-muted rounded-xl font-mono text-sm break-all">
|
|
240
|
+
{payment.transaction_hash}
|
|
241
|
+
</div>
|
|
242
|
+
</div>
|
|
243
|
+
)}
|
|
244
|
+
|
|
245
|
+
{/* External Link */}
|
|
246
|
+
{payment.payment_url && isPending && (
|
|
247
|
+
<Button
|
|
248
|
+
variant="outline"
|
|
249
|
+
className="w-full"
|
|
250
|
+
onClick={() => window.open(payment.payment_url!, '_blank')}
|
|
251
|
+
>
|
|
252
|
+
<ExternalLink className="h-4 w-4 mr-2" />
|
|
253
|
+
Open in Payment Provider
|
|
254
|
+
</Button>
|
|
255
|
+
)}
|
|
256
|
+
|
|
257
|
+
{/* Metadata */}
|
|
258
|
+
<div className="space-y-2 text-xs text-muted-foreground pt-4 border-t">
|
|
259
|
+
<div className="flex justify-between">
|
|
260
|
+
<span>Payment ID</span>
|
|
261
|
+
<span className="font-mono">{payment.id}</span>
|
|
262
|
+
</div>
|
|
263
|
+
{payment.internal_payment_id && (
|
|
264
|
+
<div className="flex justify-between">
|
|
265
|
+
<span>Order #</span>
|
|
266
|
+
<span className="font-mono">{payment.internal_payment_id}</span>
|
|
267
|
+
</div>
|
|
268
|
+
)}
|
|
269
|
+
<div className="flex justify-between">
|
|
270
|
+
<span>Created</span>
|
|
271
|
+
<span>{moment.utc(payment.created_at).local().format('MMM D, YYYY HH:mm')}</span>
|
|
272
|
+
</div>
|
|
273
|
+
</div>
|
|
274
|
+
|
|
275
|
+
{/* Refresh Button */}
|
|
276
|
+
<Button
|
|
277
|
+
variant="ghost"
|
|
278
|
+
className="w-full"
|
|
279
|
+
onClick={() => mutate()}
|
|
280
|
+
>
|
|
281
|
+
<RefreshCw className="h-4 w-4 mr-2" />
|
|
282
|
+
Refresh Status
|
|
283
|
+
</Button>
|
|
284
|
+
</div>
|
|
285
|
+
)}
|
|
286
|
+
</div>
|
|
287
|
+
</ResponsiveSheetContent>
|
|
288
|
+
</ResponsiveSheet>
|
|
289
|
+
);
|
|
290
|
+
}
|
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Responsive Sheet (Apple-style)
|
|
3
|
+
*
|
|
4
|
+
* Dialog on desktop, Drawer (pull-down) on mobile.
|
|
5
|
+
* Uses useIsMobile hook for responsive behavior.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
'use client';
|
|
9
|
+
|
|
10
|
+
import * as React from 'react';
|
|
11
|
+
|
|
12
|
+
import {
|
|
13
|
+
Dialog,
|
|
14
|
+
DialogContent,
|
|
15
|
+
DialogDescription,
|
|
16
|
+
DialogFooter,
|
|
17
|
+
DialogHeader,
|
|
18
|
+
DialogTitle,
|
|
19
|
+
Drawer,
|
|
20
|
+
DrawerContent,
|
|
21
|
+
DrawerDescription,
|
|
22
|
+
DrawerFooter,
|
|
23
|
+
DrawerHeader,
|
|
24
|
+
DrawerTitle,
|
|
25
|
+
useIsMobile,
|
|
26
|
+
} from '@djangocfg/ui-core';
|
|
27
|
+
|
|
28
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
29
|
+
// Props
|
|
30
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
31
|
+
|
|
32
|
+
interface ResponsiveSheetProps {
|
|
33
|
+
open: boolean;
|
|
34
|
+
onOpenChange: (open: boolean) => void;
|
|
35
|
+
children: React.ReactNode;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
interface ResponsiveSheetHeaderProps {
|
|
39
|
+
children: React.ReactNode;
|
|
40
|
+
className?: string;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
interface ResponsiveSheetTitleProps {
|
|
44
|
+
children: React.ReactNode;
|
|
45
|
+
className?: string;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
interface ResponsiveSheetDescriptionProps {
|
|
49
|
+
children: React.ReactNode;
|
|
50
|
+
className?: string;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
interface ResponsiveSheetContentProps {
|
|
54
|
+
children: React.ReactNode;
|
|
55
|
+
className?: string;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
interface ResponsiveSheetFooterProps {
|
|
59
|
+
children: React.ReactNode;
|
|
60
|
+
className?: string;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
64
|
+
// Context
|
|
65
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
66
|
+
|
|
67
|
+
const ResponsiveSheetContext = React.createContext<{ isMobile: boolean }>({ isMobile: false });
|
|
68
|
+
|
|
69
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
70
|
+
// Components
|
|
71
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
72
|
+
|
|
73
|
+
export function ResponsiveSheet({ open, onOpenChange, children }: ResponsiveSheetProps) {
|
|
74
|
+
const isMobile = useIsMobile();
|
|
75
|
+
|
|
76
|
+
if (isMobile) {
|
|
77
|
+
return (
|
|
78
|
+
<ResponsiveSheetContext.Provider value={{ isMobile: true }}>
|
|
79
|
+
<Drawer open={open} onOpenChange={onOpenChange}>
|
|
80
|
+
{children}
|
|
81
|
+
</Drawer>
|
|
82
|
+
</ResponsiveSheetContext.Provider>
|
|
83
|
+
);
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
return (
|
|
87
|
+
<ResponsiveSheetContext.Provider value={{ isMobile: false }}>
|
|
88
|
+
<Dialog open={open} onOpenChange={onOpenChange}>
|
|
89
|
+
{children}
|
|
90
|
+
</Dialog>
|
|
91
|
+
</ResponsiveSheetContext.Provider>
|
|
92
|
+
);
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
export function ResponsiveSheetContent({ children, className }: ResponsiveSheetContentProps) {
|
|
96
|
+
const { isMobile } = React.useContext(ResponsiveSheetContext);
|
|
97
|
+
|
|
98
|
+
if (isMobile) {
|
|
99
|
+
return (
|
|
100
|
+
<DrawerContent className={className}>
|
|
101
|
+
{children}
|
|
102
|
+
</DrawerContent>
|
|
103
|
+
);
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
return (
|
|
107
|
+
<DialogContent className={className}>
|
|
108
|
+
{children}
|
|
109
|
+
</DialogContent>
|
|
110
|
+
);
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
export function ResponsiveSheetHeader({ children, className }: ResponsiveSheetHeaderProps) {
|
|
114
|
+
const { isMobile } = React.useContext(ResponsiveSheetContext);
|
|
115
|
+
|
|
116
|
+
if (isMobile) {
|
|
117
|
+
return <DrawerHeader className={className}>{children}</DrawerHeader>;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
return <DialogHeader className={className}>{children}</DialogHeader>;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
export function ResponsiveSheetTitle({ children, className }: ResponsiveSheetTitleProps) {
|
|
124
|
+
const { isMobile } = React.useContext(ResponsiveSheetContext);
|
|
125
|
+
|
|
126
|
+
if (isMobile) {
|
|
127
|
+
return <DrawerTitle className={className}>{children}</DrawerTitle>;
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
return <DialogTitle className={className}>{children}</DialogTitle>;
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
export function ResponsiveSheetDescription({ children, className }: ResponsiveSheetDescriptionProps) {
|
|
134
|
+
const { isMobile } = React.useContext(ResponsiveSheetContext);
|
|
135
|
+
|
|
136
|
+
if (isMobile) {
|
|
137
|
+
return <DrawerDescription className={className}>{children}</DrawerDescription>;
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
return <DialogDescription className={className}>{children}</DialogDescription>;
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
export function ResponsiveSheetFooter({ children, className }: ResponsiveSheetFooterProps) {
|
|
144
|
+
const { isMobile } = React.useContext(ResponsiveSheetContext);
|
|
145
|
+
|
|
146
|
+
if (isMobile) {
|
|
147
|
+
return <DrawerFooter className={className}>{children}</DrawerFooter>;
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
return <DialogFooter className={className}>{children}</DialogFooter>;
|
|
151
|
+
}
|