@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,55 @@
|
|
|
1
|
+
<script server>
|
|
2
|
+
// Outermost email scaffold (stacksjs/stacks#1901 B1).
|
|
3
|
+
//
|
|
4
|
+
// Wraps content in the table-based body that Outlook + Gmail (Android)
|
|
5
|
+
// require, plus the standard meta block (charset / viewport /
|
|
6
|
+
// X-UA-Compatible / colour-scheme). Two-tone bodyBg / contentBg
|
|
7
|
+
// mirrors the bundled templates: muted page colour outside, white
|
|
8
|
+
// card inside. Named slots: head / header / footer. See README for
|
|
9
|
+
// usage examples.
|
|
10
|
+
//
|
|
11
|
+
// Notes on `defineProps()`: stx fills missing props with an empty
|
|
12
|
+
// string (not `undefined`), so destructure defaults silently no-op
|
|
13
|
+
// for absent props. Use `props.x || fallback` instead — that's the
|
|
14
|
+
// pattern used elsewhere in the bundled email templates.
|
|
15
|
+
interface EmailLayoutProps {
|
|
16
|
+
title?: string
|
|
17
|
+
width?: number | string
|
|
18
|
+
bodyBg?: string
|
|
19
|
+
contentBg?: string
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
const props = defineProps<EmailLayoutProps>()
|
|
23
|
+
const title = props.title || ''
|
|
24
|
+
const width = props.width || 600
|
|
25
|
+
const bodyBg = props.bodyBg || '#f4f4f5'
|
|
26
|
+
const contentBg = props.contentBg || '#ffffff'
|
|
27
|
+
</script>
|
|
28
|
+
|
|
29
|
+
<!DOCTYPE html>
|
|
30
|
+
<html lang="en">
|
|
31
|
+
<head>
|
|
32
|
+
<meta charset="UTF-8">
|
|
33
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
34
|
+
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
|
35
|
+
<meta name="color-scheme" content="light dark">
|
|
36
|
+
<meta name="supported-color-schemes" content="light dark">
|
|
37
|
+
<title>{{ title }}</title>
|
|
38
|
+
<slot name="head" />
|
|
39
|
+
</head>
|
|
40
|
+
<body style="margin:0;padding:0;background-color:{{ bodyBg }};font-family:-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,'Helvetica Neue',Arial,sans-serif;line-height:1.6;-webkit-text-size-adjust:100%;-ms-text-size-adjust:100%;">
|
|
41
|
+
<table role="presentation" cellpadding="0" cellspacing="0" border="0" style="width:100%;border-collapse:collapse;background-color:{{ bodyBg }};">
|
|
42
|
+
<tr>
|
|
43
|
+
<td align="center" style="padding:40px 20px;">
|
|
44
|
+
<table role="presentation" cellpadding="0" cellspacing="0" border="0" style="max-width:{{ width }}px;width:100%;background-color:{{ contentBg }};border-radius:8px;overflow:hidden;box-shadow:0 1px 3px rgba(0,0,0,0.1);">
|
|
45
|
+
<slot name="header" />
|
|
46
|
+
<tr><td style="padding:40px;">
|
|
47
|
+
<slot />
|
|
48
|
+
</td></tr>
|
|
49
|
+
<slot name="footer" />
|
|
50
|
+
</table>
|
|
51
|
+
</td>
|
|
52
|
+
</tr>
|
|
53
|
+
</table>
|
|
54
|
+
</body>
|
|
55
|
+
</html>
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
<script server>
|
|
2
|
+
// Inline email link (stacksjs/stacks#1901 B1).
|
|
3
|
+
//
|
|
4
|
+
// For inline mentions inside paragraphs / sentences — use
|
|
5
|
+
// `<EmailButton>` for CTAs. The brand colour is set explicitly
|
|
6
|
+
// because Gmail / Outlook ignore `<style>` blocks, so unstyled
|
|
7
|
+
// `<a>` falls back to client-default blue / purple.
|
|
8
|
+
interface EmailLinkProps {
|
|
9
|
+
href: string
|
|
10
|
+
color?: string
|
|
11
|
+
underline?: boolean
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
const props = defineProps<EmailLinkProps>()
|
|
15
|
+
const href = props.href || '#'
|
|
16
|
+
const color = props.color || '#3451b2'
|
|
17
|
+
const underline = props.underline === false ? false : true
|
|
18
|
+
const decoration = underline ? 'underline' : 'none'
|
|
19
|
+
</script>
|
|
20
|
+
<a href="{{ href }}" style="color:{{ color }};text-decoration:{{ decoration }};">
|
|
21
|
+
<slot />
|
|
22
|
+
</a>
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
<script server>
|
|
2
|
+
// Email content section (stacksjs/stacks#1901 B1) — a table row used
|
|
3
|
+
// to group content vertically. Stack several to split an email into
|
|
4
|
+
// header / body / CTA / footer blocks.
|
|
5
|
+
interface EmailSectionProps {
|
|
6
|
+
padding?: string
|
|
7
|
+
background?: string
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
const props = defineProps<EmailSectionProps>()
|
|
11
|
+
const padding = props.padding || '0'
|
|
12
|
+
const background = props.background || 'transparent'
|
|
13
|
+
</script>
|
|
14
|
+
<table role="presentation" cellpadding="0" cellspacing="0" border="0" style="width:100%;border-collapse:collapse;background-color:{{ background }};">
|
|
15
|
+
<tr>
|
|
16
|
+
<td style="padding:{{ padding }};">
|
|
17
|
+
<slot />
|
|
18
|
+
</td>
|
|
19
|
+
</tr>
|
|
20
|
+
</table>
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
<script server>
|
|
2
|
+
// Email paragraph (stacksjs/stacks#1901 B1).
|
|
3
|
+
//
|
|
4
|
+
// Wraps text in a paragraph with normalised line-height + colour,
|
|
5
|
+
// and a `size` enum covering the 80% case (sm / md / lg / heading).
|
|
6
|
+
// For arbitrary styling override `color` / `spacing` directly.
|
|
7
|
+
interface EmailTextProps {
|
|
8
|
+
align?: 'left' | 'center' | 'right'
|
|
9
|
+
size?: 'sm' | 'md' | 'lg' | 'heading'
|
|
10
|
+
color?: string
|
|
11
|
+
spacing?: string
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
const props = defineProps<EmailTextProps>()
|
|
15
|
+
const align = props.align || 'left'
|
|
16
|
+
const size = props.size || 'md'
|
|
17
|
+
const color = props.color || (size === 'heading' ? '#111827' : '#4b5563')
|
|
18
|
+
const spacing = props.spacing || '16px'
|
|
19
|
+
|
|
20
|
+
const sizeStyles: Record<string, string> = {
|
|
21
|
+
sm: 'font-size:14px;line-height:1.5;',
|
|
22
|
+
md: 'font-size:16px;line-height:1.6;',
|
|
23
|
+
lg: 'font-size:18px;line-height:1.6;',
|
|
24
|
+
heading: 'font-size:20px;line-height:1.4;font-weight:600;',
|
|
25
|
+
}
|
|
26
|
+
const sizeStyle = sizeStyles[size] || sizeStyles.md
|
|
27
|
+
</script>
|
|
28
|
+
<p style="margin:0 0 {{ spacing }} 0;text-align:{{ align }};color:{{ color }};{{ sizeStyle }}">
|
|
29
|
+
<slot />
|
|
30
|
+
</p>
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
<script>
|
|
2
|
+
interface ForumBreadcrumbProps {
|
|
3
|
+
items?: any[]
|
|
4
|
+
}
|
|
5
|
+
|
|
6
|
+
const { items = [] } = defineProps<ForumBreadcrumbProps>()
|
|
7
|
+
</script>
|
|
8
|
+
<div class="mb-4">
|
|
9
|
+
<nav class="flex" aria-label="Breadcrumb">
|
|
10
|
+
<ol class="inline-flex items-center space-x-1 md:space-x-2">
|
|
11
|
+
@foreach(items as item)
|
|
12
|
+
<li class="inline-flex items-center">
|
|
13
|
+
@if(loop.index > 0)
|
|
14
|
+
<div class="flex items-center">
|
|
15
|
+
<svg class="h-5 w-5 text-gray-400" fill="currentColor" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg">
|
|
16
|
+
<path fill-rule="evenodd" d="M7.293 14.707a1 1 0 010-1.414L10.586 10 7.293 6.707a1 1 0 011.414-1.414l4 4a1 1 0 010 1.414l-4 4a1 1 0 01-1.414 0z" clip-rule="evenodd"></path>
|
|
17
|
+
</svg>
|
|
18
|
+
</div>
|
|
19
|
+
@endif
|
|
20
|
+
@if(item.link)
|
|
21
|
+
<a
|
|
22
|
+
href="{{ item.link }}"
|
|
23
|
+
class="font-medium text-gray-700 text-sm hover:text-blue-600 : ? '' 'ml-1' {{ }} > 0 loop.index"
|
|
24
|
+
>
|
|
25
|
+
{{ item.label }}
|
|
26
|
+
</a>
|
|
27
|
+
@else
|
|
28
|
+
<span
|
|
29
|
+
class="font-medium text-gray-500 text-sm : ? '' 'ml-1' {{ }} > 0 loop.index"
|
|
30
|
+
>
|
|
31
|
+
{{ item.label }}
|
|
32
|
+
</span>
|
|
33
|
+
@endif
|
|
34
|
+
</li>
|
|
35
|
+
@endforeach
|
|
36
|
+
</ol>
|
|
37
|
+
</nav>
|
|
38
|
+
</div>
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
<script>
|
|
2
|
+
interface ForumCategoryProps {
|
|
3
|
+
title?: string
|
|
4
|
+
}
|
|
5
|
+
|
|
6
|
+
const { title = '' } = defineProps<ForumCategoryProps>()
|
|
7
|
+
</script>
|
|
8
|
+
<div class="mb-8">
|
|
9
|
+
<div class="flex items-center px-4 py-3 bg-gray-100 rounded-t-md">
|
|
10
|
+
<h2 class="font-bold text-lg">{{ title }}</h2>
|
|
11
|
+
</div>
|
|
12
|
+
|
|
13
|
+
<div class="border divide-y rounded-b-md">
|
|
14
|
+
<slot />
|
|
15
|
+
</div>
|
|
16
|
+
</div>
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
<script>
|
|
2
|
+
interface ForumCategoryItemProps {
|
|
3
|
+
title?: string
|
|
4
|
+
description?: string
|
|
5
|
+
link?: string
|
|
6
|
+
topicCount?: number
|
|
7
|
+
postCount?: number
|
|
8
|
+
icon?: string
|
|
9
|
+
latestTopic?: any
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
const { title = '', description = '', link = '', topicCount = 0, postCount = 0, icon = 'i-hugeicons-chat', latestTopic = null } = defineProps<ForumCategoryItemProps>()
|
|
13
|
+
</script>
|
|
14
|
+
<div class="flex items-start p-4 hover:bg-gray-50">
|
|
15
|
+
<div class="flex-shrink-0 mr-4">
|
|
16
|
+
<div class="flex items-center justify-center h-10 w-10 text-gray-500 bg-gray-100 rounded-full {{ }} icon"></div>
|
|
17
|
+
</div>
|
|
18
|
+
|
|
19
|
+
<div class="flex-grow min-w-0">
|
|
20
|
+
<h3 class="font-medium">
|
|
21
|
+
<a href="{{ link }}" class="text-primary hover:underline">{{ title }}</a>
|
|
22
|
+
</h3>
|
|
23
|
+
<p class="mt-1 text-gray-600 text-sm">{{ description }}</p>
|
|
24
|
+
|
|
25
|
+
<div class="flex gap-4 items-center mt-2 text-gray-500 text-xs">
|
|
26
|
+
<div class="flex gap-1 items-center">
|
|
27
|
+
<div class="i-hugeicons-file"></div>
|
|
28
|
+
<span>{{ topicCount }} topics</span>
|
|
29
|
+
</div>
|
|
30
|
+
<div class="flex gap-1 items-center">
|
|
31
|
+
<div class="i-hugeicons-chat"></div>
|
|
32
|
+
<span>{{ postCount }} posts</span>
|
|
33
|
+
</div>
|
|
34
|
+
</div>
|
|
35
|
+
</div>
|
|
36
|
+
|
|
37
|
+
@if(latestTopic)
|
|
38
|
+
<div class="flex-shrink-0 ml-4 text-right">
|
|
39
|
+
<a href="{{ latestTopic.link }}" class="font-medium line-clamp-1 text-primary text-sm hover:underline">{{ latestTopic.title }}</a>
|
|
40
|
+
<div class="mt-1 text-gray-500 text-xs">
|
|
41
|
+
{{ latestTopic.timeAgo }} by
|
|
42
|
+
<a href="{{ latestTopic.authorLink }}" class="hover:underline">{{ latestTopic.author }}</a>
|
|
43
|
+
</div>
|
|
44
|
+
</div>
|
|
45
|
+
@endif
|
|
46
|
+
</div>
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
<script>
|
|
2
|
+
interface ForumLayoutProps {
|
|
3
|
+
route?: string
|
|
4
|
+
}
|
|
5
|
+
|
|
6
|
+
const { route = 'forum' } = defineProps<ForumLayoutProps>()
|
|
7
|
+
|
|
8
|
+
function isActiveRoute(currentRoute, targetRoute) {
|
|
9
|
+
return currentRoute === targetRoute
|
|
10
|
+
}
|
|
11
|
+
</script>
|
|
12
|
+
<div class="container mx-auto px-4 py-8">
|
|
13
|
+
<header class="mb-6">
|
|
14
|
+
<div class="flex items-center justify-between mb-4">
|
|
15
|
+
<h1 class="font-bold text-2xl">Stacks Community</h1>
|
|
16
|
+
<div class="flex gap-2 items-center">
|
|
17
|
+
<a href="/forum/new-topic" class="px-4 py-2 text-white bg-primary rounded-md hover:opacity-90">New Topic</a>
|
|
18
|
+
<a href="#" class="px-4 py-2 hover:bg-gray-100 border border-gray-300 rounded-md">Sign In</a>
|
|
19
|
+
</div>
|
|
20
|
+
</div>
|
|
21
|
+
<nav class="flex gap-1 text-sm">
|
|
22
|
+
<a href="/forum" class="px-3 py-2 font-medium' 'hover:bg-gray-100 rounded-md rounded-md' : ? 'bg-gray-100 'forum') {{ }} isActiveRoute(route,">All Discussions</a>
|
|
23
|
+
<a href="/forum?filter=popular" class="px-3 py-2 font-medium' 'hover:bg-gray-100 rounded-md rounded-md' : ? 'bg-gray-100 'forum-popular') {{ }} isActiveRoute(route,">Popular</a>
|
|
24
|
+
<a href="/forum?filter=recent" class="px-3 py-2 font-medium' 'hover:bg-gray-100 rounded-md rounded-md' : ? 'bg-gray-100 'forum-recent') {{ }} isActiveRoute(route,">Recent</a>
|
|
25
|
+
<a href="/forum?filter=solved" class="px-3 py-2 font-medium' 'hover:bg-gray-100 rounded-md rounded-md' : ? 'bg-gray-100 'forum-solved') {{ }} isActiveRoute(route,">Solved</a>
|
|
26
|
+
</nav>
|
|
27
|
+
</header>
|
|
28
|
+
|
|
29
|
+
<main>
|
|
30
|
+
<slot />
|
|
31
|
+
</main>
|
|
32
|
+
|
|
33
|
+
<footer class="mt-12 py-6 text-center text-gray-500 text-sm border-t">
|
|
34
|
+
<p>Stacks Community Forum</p>
|
|
35
|
+
</footer>
|
|
36
|
+
</div>
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
<script>
|
|
2
|
+
interface ForumPaginationProps {
|
|
3
|
+
currentPage?: number
|
|
4
|
+
totalPages?: number
|
|
5
|
+
pages?: any[]
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
const { currentPage = 1, totalPages = 1, pages = [] } = defineProps<ForumPaginationProps>()
|
|
9
|
+
</script>
|
|
10
|
+
<div class="flex items-center justify-center mt-8">
|
|
11
|
+
<nav class="flex gap-1 items-center">
|
|
12
|
+
<a
|
|
13
|
+
href="#"
|
|
14
|
+
class="flex items-center justify-center h-10 w-10 hover:bg-gray-100 border rounded-md cursor-not-allowed' : ? '' 'opacity-50 {{ }} == 1 currentPage"
|
|
15
|
+
data-action="prev-page"
|
|
16
|
+
>
|
|
17
|
+
<span class="i-hugeicons-arrow-left"></span>
|
|
18
|
+
</a>
|
|
19
|
+
|
|
20
|
+
@foreach(pages as page)
|
|
21
|
+
<a
|
|
22
|
+
href="#"
|
|
23
|
+
class="flex items-center justify-center h-10 w-10 text-white' hover:bg-gray-100' rounded-md : ? 'bg-primary 'border {{ }} == currentPage page"
|
|
24
|
+
data-action="go-to-page"
|
|
25
|
+
data-page="{{ page }}"
|
|
26
|
+
>
|
|
27
|
+
{{ page }}
|
|
28
|
+
</a>
|
|
29
|
+
@endforeach
|
|
30
|
+
|
|
31
|
+
<a
|
|
32
|
+
href="#"
|
|
33
|
+
class="flex items-center justify-center h-10 w-10 hover:bg-gray-100 border rounded-md cursor-not-allowed' : ? '' 'opacity-50 {{ }} == currentPage totalPages"
|
|
34
|
+
data-action="next-page"
|
|
35
|
+
>
|
|
36
|
+
<span class="i-hugeicons-arrow-right"></span>
|
|
37
|
+
</a>
|
|
38
|
+
</nav>
|
|
39
|
+
</div>
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
<script>
|
|
2
|
+
interface ForumPostProps {
|
|
3
|
+
id?: string
|
|
4
|
+
authorName?: string
|
|
5
|
+
authorAvatar?: string
|
|
6
|
+
createdAt?: string
|
|
7
|
+
likeCount?: number
|
|
8
|
+
isOriginalPost?: boolean
|
|
9
|
+
title?: string
|
|
10
|
+
isSolved?: boolean
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
const { id = '', authorName = '', authorAvatar = '', createdAt = '', likeCount = 0, isOriginalPost = false, title = '', isSolved = false } = defineProps<ForumPostProps>()
|
|
14
|
+
</script>
|
|
15
|
+
<div id="post-{{ id }}" class="mb-6 border rounded-md">
|
|
16
|
+
<div class="flex items-center justify-between px-4 py-3 bg-gray-50 rounded-t-md">
|
|
17
|
+
<div class="flex gap-2 items-center">
|
|
18
|
+
<img src="{{ authorAvatar }}" alt="{{ authorName }}" class="h-6 w-6 rounded-full">
|
|
19
|
+
<span class="font-medium">{{ authorName }}</span>
|
|
20
|
+
<span class="text-gray-500 text-xs">{{ createdAt }}</span>
|
|
21
|
+
</div>
|
|
22
|
+
|
|
23
|
+
<div class="flex gap-2 items-center">
|
|
24
|
+
@if(isOriginalPost)
|
|
25
|
+
<button class="px-2 py-1 text-xs hover:bg-gray-100 border rounded" data-action="bookmark">
|
|
26
|
+
<span class="mr-1 i-hugeicons-bookmark"></span>
|
|
27
|
+
Bookmark
|
|
28
|
+
</button>
|
|
29
|
+
@endif
|
|
30
|
+
<button class="px-2 py-1 text-xs hover:bg-gray-100 border rounded" data-action="share">
|
|
31
|
+
<span class="mr-1 i-hugeicons-share"></span>
|
|
32
|
+
Share
|
|
33
|
+
</button>
|
|
34
|
+
</div>
|
|
35
|
+
</div>
|
|
36
|
+
|
|
37
|
+
<div class="p-4">
|
|
38
|
+
@if(isOriginalPost)
|
|
39
|
+
<h1 class="mb-4 font-bold text-xl">{{ title }}</h1>
|
|
40
|
+
@endif
|
|
41
|
+
<div class="max-w-none prose">
|
|
42
|
+
<slot />
|
|
43
|
+
</div>
|
|
44
|
+
</div>
|
|
45
|
+
|
|
46
|
+
<div class="flex items-center justify-between px-4 py-3 bg-gray-50 rounded-b-md">
|
|
47
|
+
<div class="flex gap-3 items-center text-gray-500">
|
|
48
|
+
<button class="flex gap-1 items-center hover:text-primary" data-action="like" data-post-id="{{ id }}">
|
|
49
|
+
<span class="i-hugeicons-heart"></span>
|
|
50
|
+
<span>{{ likeCount }}</span>
|
|
51
|
+
</button>
|
|
52
|
+
|
|
53
|
+
<button class="flex gap-1 items-center hover:text-primary" data-action="reply" data-post-id="{{ id }}">
|
|
54
|
+
<span class="i-hugeicons-chat"></span>
|
|
55
|
+
<span>Reply</span>
|
|
56
|
+
</button>
|
|
57
|
+
</div>
|
|
58
|
+
|
|
59
|
+
<div class="flex gap-2 items-center">
|
|
60
|
+
@if(isOriginalPost && !isSolved)
|
|
61
|
+
<button class="px-2 py-1 text-dark text-xs bg-success rounded hover:opacity-90" data-action="mark-solution" data-post-id="{{ id }}">
|
|
62
|
+
Mark as Solution
|
|
63
|
+
</button>
|
|
64
|
+
@endif
|
|
65
|
+
<button class="px-2 py-1 text-xs hover:bg-gray-100 border rounded" data-action="report" data-post-id="{{ id }}">
|
|
66
|
+
<span class="mr-1 i-hugeicons-flag"></span>
|
|
67
|
+
Report
|
|
68
|
+
</button>
|
|
69
|
+
</div>
|
|
70
|
+
</div>
|
|
71
|
+
</div>
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
<script>
|
|
2
|
+
interface ForumReplyFormProps {
|
|
3
|
+
replyContent?: string
|
|
4
|
+
notifyOnReply?: boolean
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
const { replyContent = '', notifyOnReply = true } = defineProps<ForumReplyFormProps>()
|
|
8
|
+
|
|
9
|
+
function canSubmit(content) {
|
|
10
|
+
return content.trim().length > 0
|
|
11
|
+
}
|
|
12
|
+
</script>
|
|
13
|
+
<div class="mb-6 border rounded-md">
|
|
14
|
+
<div class="flex items-center px-4 py-3 bg-gray-50 rounded-t-md">
|
|
15
|
+
<h3 class="font-medium">Post a Reply</h3>
|
|
16
|
+
</div>
|
|
17
|
+
|
|
18
|
+
<div class="p-4">
|
|
19
|
+
<div class="mb-4">
|
|
20
|
+
<div class="flex gap-2 mb-2">
|
|
21
|
+
<button class="px-2 py-1 text-sm hover:bg-gray-100 border rounded" title="Bold" data-action="format" data-format="bold">B</button>
|
|
22
|
+
<button class="px-2 py-1 text-sm hover:bg-gray-100 border rounded" title="Italic" data-action="format" data-format="italic">I</button>
|
|
23
|
+
<button class="px-2 py-1 text-sm hover:bg-gray-100 border rounded" title="Link" data-action="format" data-format="link">
|
|
24
|
+
<span class="i-hugeicons-link"></span>
|
|
25
|
+
</button>
|
|
26
|
+
<button class="px-2 py-1 text-sm hover:bg-gray-100 border rounded" title="Code" data-action="format" data-format="code">
|
|
27
|
+
<span class="i-hugeicons-code"></span>
|
|
28
|
+
</button>
|
|
29
|
+
<button class="px-2 py-1 text-sm hover:bg-gray-100 border rounded" title="Image" data-action="format" data-format="image">
|
|
30
|
+
<span class="i-hugeicons-image"></span>
|
|
31
|
+
</button>
|
|
32
|
+
<button class="px-2 py-1 text-sm hover:bg-gray-100 border rounded" title="Quote" data-action="format" data-format="quote">
|
|
33
|
+
<span class="i-hugeicons-quote"></span>
|
|
34
|
+
</button>
|
|
35
|
+
<button class="px-2 py-1 text-sm hover:bg-gray-100 border rounded" title="List" data-action="format" data-format="list">
|
|
36
|
+
<span class="i-hugeicons-list"></span>
|
|
37
|
+
</button>
|
|
38
|
+
</div>
|
|
39
|
+
<textarea
|
|
40
|
+
name="replyContent"
|
|
41
|
+
class="p-3 min-h-32 w-full border rounded-md focus:outline-none focus:ring-2 focus:ring-primary"
|
|
42
|
+
placeholder="Write your reply here..."
|
|
43
|
+
>{{ replyContent }}</textarea>
|
|
44
|
+
<div class="flex justify-between mt-1 text-gray-500 text-xs">
|
|
45
|
+
<span>Markdown formatting supported</span>
|
|
46
|
+
<span class="character-count">0 characters</span>
|
|
47
|
+
</div>
|
|
48
|
+
</div>
|
|
49
|
+
|
|
50
|
+
<div class="flex items-center justify-between">
|
|
51
|
+
<div class="flex gap-4 items-center">
|
|
52
|
+
<label class="flex items-center text-gray-600 text-sm">
|
|
53
|
+
<input type="checkbox" class="mr-2" name="notifyOnReply" {{ notifyOnReply ? 'checked' : '' }}>
|
|
54
|
+
Notify me of follow-up replies
|
|
55
|
+
</label>
|
|
56
|
+
|
|
57
|
+
<button class="text-gray-600 text-sm hover:text-primary" data-action="formatting-help">
|
|
58
|
+
Formatting Help
|
|
59
|
+
</button>
|
|
60
|
+
</div>
|
|
61
|
+
|
|
62
|
+
<div class="flex gap-2">
|
|
63
|
+
<button class="px-3 py-2 hover:bg-gray-100 border rounded-md" data-action="preview">
|
|
64
|
+
Preview
|
|
65
|
+
</button>
|
|
66
|
+
<button
|
|
67
|
+
class="px-4 py-2 text-white bg-primary rounded-md hover:opacity-90 cursor-not-allowed' : ? '' 'opacity-50 {{ }} canSubmit(replyContent)"
|
|
68
|
+
data-action="submit-reply"
|
|
69
|
+
{{ canSubmit(replyContent) ? '' : 'disabled' }}
|
|
70
|
+
>
|
|
71
|
+
Post Reply
|
|
72
|
+
</button>
|
|
73
|
+
</div>
|
|
74
|
+
</div>
|
|
75
|
+
</div>
|
|
76
|
+
</div>
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
<script>
|
|
2
|
+
interface ForumSidebarProps {
|
|
3
|
+
stats?: string
|
|
4
|
+
popularTopics?: any[]
|
|
5
|
+
onlineUsers?: any[]
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
const { stats = {, popularTopics = [], onlineUsers = [] } = defineProps<ForumSidebarProps>()
|
|
9
|
+
|
|
10
|
+
topics: 0,
|
|
11
|
+
posts: 0,
|
|
12
|
+
members: 0,
|
|
13
|
+
newestMember: ''
|
|
14
|
+
}
|
|
15
|
+
</script>
|
|
16
|
+
<div class="space-y-6">
|
|
17
|
+
<!-- Search -->
|
|
18
|
+
<div class="p-4 border rounded-md">
|
|
19
|
+
<h3 class="mb-3 font-medium">Search</h3>
|
|
20
|
+
<div class="relative">
|
|
21
|
+
<input
|
|
22
|
+
type="text"
|
|
23
|
+
placeholder="Search topics..."
|
|
24
|
+
class="pl-3 pr-10 py-2 w-full border rounded-md focus:outline-none focus:ring-2 focus:ring-primary"
|
|
25
|
+
name="search"
|
|
26
|
+
>
|
|
27
|
+
<button class="absolute right-3 top-2" data-action="search">
|
|
28
|
+
<span class="i-hugeicons-search"></span>
|
|
29
|
+
</button>
|
|
30
|
+
</div>
|
|
31
|
+
</div>
|
|
32
|
+
|
|
33
|
+
<!-- Stats -->
|
|
34
|
+
<div class="p-4 border rounded-md">
|
|
35
|
+
<h3 class="mb-3 font-medium">Forum Stats</h3>
|
|
36
|
+
<div class="space-y-2">
|
|
37
|
+
<div class="flex justify-between">
|
|
38
|
+
<span class="text-gray-600">Topics:</span>
|
|
39
|
+
<span class="font-medium">{{ stats.topics }}</span>
|
|
40
|
+
</div>
|
|
41
|
+
<div class="flex justify-between">
|
|
42
|
+
<span class="text-gray-600">Posts:</span>
|
|
43
|
+
<span class="font-medium">{{ stats.posts }}</span>
|
|
44
|
+
</div>
|
|
45
|
+
<div class="flex justify-between">
|
|
46
|
+
<span class="text-gray-600">Members:</span>
|
|
47
|
+
<span class="font-medium">{{ stats.members }}</span>
|
|
48
|
+
</div>
|
|
49
|
+
<div class="flex justify-between">
|
|
50
|
+
<span class="text-gray-600">Newest Member:</span>
|
|
51
|
+
<a href="#" class="text-primary hover:underline">{{ stats.newestMember }}</a>
|
|
52
|
+
</div>
|
|
53
|
+
</div>
|
|
54
|
+
</div>
|
|
55
|
+
|
|
56
|
+
<!-- Popular Topics -->
|
|
57
|
+
<div class="p-4 border rounded-md">
|
|
58
|
+
<h3 class="mb-3 font-medium">Popular Topics</h3>
|
|
59
|
+
<ul class="space-y-3">
|
|
60
|
+
@foreach(popularTopics as topic)
|
|
61
|
+
<li>
|
|
62
|
+
<a href="{{ topic.link }}" class="block line-clamp-1 text-primary hover:underline">{{ topic.title }}</a>
|
|
63
|
+
<div class="mt-1 text-gray-500 text-xs">
|
|
64
|
+
{{ topic.replyCount }} replies • {{ topic.viewCount }} views
|
|
65
|
+
</div>
|
|
66
|
+
</li>
|
|
67
|
+
@endforeach
|
|
68
|
+
</ul>
|
|
69
|
+
</div>
|
|
70
|
+
|
|
71
|
+
<!-- Online Users -->
|
|
72
|
+
<div class="p-4 border rounded-md">
|
|
73
|
+
<h3 class="mb-3 font-medium">Online Now</h3>
|
|
74
|
+
<div class="flex flex-wrap gap-2">
|
|
75
|
+
@foreach(onlineUsers as user)
|
|
76
|
+
<div class="relative">
|
|
77
|
+
<img src="{{ user.avatar }}" alt="{{ user.name }}" class="h-8 w-8 rounded-full">
|
|
78
|
+
<span class="absolute bottom-0 right-0 h-2.5 w-2.5 bg-green-500 border-2 border-white rounded-full"></span>
|
|
79
|
+
</div>
|
|
80
|
+
@endforeach
|
|
81
|
+
</div>
|
|
82
|
+
<div class="mt-3 text-gray-500 text-xs">
|
|
83
|
+
{{ onlineUsers.length }} users online now
|
|
84
|
+
</div>
|
|
85
|
+
</div>
|
|
86
|
+
</div>
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
<script>
|
|
2
|
+
interface ForumTopicItemProps {
|
|
3
|
+
title?: string
|
|
4
|
+
link?: string
|
|
5
|
+
authorName?: string
|
|
6
|
+
authorAvatar?: string
|
|
7
|
+
createdAt?: string
|
|
8
|
+
viewCount?: number
|
|
9
|
+
replyCount?: number
|
|
10
|
+
likeCount?: number
|
|
11
|
+
isPinned?: boolean
|
|
12
|
+
isSolved?: boolean
|
|
13
|
+
category?: string
|
|
14
|
+
categoryLink?: string
|
|
15
|
+
excerpt?: string
|
|
16
|
+
lastReplyAuthorName?: string
|
|
17
|
+
lastReplyAuthorAvatar?: string
|
|
18
|
+
lastReplyAt?: string
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
const { title = '', link = '', authorName = '', authorAvatar = '', createdAt = '', viewCount = 0, replyCount = 0, likeCount = 0, isPinned = false, isSolved = false, category = '', categoryLink = '', excerpt = '', lastReplyAuthorName = '', lastReplyAuthorAvatar = '', lastReplyAt = '' } = defineProps<ForumTopicItemProps>()
|
|
22
|
+
</script>
|
|
23
|
+
<div class="flex items-start p-4 hover:bg-gray-50">
|
|
24
|
+
<div class="flex-shrink-0 mr-4">
|
|
25
|
+
<img src="{{ authorAvatar }}" alt="{{ authorName }}" class="h-10 w-10 rounded-full">
|
|
26
|
+
</div>
|
|
27
|
+
|
|
28
|
+
<div class="flex-grow min-w-0">
|
|
29
|
+
<div class="flex gap-2 items-center">
|
|
30
|
+
<h3 class="font-medium text-primary hover:underline">
|
|
31
|
+
<a href="{{ link }}">{{ title }}</a>
|
|
32
|
+
</h3>
|
|
33
|
+
@if(isPinned)
|
|
34
|
+
<span class="px-2 py-0.5 text-gray-700 text-xs bg-gray-200 rounded">Pinned</span>
|
|
35
|
+
@endif
|
|
36
|
+
@if(isSolved)
|
|
37
|
+
<span class="px-2 py-0.5 text-dark text-xs bg-success rounded">Solved</span>
|
|
38
|
+
@endif
|
|
39
|
+
</div>
|
|
40
|
+
|
|
41
|
+
<div class="flex items-center mt-1 text-gray-500 text-xs">
|
|
42
|
+
<span>{{ authorName }}</span>
|
|
43
|
+
<span class="mx-1">•</span>
|
|
44
|
+
<span>{{ createdAt }}</span>
|
|
45
|
+
@if(category)
|
|
46
|
+
<span class="mx-1">•</span>
|
|
47
|
+
<a href="{{ categoryLink }}" class="text-gray-700 hover:underline">{{ category }}</a>
|
|
48
|
+
@endif
|
|
49
|
+
</div>
|
|
50
|
+
|
|
51
|
+
@if(excerpt)
|
|
52
|
+
<p class="mt-2 line-clamp-2 text-gray-600 text-sm">{{ excerpt }}</p>
|
|
53
|
+
@endif
|
|
54
|
+
|
|
55
|
+
<div class="flex gap-4 items-center mt-2 text-gray-500 text-xs">
|
|
56
|
+
<div class="flex gap-1 items-center">
|
|
57
|
+
<div class="i-hugeicons-eye"></div>
|
|
58
|
+
<span>{{ viewCount }}</span>
|
|
59
|
+
</div>
|
|
60
|
+
<div class="flex gap-1 items-center">
|
|
61
|
+
<div class="i-hugeicons-chat"></div>
|
|
62
|
+
<span>{{ replyCount }}</span>
|
|
63
|
+
</div>
|
|
64
|
+
<div class="flex gap-1 items-center">
|
|
65
|
+
<div class="i-hugeicons-heart"></div>
|
|
66
|
+
<span>{{ likeCount }}</span>
|
|
67
|
+
</div>
|
|
68
|
+
</div>
|
|
69
|
+
</div>
|
|
70
|
+
|
|
71
|
+
@if(lastReplyAuthorAvatar)
|
|
72
|
+
<div class="flex-shrink-0 ml-4 text-right">
|
|
73
|
+
<img src="{{ lastReplyAuthorAvatar }}" alt="{{ lastReplyAuthorName }}" class="inline-block h-6 w-6 rounded-full">
|
|
74
|
+
<div class="mt-1 text-gray-500 text-xs">{{ lastReplyAt }}</div>
|
|
75
|
+
</div>
|
|
76
|
+
@endif
|
|
77
|
+
</div>
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
<script>
|
|
2
|
+
interface ForumTopicListProps {
|
|
3
|
+
title?: string
|
|
4
|
+
}
|
|
5
|
+
|
|
6
|
+
const { title = '' } = defineProps<ForumTopicListProps>()
|
|
7
|
+
</script>
|
|
8
|
+
<div class="mb-8">
|
|
9
|
+
<div class="flex items-center justify-between px-4 py-3 bg-gray-100 rounded-t-md">
|
|
10
|
+
<h2 class="font-bold text-lg">{{ title }}</h2>
|
|
11
|
+
<div class="flex gap-2 items-center">
|
|
12
|
+
<select class="px-2 py-1 text-sm border rounded" name="sort" data-action="sort-topics">
|
|
13
|
+
<option value="latest">Sort by Latest</option>
|
|
14
|
+
<option value="popular">Sort by Popular</option>
|
|
15
|
+
<option value="unanswered">Sort by Unanswered</option>
|
|
16
|
+
</select>
|
|
17
|
+
</div>
|
|
18
|
+
</div>
|
|
19
|
+
|
|
20
|
+
<div class="border divide-y rounded-b-md">
|
|
21
|
+
<slot />
|
|
22
|
+
</div>
|
|
23
|
+
</div>
|