@stacksjs/defaults 0.70.54
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/LICENSE.md +21 -0
- package/README.md +2 -0
- package/package.json +20 -0
- package/resources/assets/fonts/013717e9.woff +0 -0
- package/resources/assets/fonts/03355817.woff2 +0 -0
- package/resources/assets/fonts/0380de7e.woff2 +0 -0
- package/resources/assets/fonts/0ba5d32a.woff +0 -0
- package/resources/assets/fonts/0bd57ddf.woff2 +0 -0
- package/resources/assets/fonts/19de0a60.woff2 +0 -0
- package/resources/assets/fonts/20b87e84.woff +0 -0
- package/resources/assets/fonts/4bbc67e1.woff +0 -0
- package/resources/assets/fonts/576fb0d7.woff +0 -0
- package/resources/assets/fonts/5ea10ee5.woff2 +0 -0
- package/resources/assets/fonts/6413fc0a.woff +0 -0
- package/resources/assets/fonts/72c114cf.woff +0 -0
- package/resources/assets/fonts/73c57e73.woff2 +0 -0
- package/resources/assets/fonts/813dca6c.woff +0 -0
- package/resources/assets/fonts/8a9b0995.woff2 +0 -0
- package/resources/assets/fonts/90b4832f.woff +0 -0
- package/resources/assets/fonts/9394ab85.woff2 +0 -0
- package/resources/assets/fonts/9b3c7d7f.woff2 +0 -0
- package/resources/assets/fonts/Monaco.ttf +0 -0
- package/resources/assets/fonts/b1b36d74.woff +0 -0
- package/resources/assets/fonts/b5d74798.woff2 +0 -0
- package/resources/assets/fonts/b9f81a4d.woff +0 -0
- package/resources/assets/fonts/c9784008.woff2 +0 -0
- package/resources/assets/fonts/cf692227.woff +0 -0
- package/resources/assets/fonts/d1c6ab51.woff2 +0 -0
- package/resources/assets/fonts/e2eb62fc.woff +0 -0
- package/resources/assets/fonts/fe21f8d8.woff2 +0 -0
- package/resources/assets/fonts/nps/CampmateScript-Regular.woff2 +0 -0
- package/resources/assets/fonts/nps/NPS_2026-variable.woff2 +0 -0
- package/resources/assets/fonts/nps/RedwoodSerif-Regular.woff2 +0 -0
- package/resources/assets/fonts/nps/SequoiaSans-Regular.woff2 +0 -0
- package/resources/assets/fonts/nps/Switchback-Regular.woff2 +0 -0
- package/resources/assets/images/app-icon.png +0 -0
- package/resources/assets/images/bg-img.png +0 -0
- package/resources/assets/images/park-ridge.svg +15 -0
- package/resources/assets/images/topography.svg +1 -0
- package/resources/assets/scripts/main.ts +2153 -0
- package/resources/assets/styles/README.md +19 -0
- package/resources/assets/styles/docs/main.css +1 -0
- package/resources/assets/styles/docs/overrides.css +1 -0
- package/resources/assets/styles/docs/vars.css +8 -0
- package/resources/assets/styles/main.css +1419 -0
- package/resources/components/Button.stx +70 -0
- package/resources/components/Buttons/BaseButton.stx +39 -0
- package/resources/components/Buttons/Counter.stx +28 -0
- package/resources/components/Buttons/ToggleDark.stx +11 -0
- package/resources/components/Container.stx +10 -0
- package/resources/components/Dashboard/.gitkeep +0 -0
- package/resources/components/Dashboard/Auth/ForgotPassword.stx +127 -0
- package/resources/components/Dashboard/Auth/Login.stx +212 -0
- package/resources/components/Dashboard/Auth/Register.stx +306 -0
- package/resources/components/Dashboard/Avatar.stx +123 -0
- package/resources/components/Dashboard/Billing/ActivePlan.stx +57 -0
- package/resources/components/Dashboard/Billing/CardBrands.stx +32 -0
- package/resources/components/Dashboard/Billing/CardForm.stx +34 -0
- package/resources/components/Dashboard/Billing/OneTimePayment.stx +28 -0
- package/resources/components/Dashboard/Billing/PaymentForm.stx +33 -0
- package/resources/components/Dashboard/Billing/PaymentMethod.stx +66 -0
- package/resources/components/Dashboard/Billing/PaymentMethodList.stx +52 -0
- package/resources/components/Dashboard/Billing/Plans.stx +136 -0
- package/resources/components/Dashboard/Buttons/AppButton.stx +48 -0
- package/resources/components/Dashboard/Buttons/IconButton.stx +20 -0
- package/resources/components/Dashboard/Card.stx +78 -0
- package/resources/components/Dashboard/Chart.stx +75 -0
- package/resources/components/Dashboard/CodeEditor.stx +41 -0
- package/resources/components/Dashboard/Commerce/BulkActionBar.stx +70 -0
- package/resources/components/Dashboard/Commerce/CategoriesTable.stx +133 -0
- package/resources/components/Dashboard/Commerce/CouponsTable.stx +161 -0
- package/resources/components/Dashboard/Commerce/CustomersTable.stx +142 -0
- package/resources/components/Dashboard/Commerce/Delivery/DeliveryRoutesTable.stx +80 -0
- package/resources/components/Dashboard/Commerce/Delivery/DigitalDeliveryTable.stx +85 -0
- package/resources/components/Dashboard/Commerce/Delivery/DriversTable.stx +99 -0
- package/resources/components/Dashboard/Commerce/Delivery/LicenseKeysTable.stx +92 -0
- package/resources/components/Dashboard/Commerce/Delivery/LicenseTemplatesTable.stx +88 -0
- package/resources/components/Dashboard/Commerce/Delivery/Pagination.stx +122 -0
- package/resources/components/Dashboard/Commerce/Delivery/SearchFilter.stx +23 -0
- package/resources/components/Dashboard/Commerce/Delivery/ShippingMethodsTable.stx +80 -0
- package/resources/components/Dashboard/Commerce/Delivery/ShippingRatesTable.stx +59 -0
- package/resources/components/Dashboard/Commerce/Delivery/ShippingZonesTable.stx +71 -0
- package/resources/components/Dashboard/Commerce/Delivery/TabNavigation.stx +36 -0
- package/resources/components/Dashboard/Commerce/Forms/CouponsForm.stx +191 -0
- package/resources/components/Dashboard/Commerce/OrdersTable.stx +131 -0
- package/resources/components/Dashboard/Commerce/ProductsTable.stx +170 -0
- package/resources/components/Dashboard/CreateRecordModal.stx +363 -0
- package/resources/components/Dashboard/DashboardLayout.stx +155 -0
- package/resources/components/Dashboard/Deployments/ActivityFeed.stx +54 -0
- package/resources/components/Dashboard/Deployments/DeployScript.stx +23 -0
- package/resources/components/Dashboard/Deployments/DeploymentHistory.stx +97 -0
- package/resources/components/Dashboard/Deployments/DeploymentList.stx +94 -0
- package/resources/components/Dashboard/Deployments/LiveTerminalOutput.stx +18 -0
- package/resources/components/Dashboard/Elements/Dropdown.stx +57 -0
- package/resources/components/Dashboard/Email/EmailActivityChart.stx +111 -0
- package/resources/components/Dashboard/Email/EmailCompose.stx +72 -0
- package/resources/components/Dashboard/Email/EmailDetail.stx +105 -0
- package/resources/components/Dashboard/Email/EmailList.stx +117 -0
- package/resources/components/Dashboard/Email/EmailSearch.stx +40 -0
- package/resources/components/Dashboard/Email/EmailSidebar.stx +133 -0
- package/resources/components/Dashboard/GlobalSearch.stx +124 -0
- package/resources/components/Dashboard/MobileSidebar.stx +47 -0
- package/resources/components/Dashboard/Modals/BaseModal.stx +50 -0
- package/resources/components/Dashboard/Modals/Popups/Alert.stx +112 -0
- package/resources/components/Dashboard/Modals/Popups/Toast.stx +70 -0
- package/resources/components/Dashboard/Modals/ToastWrapper.stx +35 -0
- package/resources/components/Dashboard/Monitoring/ErrorDetailModal.stx +228 -0
- package/resources/components/Dashboard/Monitoring/ErrorsTable.stx +184 -0
- package/resources/components/Dashboard/Navbar.stx +194 -0
- package/resources/components/Dashboard/NavbarModern.stx +188 -0
- package/resources/components/Dashboard/NotificationErrorModal.stx +105 -0
- package/resources/components/Dashboard/NotificationStatusBadge.stx +20 -0
- package/resources/components/Dashboard/Pagination.stx +90 -0
- package/resources/components/Dashboard/Queue/QueueTable.stx +127 -0
- package/resources/components/Dashboard/Settings/Forms/AIForm.stx +126 -0
- package/resources/components/Dashboard/Settings/Forms/AnalyticsForm.stx +52 -0
- package/resources/components/Dashboard/Settings/Forms/AppForm.stx +157 -0
- package/resources/components/Dashboard/Settings/Forms/CLIForm.stx +66 -0
- package/resources/components/Dashboard/Settings/Forms/CacheForm.stx +253 -0
- package/resources/components/Dashboard/Settings/Forms/CloudForm.stx +441 -0
- package/resources/components/Dashboard/Settings/Forms/DNSForm.stx +307 -0
- package/resources/components/Dashboard/Settings/Forms/DatabaseForm.stx +168 -0
- package/resources/components/Dashboard/Settings/Forms/EmailForm.stx +100 -0
- package/resources/components/Dashboard/Settings/Forms/FileSystemForm.stx +259 -0
- package/resources/components/Dashboard/Settings/Forms/HashingForm.stx +119 -0
- package/resources/components/Dashboard/Settings/Forms/LibraryForm.stx +389 -0
- package/resources/components/Dashboard/Settings/Forms/QueueForm.stx +219 -0
- package/resources/components/Dashboard/Settings/Forms/SearchEngineForm.stx +48 -0
- package/resources/components/Dashboard/Settings/Forms/SecurityForm.stx +143 -0
- package/resources/components/Dashboard/Settings/Forms/ServicesForm.stx +194 -0
- package/resources/components/Dashboard/Settings/Forms/StorageForm.stx +191 -0
- package/resources/components/Dashboard/Settings/Forms/TeamsForm.stx +33 -0
- package/resources/components/Dashboard/Settings/SettingsFormManager.stx +181 -0
- package/resources/components/Dashboard/SettingsHeader.stx +88 -0
- package/resources/components/Dashboard/SettingsSidebar.stx +234 -0
- package/resources/components/Dashboard/Sidebar.stx +23 -0
- package/resources/components/Dashboard/SidebarModern.stx +249 -0
- package/resources/components/Dashboard/Skeleton/LoadingCard.stx +15 -0
- package/resources/components/Dashboard/Skeleton/LoadingDetails.stx +26 -0
- package/resources/components/Dashboard/Table.stx +82 -0
- package/resources/components/Dashboard/TerminalContainer.stx +97 -0
- package/resources/components/Dashboard/Tooltip.stx +166 -0
- package/resources/components/Dashboard/Transaction/index.stx +88 -0
- package/resources/components/Dashboard/UI/ActivityTable.stx +54 -0
- package/resources/components/Dashboard/UI/Avatar.stx +102 -0
- package/resources/components/Dashboard/UI/Badge.stx +66 -0
- package/resources/components/Dashboard/UI/Button.stx +73 -0
- package/resources/components/Dashboard/UI/Card.stx +51 -0
- package/resources/components/Dashboard/UI/ChartCard.stx +36 -0
- package/resources/components/Dashboard/UI/Checkbox.stx +74 -0
- package/resources/components/Dashboard/UI/ConfirmDialog.stx +74 -0
- package/resources/components/Dashboard/UI/DataTable.stx +45 -0
- package/resources/components/Dashboard/UI/Dropdown.stx +72 -0
- package/resources/components/Dashboard/UI/DropdownItem.stx +80 -0
- package/resources/components/Dashboard/UI/EmptyState.stx +50 -0
- package/resources/components/Dashboard/UI/FilterBar.stx +48 -0
- package/resources/components/Dashboard/UI/Input.stx +77 -0
- package/resources/components/Dashboard/UI/Modal.stx +75 -0
- package/resources/components/Dashboard/UI/PageHeader.stx +69 -0
- package/resources/components/Dashboard/UI/PageLayout.stx +84 -0
- package/resources/components/Dashboard/UI/Pagination.stx +126 -0
- package/resources/components/Dashboard/UI/QuickLinks.stx +31 -0
- package/resources/components/Dashboard/UI/RouterLink.stx +31 -0
- package/resources/components/Dashboard/UI/Select.stx +84 -0
- package/resources/components/Dashboard/UI/ServiceHealth.stx +38 -0
- package/resources/components/Dashboard/UI/StatsCard.stx +79 -0
- package/resources/components/Dashboard/UI/Table.stx +143 -0
- package/resources/components/Dashboard/UI/Tabs.stx +45 -0
- package/resources/components/Dashboard/UI/Textarea.stx +93 -0
- package/resources/components/Dashboard/UI/Toggle.stx +84 -0
- package/resources/components/Dashboard/UI/WindowControls.stx +135 -0
- package/resources/components/Dashboard/Widget.stx +89 -0
- package/resources/components/Dashboard/WindowControls.stx +119 -0
- package/resources/components/Dashboard/index.ts +106 -0
- package/resources/components/Docs/Demo/ComboboxCode.md +114 -0
- package/resources/components/Docs/Demo/ComboboxDemo.stx +91 -0
- package/resources/components/Docs/Demo/DialogCode.md +42 -0
- package/resources/components/Docs/Demo/DialogDemo.stx +76 -0
- package/resources/components/Docs/Demo/DocsPlayground.stx +39 -0
- package/resources/components/Docs/Demo/DropdownCode.md +109 -0
- package/resources/components/Docs/Demo/DropdownDemo.stx +82 -0
- package/resources/components/Docs/Demo/Hero.stx +100 -0
- package/resources/components/Docs/Demo/ListboxCode.md +87 -0
- package/resources/components/Docs/Demo/ListboxDemo.stx +59 -0
- package/resources/components/Docs/Demo/NotificationCode.md +173 -0
- package/resources/components/Docs/Demo/NotificationDemo.stx +99 -0
- package/resources/components/Docs/Demo/PopoverCode.md +161 -0
- package/resources/components/Docs/Demo/PopoverDemo.stx +96 -0
- package/resources/components/Docs/Demo/RadioGroupCode.md +98 -0
- package/resources/components/Docs/Demo/RadioGroupDemo.stx +53 -0
- package/resources/components/Docs/Demo/StepperCode.md +216 -0
- package/resources/components/Docs/Demo/StepperDemo.stx +137 -0
- package/resources/components/Docs/Demo/SwitchCode.md +24 -0
- package/resources/components/Docs/Demo/SwitchDemo.stx +28 -0
- package/resources/components/Docs/Home.stx +7 -0
- package/resources/components/Docs/HomeContributors.stx +23 -0
- package/resources/components/Docs/HomeSponsors.stx +17 -0
- package/resources/components/Docs/HomeTeam.stx +18 -0
- package/resources/components/Docs/TeamMember.stx +79 -0
- package/resources/components/Email/EmailButton.stx +32 -0
- package/resources/components/Email/EmailDivider.stx +20 -0
- package/resources/components/Email/EmailImage.stx +24 -0
- package/resources/components/Email/EmailLayout.stx +55 -0
- package/resources/components/Email/EmailLink.stx +22 -0
- package/resources/components/Email/EmailSection.stx +20 -0
- package/resources/components/Email/EmailText.stx +30 -0
- package/resources/components/Forum/ForumBreadcrumb.stx +38 -0
- package/resources/components/Forum/ForumCategory.stx +16 -0
- package/resources/components/Forum/ForumCategoryItem.stx +46 -0
- package/resources/components/Forum/ForumLayout.stx +36 -0
- package/resources/components/Forum/ForumPagination.stx +39 -0
- package/resources/components/Forum/ForumPost.stx +71 -0
- package/resources/components/Forum/ForumReplyForm.stx +76 -0
- package/resources/components/Forum/ForumSidebar.stx +86 -0
- package/resources/components/Forum/ForumTopicItem.stx +77 -0
- package/resources/components/Forum/ForumTopicList.stx +23 -0
- package/resources/components/HelloWorld.stx +253 -0
- package/resources/components/Logo.stx +10 -0
- package/resources/components/Marketing/CallToAction.stx +30 -0
- package/resources/components/Marketing/ComingSoon.stx +155 -0
- package/resources/components/Marketing/Faqs.stx +99 -0
- package/resources/components/Marketing/Feature.stx +32 -0
- package/resources/components/Marketing/Fields.stx +28 -0
- package/resources/components/Marketing/Footer.stx +33 -0
- package/resources/components/Marketing/Header.stx +51 -0
- package/resources/components/Marketing/Hero.stx +46 -0
- package/resources/components/Marketing/Layout.stx +26 -0
- package/resources/components/Marketing/NavLink.stx +13 -0
- package/resources/components/Marketing/Plan.stx +43 -0
- package/resources/components/Marketing/Pricing.stx +120 -0
- package/resources/components/Marketing/PrimaryFeatures.stx +80 -0
- package/resources/components/Marketing/PrimaryFeatures2.stx +98 -0
- package/resources/components/Marketing/SecondaryFeatures.stx +80 -0
- package/resources/components/Marketing/Testimonials.stx +120 -0
- package/resources/components/Pagination.stx +149 -0
- package/resources/components/Playground.stx +9 -0
- package/resources/components/README.md +87 -0
- package/resources/components/Storefront/AnnouncementBar.stx +17 -0
- package/resources/components/Storefront/CartDrawer.stx +227 -0
- package/resources/components/Storefront/CheckoutSteps.stx +50 -0
- package/resources/components/Storefront/Footer.stx +81 -0
- package/resources/components/Storefront/Header.stx +66 -0
- package/resources/components/Storefront/OrderSummary.stx +79 -0
- package/resources/components/Storefront/ProductCard.stx +63 -0
- package/resources/components/Storefront/ProductGallery.stx +88 -0
- package/resources/components/Storefront/QuantitySelector.stx +97 -0
- package/resources/components/index.ts +13 -0
- package/resources/emails/email-verification.stx +46 -0
- package/resources/emails/layouts/base.html +113 -0
- package/resources/emails/password-changed.stx +55 -0
- package/resources/emails/password-reset.stx +43 -0
- package/resources/emails/subscription-confirmation.stx +99 -0
- package/resources/emails/welcome.stx +48 -0
- package/resources/functions/README.md +28 -0
- package/resources/functions/counter.ts +13 -0
- package/resources/functions/dark.ts +4 -0
- package/resources/functions/dashboard/analytics.ts +238 -0
- package/resources/functions/dashboard/config-io.ts +316 -0
- package/resources/functions/dashboard/data.ts +375 -0
- package/resources/functions/dashboard/library.ts +250 -0
- package/resources/functions/dashboard/sidebar.ts +537 -0
- package/resources/functions/dashboard/system.ts +150 -0
- package/resources/layouts/403.stx +188 -0
- package/resources/layouts/404.stx +34 -0
- package/resources/layouts/README.md +14 -0
- package/resources/layouts/dashboard/default.stx +20 -0
- package/resources/layouts/dashboard/guest.stx +10 -0
- package/resources/layouts/default.stx +3 -0
- package/resources/layouts/maintenance.stx +11 -0
- package/resources/layouts/storefront.stx +73 -0
- package/resources/layouts/system-tray/default.stx +3 -0
- package/resources/modules/.gitkeep +0 -0
- package/resources/plugins/.gitkeep +0 -0
- package/resources/plugins/preloader.ts +308 -0
- package/resources/types/README.md +3 -0
- package/resources/views/cart.stx +149 -0
- package/resources/views/checkout/contact.stx +101 -0
- package/resources/views/checkout/payment.stx +114 -0
- package/resources/views/checkout/shipping.stx +120 -0
- package/resources/views/coming-soon.stx +9 -0
- package/resources/views/dashboard/custom-page.stx +45 -0
- package/resources/views/dashboard/index.stx +24 -0
- package/resources/views/emails/welcome.stx +0 -0
- package/resources/views/errors/tester.stx +26 -0
- package/resources/views/index.stx +2865 -0
- package/resources/views/orders/[id].stx +130 -0
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
<script>
|
|
2
|
+
interface indexProps {
|
|
3
|
+
transactionHistory?: any[]
|
|
4
|
+
}
|
|
5
|
+
|
|
6
|
+
const { transactionHistory = [] } = defineProps<indexProps>()
|
|
7
|
+
|
|
8
|
+
function formatTimestampDate(timestamp) {
|
|
9
|
+
if (!timestamp) return ''
|
|
10
|
+
const date = new Date(timestamp * 1000)
|
|
11
|
+
return date.toLocaleDateString()
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
function getTransactionType(lineData) {
|
|
15
|
+
return lineData[0]?.plan?.interval || ''
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
function getUnitPrice(lineData) {
|
|
19
|
+
return (Number(lineData[0]?.price?.unit_amount || 0) / 100).toFixed(2)
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
function getLastDigits(paymentIntent) {
|
|
23
|
+
return paymentIntent?.payment_method?.card?.last4 || ''
|
|
24
|
+
}
|
|
25
|
+
</script>
|
|
26
|
+
<div class="sm:flex sm:items-center">
|
|
27
|
+
<div class="sm:flex-auto">
|
|
28
|
+
<h1 class="font-semibold leading-6 text-base text-gray-900">
|
|
29
|
+
Transaction History
|
|
30
|
+
</h1>
|
|
31
|
+
<p class="mt-2 text-gray-700 text-sm">
|
|
32
|
+
A list with all your Stacks-relating transactions.
|
|
33
|
+
</p>
|
|
34
|
+
</div>
|
|
35
|
+
</div>
|
|
36
|
+
|
|
37
|
+
<div class="flow-root mt-8">
|
|
38
|
+
<div class="overflow-x-auto -mx-4 -my-2 sm:-mx-6 lg:-mx-8">
|
|
39
|
+
<div class="inline-block py-2 sm:px-6 lg:px-8 min-w-full align-middle">
|
|
40
|
+
<div class="overflow-hidden ring-1 ring-black ring-opacity-5 sm:rounded-lg shadow">
|
|
41
|
+
<table class="min-w-full divide-gray-300 divide-y">
|
|
42
|
+
<thead class="bg-gray-50">
|
|
43
|
+
<tr>
|
|
44
|
+
<th scope="col" class="pl-4 pr-3 py-3.5 sm:pl-6 font-semibold text-gray-900 text-left text-sm">
|
|
45
|
+
Transaction
|
|
46
|
+
</th>
|
|
47
|
+
<th scope="col" class="px-3 py-3.5 font-semibold text-gray-900 text-left text-sm">
|
|
48
|
+
Date
|
|
49
|
+
</th>
|
|
50
|
+
<th scope="col" class="px-3 py-3.5 font-semibold text-gray-900 text-left text-sm">
|
|
51
|
+
Amount
|
|
52
|
+
</th>
|
|
53
|
+
<th scope="col" class="px-3 py-3.5 font-semibold text-gray-900 text-left text-sm">
|
|
54
|
+
Payment Method
|
|
55
|
+
</th>
|
|
56
|
+
<th scope="col" class="relative pl-3 pr-4 py-3.5 sm:pr-6">
|
|
57
|
+
<span class="sr-only">Edit</span>
|
|
58
|
+
</th>
|
|
59
|
+
</tr>
|
|
60
|
+
</thead>
|
|
61
|
+
|
|
62
|
+
<tbody class="bg-white divide-gray-200 divide-y">
|
|
63
|
+
@foreach(transactionHistory as transaction, index)
|
|
64
|
+
<tr>
|
|
65
|
+
<td class="pl-4 pr-3 py-4 sm:pl-6 font-medium text-gray-900 text-sm whitespace-nowrap">
|
|
66
|
+
Dashboard Subscription <em class="italic">({{ getTransactionType(transaction.name) }}ly)</em>
|
|
67
|
+
</td>
|
|
68
|
+
<td class="px-3 py-4 text-gray-500 text-sm whitespace-nowrap">
|
|
69
|
+
{{ formatTimestampDate(transaction.created_at) }}
|
|
70
|
+
</td>
|
|
71
|
+
<td class="px-3 py-4 text-gray-500 text-sm whitespace-nowrap">
|
|
72
|
+
${{ getUnitPrice(transaction.unit_price) }}
|
|
73
|
+
</td>
|
|
74
|
+
<td class="flex items-center px-3 py-4 space-x-2 text-gray-500 text-sm whitespace-nowrap">
|
|
75
|
+
<slot name="cardBrand" />
|
|
76
|
+
<span>**** **** **** {{ getLastDigits(transaction.payment_intent) }}</span>
|
|
77
|
+
</td>
|
|
78
|
+
<td class="relative pl-3 pr-4 py-4 sm:pr-6 font-medium text-right text-sm whitespace-nowrap">
|
|
79
|
+
<a href="#" class="text-blue-600 hover:text-blue-900">View<span class="sr-only">, Transaction</span></a>
|
|
80
|
+
</td>
|
|
81
|
+
</tr>
|
|
82
|
+
@endforeach
|
|
83
|
+
</tbody>
|
|
84
|
+
</table>
|
|
85
|
+
</div>
|
|
86
|
+
</div>
|
|
87
|
+
</div>
|
|
88
|
+
</div>
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
<script server>
|
|
2
|
+
interface ActivityTableProps {
|
|
3
|
+
activities?: any[]
|
|
4
|
+
title?: string
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
const { activities = [], title = 'Recent Activity' } = defineProps<ActivityTableProps>()
|
|
8
|
+
</script>
|
|
9
|
+
<div class="bg-white dark:bg-neutral-800/90 border border-black/5 rounded-xl dark:border-white/5">
|
|
10
|
+
<div class="flex items-center justify-between p-5 border-b border-neutral-200/60 dark:border-white/5">
|
|
11
|
+
<h3 class="font-semibold text-[14px] text-neutral-900 tracking-tight dark:text-white">{{ title }}</h3>
|
|
12
|
+
<slot name="actions" />
|
|
13
|
+
</div>
|
|
14
|
+
|
|
15
|
+
@if(activities.length > 0)
|
|
16
|
+
<div class="overflow-x-auto">
|
|
17
|
+
<table class="min-w-full">
|
|
18
|
+
<thead>
|
|
19
|
+
<tr class="border-b border-neutral-200/60 dark:border-white/5">
|
|
20
|
+
<th class="px-5 py-3 font-semibold text-[11px] text-left text-neutral-500 tracking-wider uppercase dark:text-neutral-400">Type</th>
|
|
21
|
+
<th class="px-5 py-3 font-semibold text-[11px] text-left text-neutral-500 tracking-wider uppercase dark:text-neutral-400">Activity</th>
|
|
22
|
+
<th class="px-5 py-3 font-semibold text-[11px] text-left text-neutral-500 tracking-wider uppercase dark:text-neutral-400">Source</th>
|
|
23
|
+
<th class="px-5 py-3 font-semibold text-[11px] text-left text-neutral-500 tracking-wider uppercase dark:text-neutral-400">Time</th>
|
|
24
|
+
</tr>
|
|
25
|
+
</thead>
|
|
26
|
+
<tbody class="divide-neutral-100 divide-y dark:divide-white/5">
|
|
27
|
+
@foreach(activities as activity)
|
|
28
|
+
<tr class="hover:bg-neutral-50 dark:hover:bg-white/[0.02] transition-colors">
|
|
29
|
+
<td class="px-5 py-3.5">
|
|
30
|
+
<Badge
|
|
31
|
+
variant="{{ activity.type === 'error' ? 'danger' : activity.type === 'order' ? 'primary' : activity.type === 'user' ? 'success' : 'default' }}"
|
|
32
|
+
size="xs"
|
|
33
|
+
>
|
|
34
|
+
{{ activity.type }}
|
|
35
|
+
</Badge>
|
|
36
|
+
</td>
|
|
37
|
+
<td class="px-5 py-3.5 text-[13px] text-neutral-900 dark:text-white">{{ activity.message }}</td>
|
|
38
|
+
<td class="px-5 py-3.5 text-[13px] text-neutral-500 dark:text-neutral-400">{{ activity.user }}</td>
|
|
39
|
+
<td class="px-5 py-3.5 text-[12px] text-neutral-400 dark:text-neutral-500">{{ activity.time }}</td>
|
|
40
|
+
</tr>
|
|
41
|
+
@endforeach
|
|
42
|
+
</tbody>
|
|
43
|
+
</table>
|
|
44
|
+
</div>
|
|
45
|
+
@else
|
|
46
|
+
<div class="py-12 text-center">
|
|
47
|
+
<div class="inline-flex mb-3 p-3 bg-neutral-100 dark:bg-neutral-800 rounded-full">
|
|
48
|
+
<div class="h-6 w-6 text-neutral-400 dark:text-neutral-500 i-hugeicons-activity-01"></div>
|
|
49
|
+
</div>
|
|
50
|
+
<p class="font-medium text-neutral-900 text-sm dark:text-white">No recent activity</p>
|
|
51
|
+
<p class="mt-1 text-[12px] text-neutral-500 dark:text-neutral-400">Activity will appear here as your app is used</p>
|
|
52
|
+
</div>
|
|
53
|
+
@endif
|
|
54
|
+
</div>
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
<script server>
|
|
2
|
+
interface AvatarProps {
|
|
3
|
+
src?: string
|
|
4
|
+
alt?: string
|
|
5
|
+
name?: string
|
|
6
|
+
size?: 'xs' | 'sm' | 'md' | 'lg' | 'xl' | '2xl'
|
|
7
|
+
rounded?: 'sm' | 'md' | 'lg' | 'full'
|
|
8
|
+
status?: 'online' | 'offline' | 'away' | 'busy'
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
const { src = '', alt = '', name = '', size = 'md', rounded = 'full', status = '' } = defineProps<AvatarProps>()
|
|
12
|
+
|
|
13
|
+
const sizeClasses = {
|
|
14
|
+
xs: 'h-5 w-5 text-[10px]',
|
|
15
|
+
sm: 'h-7 w-7 text-[11px]',
|
|
16
|
+
md: 'h-8 w-8 text-[12px]',
|
|
17
|
+
lg: 'h-10 w-10 text-[13px]',
|
|
18
|
+
xl: 'h-12 w-12 text-[14px]',
|
|
19
|
+
'2xl': 'h-14 w-14 text-[16px]'
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
const radiusClasses = {
|
|
23
|
+
sm: 'rounded-md',
|
|
24
|
+
md: 'rounded-lg',
|
|
25
|
+
lg: 'rounded-xl',
|
|
26
|
+
full: 'rounded-full'
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
const statusColors = {
|
|
30
|
+
online: 'bg-green-500',
|
|
31
|
+
offline: 'bg-neutral-400',
|
|
32
|
+
away: 'bg-orange-500',
|
|
33
|
+
busy: 'bg-red-500'
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
const statusSizes = {
|
|
37
|
+
xs: 'h-1.5 w-1.5',
|
|
38
|
+
sm: 'h-2 w-2',
|
|
39
|
+
md: 'h-2 w-2',
|
|
40
|
+
lg: 'h-2.5 w-2.5',
|
|
41
|
+
xl: 'h-3 w-3',
|
|
42
|
+
'2xl': 'h-3.5 w-3.5'
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
// Generate initials from name
|
|
46
|
+
function getInitials(fullName) {
|
|
47
|
+
if (!fullName) return ''
|
|
48
|
+
const parts = fullName.trim().split(/\s+/)
|
|
49
|
+
if (parts.length === 1) return parts[0].slice(0, 2).toUpperCase()
|
|
50
|
+
return (parts[0][0] + parts[parts.length - 1][0]).toUpperCase()
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
const initials = getInitials(name)
|
|
54
|
+
|
|
55
|
+
// Background colors for initials (consistent based on name)
|
|
56
|
+
const bgColors = [
|
|
57
|
+
'bg-red-500/15 text-red-600 dark:bg-red-400/20 dark:text-red-400',
|
|
58
|
+
'bg-orange-500/15 text-orange-600 dark:bg-orange-400/20 dark:text-orange-400',
|
|
59
|
+
'bg-yellow-500/15 text-yellow-600 dark:bg-yellow-400/20 dark:text-yellow-400',
|
|
60
|
+
'bg-green-500/15 text-green-600 dark:bg-green-400/20 dark:text-green-400',
|
|
61
|
+
'bg-teal-500/15 text-teal-600 dark:bg-teal-400/20 dark:text-teal-400',
|
|
62
|
+
'bg-cyan-500/15 text-cyan-600 dark:bg-cyan-400/20 dark:text-cyan-400',
|
|
63
|
+
'bg-blue-500/15 text-blue-600 dark:bg-blue-400/20 dark:text-blue-400',
|
|
64
|
+
'bg-indigo-500/15 text-indigo-600 dark:bg-indigo-400/20 dark:text-indigo-400',
|
|
65
|
+
'bg-purple-500/15 text-purple-600 dark:bg-purple-400/20 dark:text-purple-400',
|
|
66
|
+
'bg-pink-500/15 text-pink-600 dark:bg-pink-400/20 dark:text-pink-400'
|
|
67
|
+
]
|
|
68
|
+
|
|
69
|
+
function getBgColorIndex(fullName) {
|
|
70
|
+
if (!fullName) return 0
|
|
71
|
+
let hash = 0
|
|
72
|
+
for (let i = 0; i < fullName.length; i++) {
|
|
73
|
+
hash = fullName.charCodeAt(i) + ((hash << 5) - hash)
|
|
74
|
+
}
|
|
75
|
+
return Math.abs(hash) % bgColors.length
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
const bgColor = name ? bgColors[getBgColorIndex(name)] : 'bg-black/[0.06] text-neutral-500 dark:bg-white/10 dark:text-neutral-400'
|
|
79
|
+
</script>
|
|
80
|
+
<div class="inline-flex relative flex-shrink-0">
|
|
81
|
+
@if(src)
|
|
82
|
+
<img
|
|
83
|
+
src="{{ src }}"
|
|
84
|
+
alt="{{ alt || name || 'Avatar' }}"
|
|
85
|
+
class="object-cover {{ sizeClasses[size] }} {{ radiusClasses[rounded] }}"
|
|
86
|
+
>
|
|
87
|
+
@else
|
|
88
|
+
<div class="inline-flex items-center justify-center font-medium {{ sizeClasses[size] }} {{ radiusClasses[rounded] }} {{ bgColor }}">
|
|
89
|
+
@if(initials)
|
|
90
|
+
<span>{{ initials }}</span>
|
|
91
|
+
@else
|
|
92
|
+
<svg class="h-1/2 w-1/2 text-neutral-400" fill="currentColor" viewBox="0 0 20 20">
|
|
93
|
+
<path fill-rule="evenodd" d="M10 9a3 3 0 100-6 3 3 0 000 6zm-7 9a7 7 0 1114 0H3z" clip-rule="evenodd"></path>
|
|
94
|
+
</svg>
|
|
95
|
+
@endif
|
|
96
|
+
</div>
|
|
97
|
+
@endif
|
|
98
|
+
|
|
99
|
+
@if(status)
|
|
100
|
+
<span class="absolute bottom-0 right-0 rounded-full ring-2 ring-white dark:ring-neutral-900 {{ statusColors[status] }} {{ statusSizes[size] }}"></span>
|
|
101
|
+
@endif
|
|
102
|
+
</div>
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
<script server>
|
|
2
|
+
interface BadgeProps {
|
|
3
|
+
variant?: 'default' | 'primary' | 'success' | 'warning' | 'danger' | 'info'
|
|
4
|
+
size?: 'xs' | 'sm' | 'md' | 'lg'
|
|
5
|
+
rounded?: 'default' | 'full'
|
|
6
|
+
outline?: boolean
|
|
7
|
+
dot?: boolean
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
const { variant = 'default', size = 'sm', rounded = 'full', outline = false, dot = false } = defineProps<BadgeProps>()
|
|
11
|
+
// `text` was removed as a prop because `text` is auto-imported as a
|
|
12
|
+
// global from @stacksjs/validation (the schema text() validator). Even
|
|
13
|
+
// when no caller passes `text`, the global shadows the prop default and
|
|
14
|
+
// `{{ text }}` rendered the validator function source into every Badge.
|
|
15
|
+
// Use the slot for the badge label instead.
|
|
16
|
+
|
|
17
|
+
const sizeClasses = {
|
|
18
|
+
xs: 'text-[10px] px-1.5 py-0.5',
|
|
19
|
+
sm: 'text-[11px] px-2 py-0.5',
|
|
20
|
+
md: 'text-[12px] px-2.5 py-0.5',
|
|
21
|
+
lg: 'text-[13px] px-3 py-1'
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
const solidVariants = {
|
|
25
|
+
default: 'bg-black/[0.06] text-neutral-600 dark:bg-white/10 dark:text-neutral-300',
|
|
26
|
+
primary: 'bg-blue-500/15 text-blue-600 dark:bg-blue-400/20 dark:text-blue-400',
|
|
27
|
+
success: 'bg-green-500/15 text-green-600 dark:bg-green-400/20 dark:text-green-400',
|
|
28
|
+
warning: 'bg-orange-500/15 text-orange-600 dark:bg-orange-400/20 dark:text-orange-400',
|
|
29
|
+
danger: 'bg-red-500/15 text-red-600 dark:bg-red-400/20 dark:text-red-400',
|
|
30
|
+
info: 'bg-cyan-500/15 text-cyan-600 dark:bg-cyan-400/20 dark:text-cyan-400'
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
const outlineVariants = {
|
|
34
|
+
default: 'border border-black/15 text-neutral-600 dark:border-white/20 dark:text-neutral-300',
|
|
35
|
+
primary: 'border border-blue-500/40 text-blue-600 dark:border-blue-400/50 dark:text-blue-400',
|
|
36
|
+
success: 'border border-green-500/40 text-green-600 dark:border-green-400/50 dark:text-green-400',
|
|
37
|
+
warning: 'border border-orange-500/40 text-orange-600 dark:border-orange-400/50 dark:text-orange-400',
|
|
38
|
+
danger: 'border border-red-500/40 text-red-600 dark:border-red-400/50 dark:text-red-400',
|
|
39
|
+
info: 'border border-cyan-500/40 text-cyan-600 dark:border-cyan-400/50 dark:text-cyan-400'
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
const dotColors = {
|
|
43
|
+
default: 'bg-neutral-400 dark:bg-neutral-500',
|
|
44
|
+
primary: 'bg-blue-500 dark:bg-blue-400',
|
|
45
|
+
success: 'bg-green-500 dark:bg-green-400',
|
|
46
|
+
warning: 'bg-orange-500 dark:bg-orange-400',
|
|
47
|
+
danger: 'bg-red-500 dark:bg-red-400',
|
|
48
|
+
info: 'bg-cyan-500 dark:bg-cyan-400'
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
const badgeClass = [
|
|
52
|
+
'inline-flex items-center font-medium tracking-tight',
|
|
53
|
+
'transition-all duration-150',
|
|
54
|
+
sizeClasses[size],
|
|
55
|
+
rounded === 'full' ? 'rounded-full' : 'rounded-md',
|
|
56
|
+
outline ? outlineVariants[variant] : solidVariants[variant]
|
|
57
|
+
].join(' ')
|
|
58
|
+
|
|
59
|
+
const dotClass = 'w-1.5 h-1.5 rounded-full mr-1.5 ' + dotColors[variant]
|
|
60
|
+
</script>
|
|
61
|
+
<span class="{{ badgeClass }}">
|
|
62
|
+
@if(dot)
|
|
63
|
+
<span class="{{ dotClass }}"></span>
|
|
64
|
+
@endif
|
|
65
|
+
<slot />
|
|
66
|
+
</span>
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
<script server>
|
|
2
|
+
interface ButtonProps {
|
|
3
|
+
variant?: 'primary' | 'secondary' | 'outline' | 'ghost' | 'danger' | 'success'
|
|
4
|
+
size?: 'xs' | 'sm' | 'md' | 'lg'
|
|
5
|
+
disabled?: boolean
|
|
6
|
+
loading?: boolean
|
|
7
|
+
fullWidth?: boolean
|
|
8
|
+
iconOnly?: boolean
|
|
9
|
+
href?: string
|
|
10
|
+
type?: string
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
const { variant = 'primary', size = 'md', disabled = false, loading = false, fullWidth = false, iconOnly = false, href = '', type = 'button' } = defineProps<ButtonProps>()
|
|
14
|
+
|
|
15
|
+
// Variant classes
|
|
16
|
+
const variantClasses = {
|
|
17
|
+
primary: 'bg-gradient-to-b from-blue-500 to-blue-600 text-white shadow-sm shadow-blue-600/25 hover:from-blue-400 hover:to-blue-500 active:from-blue-600 active:to-blue-700 dark:from-blue-600 dark:to-blue-700 dark:hover:from-blue-500 dark:hover:to-blue-600',
|
|
18
|
+
secondary: 'bg-white/80 dark:bg-white/10 text-neutral-800 dark:text-neutral-100 border border-black/10 dark:border-white/10 shadow-sm hover:bg-white dark:hover:bg-white/15 active:bg-neutral-100 dark:active:bg-white/5',
|
|
19
|
+
outline: 'bg-transparent text-neutral-700 dark:text-neutral-200 border border-black/15 dark:border-white/15 hover:bg-black/5 dark:hover:bg-white/8 active:bg-black/10 dark:active:bg-white/10',
|
|
20
|
+
ghost: 'bg-transparent text-neutral-600 dark:text-neutral-300 hover:bg-black/5 dark:hover:bg-white/8 active:bg-black/10 dark:active:bg-white/12',
|
|
21
|
+
danger: 'bg-gradient-to-b from-red-500 to-red-600 text-white shadow-sm shadow-red-600/25 hover:from-red-400 hover:to-red-500 active:from-red-600 active:to-red-700',
|
|
22
|
+
success: 'bg-gradient-to-b from-green-500 to-green-600 text-white shadow-sm shadow-green-600/25 hover:from-green-400 hover:to-green-500 active:from-green-600 active:to-green-700'
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
// Size classes
|
|
26
|
+
const sizeClasses = {
|
|
27
|
+
xs: 'text-[11px] px-2 py-1 rounded-md gap-1 h-6',
|
|
28
|
+
sm: 'text-[12px] px-2.5 py-1 rounded-md gap-1.5 h-7',
|
|
29
|
+
md: 'text-[13px] px-3 py-1.5 rounded-lg gap-1.5 h-8',
|
|
30
|
+
lg: 'text-[14px] px-4 py-2 rounded-lg gap-2 h-9'
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
const iconOnlySizes = {
|
|
34
|
+
xs: 'h-6 w-6 rounded-md',
|
|
35
|
+
sm: 'h-7 w-7 rounded-md',
|
|
36
|
+
md: 'h-8 w-8 rounded-lg',
|
|
37
|
+
lg: 'h-9 w-9 rounded-lg'
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
const buttonClass = [
|
|
41
|
+
'inline-flex items-center justify-center',
|
|
42
|
+
'font-medium tracking-tight',
|
|
43
|
+
'transition-all duration-150',
|
|
44
|
+
'select-none',
|
|
45
|
+
'focus:outline-none focus-visible:ring-2 focus-visible:ring-blue-500/40 focus-visible:ring-offset-0',
|
|
46
|
+
'disabled:opacity-40 disabled:cursor-not-allowed disabled:pointer-events-none',
|
|
47
|
+
'active:scale-[0.98]',
|
|
48
|
+
fullWidth ? 'w-full' : '',
|
|
49
|
+
iconOnly ? iconOnlySizes[size] : sizeClasses[size],
|
|
50
|
+
variantClasses[variant]
|
|
51
|
+
].join(' ')
|
|
52
|
+
</script>
|
|
53
|
+
@if(href && href.length > 0)
|
|
54
|
+
<a href="{{ href }}" class="{{ buttonClass }}" aria-disabled="{{ disabled ? 'true' : 'false' }}">
|
|
55
|
+
@if(loading)
|
|
56
|
+
<svg class="animate-spin h-3.5 w-3.5 {{ iconOnly ? '' : '-ml-0.5 mr-1.5' }}" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24">
|
|
57
|
+
<circle class="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" stroke-width="4"></circle>
|
|
58
|
+
<path class="opacity-75" fill="currentColor" d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"></path>
|
|
59
|
+
</svg>
|
|
60
|
+
@endif
|
|
61
|
+
<slot />
|
|
62
|
+
</a>
|
|
63
|
+
@else
|
|
64
|
+
<button type="{{ type }}" class="{{ buttonClass }}" {{ (disabled || loading) ? 'disabled' : '' }}>
|
|
65
|
+
@if(loading)
|
|
66
|
+
<svg class="animate-spin h-3.5 w-3.5 {{ iconOnly ? '' : '-ml-0.5 mr-1.5' }}" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24">
|
|
67
|
+
<circle class="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" stroke-width="4"></circle>
|
|
68
|
+
<path class="opacity-75" fill="currentColor" d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"></path>
|
|
69
|
+
</svg>
|
|
70
|
+
@endif
|
|
71
|
+
<slot />
|
|
72
|
+
</button>
|
|
73
|
+
@endif
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
<script server>
|
|
2
|
+
interface CardProps {
|
|
3
|
+
variant?: 'default' | 'elevated' | 'outline' | 'ghost' | 'vibrancy'
|
|
4
|
+
padding?: 'none' | 'sm' | 'md' | 'lg' | 'xl'
|
|
5
|
+
rounded?: 'sm' | 'md' | 'lg' | 'xl' | '2xl' | '3xl'
|
|
6
|
+
hoverable?: boolean
|
|
7
|
+
clickable?: boolean
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
const { variant = 'default', padding = 'md', rounded = 'lg', hoverable = false, clickable = false } = defineProps<CardProps>()
|
|
11
|
+
|
|
12
|
+
const variantClasses = {
|
|
13
|
+
default: 'bg-white dark:bg-neutral-800/90 border border-stone-200/80 dark:border-white/5 shadow-sm shadow-stone-200/50 dark:shadow-black/20',
|
|
14
|
+
elevated: 'bg-white dark:bg-neutral-800 shadow-lg shadow-stone-200/60 dark:shadow-black/30 border border-stone-200/60 dark:border-white/10',
|
|
15
|
+
outline: 'bg-transparent border border-stone-200/80 dark:border-white/10',
|
|
16
|
+
ghost: 'bg-stone-50/50 dark:bg-white/[0.05] border border-transparent',
|
|
17
|
+
vibrancy: 'bg-white/60 dark:bg-neutral-800/60 backdrop-blur-xl backdrop-saturate-150 border border-stone-200/60 dark:border-white/10 shadow-sm shadow-stone-200/50'
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
const paddingClasses = {
|
|
21
|
+
none: '',
|
|
22
|
+
sm: 'p-2.5',
|
|
23
|
+
md: 'p-4',
|
|
24
|
+
lg: 'p-5',
|
|
25
|
+
xl: 'p-6'
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
const roundedClasses = {
|
|
29
|
+
sm: 'rounded-md',
|
|
30
|
+
md: 'rounded-lg',
|
|
31
|
+
lg: 'rounded-xl',
|
|
32
|
+
xl: 'rounded-2xl',
|
|
33
|
+
'2xl': 'rounded-[20px]',
|
|
34
|
+
'3xl': 'rounded-[24px]'
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
const hoverClass = (hoverable || clickable) ? 'hover:shadow-md hover:shadow-stone-300/60 dark:hover:shadow-black/25 hover:border-stone-300/80 dark:hover:border-white/15' : ''
|
|
38
|
+
const clickableClass = clickable ? 'cursor-pointer active:scale-[0.98] active:shadow-sm' : ''
|
|
39
|
+
|
|
40
|
+
const cardClass = [
|
|
41
|
+
'transition-all duration-150',
|
|
42
|
+
variantClasses[variant],
|
|
43
|
+
paddingClasses[padding],
|
|
44
|
+
roundedClasses[rounded],
|
|
45
|
+
hoverClass,
|
|
46
|
+
clickableClass
|
|
47
|
+
].join(' ')
|
|
48
|
+
</script>
|
|
49
|
+
<div class="{{ cardClass }}">
|
|
50
|
+
<slot />
|
|
51
|
+
</div>
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
<script server>
|
|
2
|
+
interface ChartCardProps {
|
|
3
|
+
title?: string
|
|
4
|
+
subtitle?: string
|
|
5
|
+
height?: string
|
|
6
|
+
loading?: boolean
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
const { title = '', subtitle = '', height = '300px', loading = false } = defineProps<ChartCardProps>()
|
|
10
|
+
</script>
|
|
11
|
+
<div class="bg-white dark:bg-neutral-800/90 border border-black/5 rounded-xl dark:border-white/5">
|
|
12
|
+
@if(title)
|
|
13
|
+
<div class="flex items-center justify-between p-5 border-b border-neutral-200/60 dark:border-white/5">
|
|
14
|
+
<div>
|
|
15
|
+
<h3 class="font-semibold text-[14px] text-neutral-900 tracking-tight dark:text-white">{{ title }}</h3>
|
|
16
|
+
@if(subtitle)
|
|
17
|
+
<p class="mt-0.5 text-[12px] text-neutral-500 dark:text-neutral-400">{{ subtitle }}</p>
|
|
18
|
+
@endif
|
|
19
|
+
</div>
|
|
20
|
+
<div class="flex gap-2 items-center">
|
|
21
|
+
<slot name="controls" />
|
|
22
|
+
</div>
|
|
23
|
+
</div>
|
|
24
|
+
@endif
|
|
25
|
+
<div class="relative p-5" style="height: {{ height }}">
|
|
26
|
+
@if(loading)
|
|
27
|
+
<div class="flex absolute inset-0 z-10 items-center justify-center bg-white/80 dark:bg-neutral-800/80 rounded-b-xl">
|
|
28
|
+
<svg class="h-6 w-6 text-blue-500 animate-spin" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24">
|
|
29
|
+
<circle class="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" stroke-width="4"></circle>
|
|
30
|
+
<path class="opacity-75" fill="currentColor" d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"></path>
|
|
31
|
+
</svg>
|
|
32
|
+
</div>
|
|
33
|
+
@endif
|
|
34
|
+
<slot />
|
|
35
|
+
</div>
|
|
36
|
+
</div>
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
<script server>
|
|
2
|
+
interface CheckboxProps {
|
|
3
|
+
checked?: boolean
|
|
4
|
+
label?: string
|
|
5
|
+
description?: string
|
|
6
|
+
disabled?: boolean
|
|
7
|
+
indeterminate?: boolean
|
|
8
|
+
size?: 'sm' | 'md' | 'lg'
|
|
9
|
+
error?: string
|
|
10
|
+
name?: string
|
|
11
|
+
id?: string
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
const { checked = false, label = '', description = '', disabled = false, indeterminate = false, size = 'md', error = '', name = '', id = '' } = defineProps<CheckboxProps>()
|
|
15
|
+
|
|
16
|
+
const sizeClasses = {
|
|
17
|
+
sm: { checkbox: 'h-4 w-4', text: 'text-sm', desc: 'text-xs' },
|
|
18
|
+
md: { checkbox: 'h-5 w-5', text: 'text-sm', desc: 'text-sm' },
|
|
19
|
+
lg: { checkbox: 'h-6 w-6', text: 'text-base', desc: 'text-sm' }
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
const checkboxId = id || 'checkbox-' + Math.random().toString(36).slice(2, 11)
|
|
23
|
+
</script>
|
|
24
|
+
<div class="relative flex {{ label || description ? 'gap-3' : '' }} {{ disabled ? 'opacity-60 cursor-not-allowed' : '' }}">
|
|
25
|
+
<div class="flex items-start pt-0.5">
|
|
26
|
+
<input
|
|
27
|
+
type="checkbox"
|
|
28
|
+
id="{{ checkboxId }}"
|
|
29
|
+
name="{{ name }}"
|
|
30
|
+
class="sr-only peer"
|
|
31
|
+
@if(checked) checked @endif
|
|
32
|
+
@if(disabled) disabled @endif
|
|
33
|
+
>
|
|
34
|
+
<label
|
|
35
|
+
for="{{ checkboxId }}"
|
|
36
|
+
class="{{ sizeClasses[size].checkbox }} relative rounded transition-all duration-150 flex items-center justify-center border-2 {{ disabled ? '' : 'cursor-pointer' }} peer-checked:bg-blue-600 peer-checked:border-blue-600 bg-white dark:bg-neutral-900 border-neutral-300 dark:border-neutral-600 hover:border-blue-400 dark:hover:border-blue-500 {{ error ? 'border-red-500' : '' }}"
|
|
37
|
+
>
|
|
38
|
+
<svg class="{{ sizeClasses[size].checkbox }} text-white hidden peer-checked:block" viewBox="0 0 20 20" fill="currentColor">
|
|
39
|
+
<path fill-rule="evenodd" d="M16.707 5.293a1 1 0 010 1.414l-8 8a1 1 0 01-1.414 0l-4-4a1 1 0 011.414-1.414L8 12.586l7.293-7.293a1 1 0 011.414 0z" clip-rule="evenodd"></path>
|
|
40
|
+
</svg>
|
|
41
|
+
</label>
|
|
42
|
+
</div>
|
|
43
|
+
|
|
44
|
+
@if(label || description)
|
|
45
|
+
<div class="flex-1 min-w-0">
|
|
46
|
+
@if(label)
|
|
47
|
+
<label
|
|
48
|
+
for="{{ checkboxId }}"
|
|
49
|
+
class="{{ sizeClasses[size].text }} font-medium {{ disabled ? 'text-neutral-400 dark:text-neutral-500 cursor-not-allowed' : 'text-neutral-700 dark:text-neutral-200 cursor-pointer' }}"
|
|
50
|
+
>
|
|
51
|
+
{{ label }}
|
|
52
|
+
</label>
|
|
53
|
+
@endif
|
|
54
|
+
@if(description)
|
|
55
|
+
<p class="{{ sizeClasses[size].desc }} mt-0.5 {{ disabled ? 'text-neutral-300 dark:text-neutral-600' : 'text-neutral-500 dark:text-neutral-400' }}">
|
|
56
|
+
{{ description }}
|
|
57
|
+
</p>
|
|
58
|
+
@endif
|
|
59
|
+
</div>
|
|
60
|
+
@endif
|
|
61
|
+
</div>
|
|
62
|
+
|
|
63
|
+
@if(error)
|
|
64
|
+
<p class="mt-1.5 text-red-600 text-sm dark:text-red-400">{{ error }}</p>
|
|
65
|
+
@endif
|
|
66
|
+
<style>
|
|
67
|
+
input:checked + label {
|
|
68
|
+
background-color: rgb(37 99 235);
|
|
69
|
+
border-color: rgb(37 99 235);
|
|
70
|
+
}
|
|
71
|
+
input:checked + label svg {
|
|
72
|
+
display: block;
|
|
73
|
+
}
|
|
74
|
+
</style>
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
<script server>
|
|
2
|
+
interface ConfirmDialogProps {
|
|
3
|
+
isOpen?: boolean
|
|
4
|
+
title?: string
|
|
5
|
+
description?: string
|
|
6
|
+
confirmLabel?: string
|
|
7
|
+
cancelLabel?: string
|
|
8
|
+
variant?: 'danger' | 'warning'
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
const { isOpen = false, title = 'Are you sure?', description = 'This action cannot be undone.', confirmLabel = 'Delete', cancelLabel = 'Cancel', variant = 'danger' } = defineProps<ConfirmDialogProps>()
|
|
12
|
+
|
|
13
|
+
const iconClasses = {
|
|
14
|
+
danger: 'bg-red-500/15 text-red-600 dark:bg-red-400/20 dark:text-red-400',
|
|
15
|
+
warning: 'bg-orange-500/15 text-orange-600 dark:bg-orange-400/20 dark:text-orange-400'
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
const iconNames = {
|
|
19
|
+
danger: 'i-hugeicons-alert-02',
|
|
20
|
+
warning: 'i-hugeicons-alert-circle'
|
|
21
|
+
}
|
|
22
|
+
</script>
|
|
23
|
+
@if(isOpen)
|
|
24
|
+
<div ref="pageRoot" class="fixed inset-0 overflow-y-auto z-50">
|
|
25
|
+
<div class="fixed inset-0 bg-black/50 backdrop-blur-sm" data-modal-overlay></div>
|
|
26
|
+
|
|
27
|
+
<div class="flex items-center justify-center p-4 min-h-full">
|
|
28
|
+
<div class="relative p-6 max-w-md w-full bg-white dark:bg-neutral-900 rounded-xl shadow-2xl">
|
|
29
|
+
<div class="flex gap-4 items-start">
|
|
30
|
+
<div class="p-2.5 rounded-lg flex-shrink-0 {{ iconClasses[variant] }}">
|
|
31
|
+
<div class="{{ iconNames[variant] }} w-5 h-5"></div>
|
|
32
|
+
</div>
|
|
33
|
+
<div class="flex-1 min-w-0">
|
|
34
|
+
<h3 class="font-semibold text-lg text-neutral-900 dark:text-white">
|
|
35
|
+
{{ title }}
|
|
36
|
+
</h3>
|
|
37
|
+
<p class="mt-1 text-neutral-500 text-sm dark:text-neutral-400">
|
|
38
|
+
{{ description }}
|
|
39
|
+
</p>
|
|
40
|
+
</div>
|
|
41
|
+
</div>
|
|
42
|
+
|
|
43
|
+
<div class="flex gap-2 items-center justify-end mt-6">
|
|
44
|
+
<button
|
|
45
|
+
type="button"
|
|
46
|
+
class="inline-flex items-center justify-center px-3 py-1.5 font-medium text-[13px] text-neutral-800 tracking-tight dark:text-neutral-100 bg-white/80 dark:bg-white/10 hover:bg-white dark:hover:bg-white/15 border border-black/10 rounded-lg dark:border-white/10 shadow-sm duration-150 transition-all"
|
|
47
|
+
data-modal-close
|
|
48
|
+
>
|
|
49
|
+
{{ cancelLabel }}
|
|
50
|
+
</button>
|
|
51
|
+
<button
|
|
52
|
+
type="button"
|
|
53
|
+
class="inline-flex items-center justify-center px-3 py-1.5 font-medium text-[13px] text-white tracking-tight bg-gradient-to-b from-red-500 to-red-600 hover:from-red-400 hover:to-red-500 rounded-lg shadow-red-600/25 shadow-sm duration-150 transition-all"
|
|
54
|
+
data-confirm-action
|
|
55
|
+
>
|
|
56
|
+
{{ confirmLabel }}
|
|
57
|
+
</button>
|
|
58
|
+
</div>
|
|
59
|
+
</div>
|
|
60
|
+
</div>
|
|
61
|
+
</div>
|
|
62
|
+
@endif
|
|
63
|
+
<script client>
|
|
64
|
+
var _root = useRef('pageRoot')
|
|
65
|
+
onMount(function() {
|
|
66
|
+
var el = _root.current
|
|
67
|
+
if (!el) return
|
|
68
|
+
el.querySelectorAll('[data-modal-overlay], [data-modal-close]').forEach(function(item) {
|
|
69
|
+
item.addEventListener('click', function() {
|
|
70
|
+
item.closest('.fixed.inset-0')?.remove()
|
|
71
|
+
})
|
|
72
|
+
})
|
|
73
|
+
})
|
|
74
|
+
</script>
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
<script server>
|
|
2
|
+
interface DataTableProps {
|
|
3
|
+
columns?: any[]
|
|
4
|
+
data?: any[]
|
|
5
|
+
striped?: boolean
|
|
6
|
+
emptyTitle?: string
|
|
7
|
+
emptyDescription?: string
|
|
8
|
+
emptyIcon?: string
|
|
9
|
+
hoverable?: boolean
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
const { columns = [], data = [], striped = false, emptyTitle = 'No data found', emptyDescription = '', emptyIcon = 'i-hugeicons-folder-02', hoverable = true } = defineProps<DataTableProps>()
|
|
13
|
+
</script>
|
|
14
|
+
<div class="overflow-x-auto">
|
|
15
|
+
<table class="min-w-full">
|
|
16
|
+
<thead>
|
|
17
|
+
<tr class="border-b border-neutral-200/60 dark:border-white/5">
|
|
18
|
+
@foreach(columns as col)
|
|
19
|
+
<th class="px-4 py-3 text-left text-[11px] font-semibold uppercase tracking-wider text-neutral-500 dark:text-neutral-400 {{ col.class || '' }}">
|
|
20
|
+
{{ col.label }}
|
|
21
|
+
</th>
|
|
22
|
+
@endforeach
|
|
23
|
+
</tr>
|
|
24
|
+
</thead>
|
|
25
|
+
<tbody class="divide-neutral-100 divide-y dark:divide-white/5">
|
|
26
|
+
@if(data.length > 0)
|
|
27
|
+
<slot />
|
|
28
|
+
@else
|
|
29
|
+
<tr>
|
|
30
|
+
<td colspan="{{ columns.length }}" class="px-4 py-12">
|
|
31
|
+
<div class="flex flex-col items-center justify-center text-center">
|
|
32
|
+
<div class="mb-3 p-3 bg-neutral-100 dark:bg-neutral-800 rounded-full">
|
|
33
|
+
<div class="{{ emptyIcon }} w-6 h-6 text-neutral-400 dark:text-neutral-500"></div>
|
|
34
|
+
</div>
|
|
35
|
+
<p class="font-medium text-neutral-900 text-sm dark:text-white">{{ emptyTitle }}</p>
|
|
36
|
+
@if(emptyDescription)
|
|
37
|
+
<p class="mt-1 text-[12px] text-neutral-500 dark:text-neutral-400">{{ emptyDescription }}</p>
|
|
38
|
+
@endif
|
|
39
|
+
</div>
|
|
40
|
+
</td>
|
|
41
|
+
</tr>
|
|
42
|
+
@endif
|
|
43
|
+
</tbody>
|
|
44
|
+
</table>
|
|
45
|
+
</div>
|