@ludoloops/svelteforge 0.2.0 → 0.2.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +2 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -145,7 +145,7 @@ const fullstackFiles = {
|
|
|
145
145
|
"/lib/components/layout/footer.svelte": "<script lang=\"ts\">\n const currentYear = new Date().getFullYear();\n<\/script>\n\n<footer\n class=\"bg-surface-50-950 border-t border-surface-200-800\"\n>\n <div class=\"mx-auto\" style=\"max-width: var(--max-w-footer); padding: var(--footer-py) var(--footer-px)\">\n <div class=\"flex flex-col md:flex-row justify-between items-center\" style=\"gap: var(--gap-xl)\">\n <div class=\"flex flex-col items-center md:items-start\" style=\"gap: var(--gap-lg)\">\n <a\n href=\"/\"\n class=\"text-surface-900-100 hover:text-primary-600-400 transition-colors\"\n style=\"font-size: var(--text-logo); font-weight: var(--weight-title)\"\n >\n SvelteForge\n </a>\n <p class=\"text-surface-600-400 max-w-xs text-center md:text-left\" style=\"font-size: var(--text-body)\">\n A production-ready SvelteKit boilerplate with BetterAuth, Drizzle ORM, and Skeleton UI.\n </p>\n </div>\n\n <div class=\"flex flex-col items-center md:items-end\" style=\"gap: var(--gap-lg)\">\n <div\n class=\"text-surface-500 flex flex-col items-center md:items-end\"\n style=\"font-size: var(--text-caption); gap: var(--gap-xs)\"\n >\n <p>© {currentYear} SvelteForge. All rights reserved.</p>\n </div>\n </div>\n </div>\n </div>\n</footer>\n",
|
|
146
146
|
"/lib/components/layout/navbar.svelte": "<script lang=\"ts\">\n import { AppBar } from '@skeletonlabs/skeleton-svelte';\n import AuthButtons from './auth-buttons.svelte';\n import { themeStore } from '$lib/utils/theme.svelte';\n import { onMount, onDestroy } from 'svelte';\n import MobileMenu from './mobile-menu.svelte';\n import Icon from '$lib/components/icons/Icon.svelte';\n import Sheet from '$lib/components/ui/Sheet.svelte';\n import NotificationBadge from '$lib/components/ui/NotificationBadge.svelte';\n import EmptyState from '$lib/components/ui/EmptyState.svelte';\n import {\n getNotifications,\n getUnreadCount,\n markAsRead,\n markAllRead,\n fetchNotifications,\n timeAgo\n } from '$lib/stores/notification-store.svelte';\n\n interface Props {\n user?: { id: string; name?: string; email: string; role?: string; image?: string } | null;\n }\n\n let { user = null }: Props = $props();\n let mobileMenuOpen = $state(false);\n let notifOpen = $state(false);\n\n // Initialize notifications on mount\n onMount(() => {\n themeStore.init();\n if (user) {\n fetchNotifications();\n }\n });\n\n onDestroy(() => {\n themeStore.destroy();\n });\n\n function closeMobileMenu() {\n mobileMenuOpen = false;\n }\n\n function handleMarkAllRead() {\n markAllRead();\n }\n\n function handleNotificationClick(id: string) {\n markAsRead(id);\n }\n<\/script>\n\n<MobileMenu {user} onClose={closeMobileMenu} open={mobileMenuOpen} />\n\n<AppBar>\n <AppBar.Toolbar class=\"grid-cols-[1fr_auto_1fr]\">\n <AppBar.Lead>\n <a href=\"/\" class=\"text-primary-400-500 hover:text-primary-300-600 transition-colors font-bold\" style=\"font-size: var(--text-logo); font-weight: var(--weight-title)\">\n SvelteForge\n </a>\n </AppBar.Lead>\n\n <AppBar.Headline>\n <!-- Center: empty or breadcrumb -->\n </AppBar.Headline>\n\n <AppBar.Trail>\n <!-- Notification Bell (only for logged-in users) -->\n {#if user}\n <div class=\"relative\">\n <button\n onclick={() => (notifOpen = !notifOpen)}\n class=\"btn-icon text-surface-50-950 hover:bg-surface-200-800 transition-colors relative\"\n aria-label=\"Notifications\"\n >\n <Icon name=\"bell\" size={20} />\n {#if getUnreadCount() > 0}\n <NotificationBadge count={getUnreadCount()} />\n {/if}\n </button>\n </div>\n {/if}\n\n <AuthButtons {user} class=\"hidden md:flex items-center\" />\n\n <!-- Mobile menu toggle -->\n <button\n onclick={() => (mobileMenuOpen = !mobileMenuOpen)}\n class=\"md:hidden btn-icon text-surface-50-950\"\n aria-label=\"Menu\"\n >\n {#if mobileMenuOpen}\n <Icon name=\"x\" size={24} />\n {:else}\n <Icon name=\"menu\" size={24} />\n {/if}\n </button>\n </AppBar.Trail>\n </AppBar.Toolbar>\n</AppBar>\n\n<!-- Notification Sheet -->\n{#if user}\n <Sheet open={notifOpen} side=\"right\" title=\"Notifications\" class=\"bg-surface-50-950\">\n <div class=\"flex flex-col gap-4\">\n <!-- Actions -->\n {#if getUnreadCount() > 0}\n <div class=\"flex items-center justify-between\">\n <span class=\"text-sm text-surface-500\">\n {getUnreadCount()} unread\n </span>\n <button\n onclick={handleMarkAllRead}\n class=\"text-sm text-primary-500 hover:text-primary-600-400 transition-colors font-medium\"\n >\n Mark all read\n </button>\n </div>\n {/if}\n\n <!-- Notification List -->\n {#if getNotifications().length === 0}\n <EmptyState\n icon=\"bell\"\n title=\"No notifications\"\n description=\"You're all caught up! New notifications will appear here.\"\n />\n {:else}\n <div class=\"flex flex-col divide-y divide-surface-200-700\">\n {#each getNotifications() as notif (notif.id)}\n <button\n class=\"flex flex-col gap-1 text-left w-full py-3 px-1 transition-colors hover:bg-surface-100-900 relative\n {!notif.read ? 'border-l-2 border-l-primary-500 pl-2' : 'pl-3'}\"\n onclick={() => handleNotificationClick(notif.id)}\n >\n <div class=\"flex items-center justify-between gap-2\">\n <span class=\"text-sm font-medium {notif.read ? 'text-surface-600-400' : 'text-surface-50-950'}\">\n {notif.title}\n </span>\n {#if !notif.read}\n <span class=\"w-2 h-2 rounded-full bg-primary-500 shrink-0\"></span>\n {/if}\n </div>\n <p class=\"text-xs text-surface-500 line-clamp-2\">\n {notif.message}\n </p>\n <span class=\"text-xs text-surface-400-500 mt-0.5\">\n {timeAgo(notif.createdAt)}\n </span>\n </button>\n {/each}\n </div>\n {/if}\n </div>\n </Sheet>\n{/if}\n",
|
|
147
147
|
"/lib/types.ts": "/**\n * types.ts - Common types shared by all services\n *\n * Centralizes types to avoid duplication\n * and maintain a consistent architecture.\n */\n\n// ============================================================================\n// USER TYPES\n// ============================================================================\n\n/**\n * Options for paginated user queries\n */\nexport interface UserQueryOptions {\n page?: number;\n limit?: number;\n search?: string;\n sortBy?: string;\n sortOrder?: 'asc' | 'desc';\n filter?: string;\n}\n\n/**\n * Paginated result\n */\nexport interface PaginatedResult<T> {\n data: T[];\n total: number;\n page: number;\n limit: number;\n totalPages: number;\n}\n\n/**\n * Data to update for a user\n */\nexport interface UpdateUserData {\n name?: string;\n email?: string;\n image?: string;\n}\n\n// ============================================================================\n// ADMIN USER TYPES\n// ============================================================================\n\nexport interface UpdateUserAsAdminData {\n name?: string;\n email?: string;\n}\n",
|
|
148
|
-
"/app.css": "@import './lib/styles/fonts.css';\n
|
|
148
|
+
"/app.css": "@import './lib/styles/fonts.css';\n@import 'tailwindcss';\n@import '@skeletonlabs/skeleton';\n@import '@skeletonlabs/skeleton-common';\n@import './lib/styles/svelteForge.css';\n@import './lib/styles/tokens.css';\n\n@plugin '@tailwindcss/forms';\n@plugin '@tailwindcss/typography';\n\n/* Dark mode strategy: data attribute (Skeleton native) */\n@custom-variant dark (&:where([data-mode=\"dark\"], [data-mode=\"dark\"] *));\n",
|
|
149
149
|
"/app.html": "<!doctype html>\n<html lang=\"en\" data-theme=\"svelteForge\">\n <head>\n <meta charset=\"utf-8\" />\n <link rel=\"icon\" href=\"%sveltekit.assets%/favicon.ico\" />\n <meta name=\"viewport\" content=\"width=device-width, initial-scale=1\" />\n %sveltekit.head%\n </head>\n <body data-sveltekit-preload-data=\"hover\">\n <div style=\"display: contents\">%sveltekit.body%</div>\n </body>\n</html>\n",
|
|
150
150
|
"/app.d.ts": "import type { Auth } from 'better-auth';\nimport type pino from 'pino';\n\ndeclare global {\n namespace App {\n interface Locals {\n auth: Auth;\n logger: pino.Logger;\n responseStatus?: number;\n rateLimit?: {\n limit: number;\n remaining: number;\n reset: Date;\n };\n session: {\n id: string;\n expiresAt: Date;\n ipAddress?: string;\n userAgent?: string;\n } | null;\n user: {\n id: string;\n email: string;\n emailVerified: boolean;\n name: string;\n image?: string | null;\n role?: string | null;\n banned?: boolean | null;\n banReason?: string | null;\n banExpires?: Date | null;\n } | null;\n }\n }\n}\n\ndeclare module 'better-auth' {\n interface Session {\n user: {\n id: string;\n createdAt: Date;\n updatedAt: Date;\n email: string;\n emailVerified: boolean;\n name: string;\n image?: string | null;\n role?: string | null;\n banned?: boolean | null;\n banReason?: string | null;\n banExpires?: Date | null;\n };\n }\n}\n\nexport {};\n",
|
|
151
151
|
"/tests-setup.ts": "import '@testing-library/jest-dom/vitest';\n"
|
|
@@ -348,6 +348,7 @@ var src_default = defineAddon({
|
|
|
348
348
|
sv.dependency("tailwind-merge", "latest");
|
|
349
349
|
sv.dependency("zod", "latest");
|
|
350
350
|
sv.devDependency("@skeletonlabs/skeleton", "latest");
|
|
351
|
+
sv.devDependency("@skeletonlabs/skeleton-common", "latest");
|
|
351
352
|
sv.devDependency("@skeletonlabs/skeleton-svelte", "latest");
|
|
352
353
|
sv.devDependency("@tailwindcss/forms", "^0.5.0");
|
|
353
354
|
sv.devDependency("@tailwindcss/typography", "^0.5.0");
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ludoloops/svelteforge",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.2",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "sv community addon — 34 theme-aware UI components, admin dashboard, and 3-layer theme system for SvelteKit",
|
|
6
6
|
"author": "Ludo (https://lelab.dev)",
|