@classic-homes/theme-svelte 0.1.6 → 0.1.7
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.
|
@@ -1,11 +1,29 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
|
+
/**
|
|
3
|
+
* CardFooter - Footer section for Card component
|
|
4
|
+
*
|
|
5
|
+
* Provides consistent padding and flex layout for card action buttons
|
|
6
|
+
* or summary content.
|
|
7
|
+
*
|
|
8
|
+
* @example
|
|
9
|
+
* <Card>
|
|
10
|
+
* <CardHeader>...</CardHeader>
|
|
11
|
+
* <CardContent>...</CardContent>
|
|
12
|
+
* <CardFooter>
|
|
13
|
+
* <Button>Save</Button>
|
|
14
|
+
* <Button variant="outline">Cancel</Button>
|
|
15
|
+
* </CardFooter>
|
|
16
|
+
* </Card>
|
|
17
|
+
*/
|
|
2
18
|
import type { Snippet } from 'svelte';
|
|
19
|
+
import type { HTMLAttributes } from 'svelte/elements';
|
|
3
20
|
import { cn } from '../utils.js';
|
|
4
21
|
|
|
5
|
-
interface Props {
|
|
22
|
+
interface Props extends HTMLAttributes<HTMLDivElement> {
|
|
23
|
+
/** Additional CSS classes */
|
|
6
24
|
class?: string;
|
|
25
|
+
/** Footer content */
|
|
7
26
|
children: Snippet;
|
|
8
|
-
[key: string]: unknown;
|
|
9
27
|
}
|
|
10
28
|
|
|
11
29
|
let { class: className, children, ...restProps }: Props = $props();
|
|
@@ -1,8 +1,26 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* CardFooter - Footer section for Card component
|
|
3
|
+
*
|
|
4
|
+
* Provides consistent padding and flex layout for card action buttons
|
|
5
|
+
* or summary content.
|
|
6
|
+
*
|
|
7
|
+
* @example
|
|
8
|
+
* <Card>
|
|
9
|
+
* <CardHeader>...</CardHeader>
|
|
10
|
+
* <CardContent>...</CardContent>
|
|
11
|
+
* <CardFooter>
|
|
12
|
+
* <Button>Save</Button>
|
|
13
|
+
* <Button variant="outline">Cancel</Button>
|
|
14
|
+
* </CardFooter>
|
|
15
|
+
* </Card>
|
|
16
|
+
*/
|
|
1
17
|
import type { Snippet } from 'svelte';
|
|
2
|
-
|
|
18
|
+
import type { HTMLAttributes } from 'svelte/elements';
|
|
19
|
+
interface Props extends HTMLAttributes<HTMLDivElement> {
|
|
20
|
+
/** Additional CSS classes */
|
|
3
21
|
class?: string;
|
|
22
|
+
/** Footer content */
|
|
4
23
|
children: Snippet;
|
|
5
|
-
[key: string]: unknown;
|
|
6
24
|
}
|
|
7
25
|
declare const CardFooter: import("svelte").Component<Props, {}, "">;
|
|
8
26
|
type CardFooter = ReturnType<typeof CardFooter>;
|
|
@@ -42,72 +42,77 @@
|
|
|
42
42
|
class: className,
|
|
43
43
|
}: Props = $props();
|
|
44
44
|
|
|
45
|
-
const currentYear = new Date().getFullYear();
|
|
46
|
-
const defaultCopyright = `${currentYear} Classic Homes. All rights reserved.`;
|
|
47
|
-
|
|
48
45
|
const isDark = $derived(variant === 'dark');
|
|
46
|
+
const displayCopyright = $derived(
|
|
47
|
+
copyright || `${new Date().getFullYear()} Classic Homes. All rights reserved.`
|
|
48
|
+
);
|
|
49
49
|
</script>
|
|
50
50
|
|
|
51
51
|
<footer
|
|
52
|
+
aria-label="Site footer"
|
|
52
53
|
class={cn(
|
|
53
54
|
// Base styles
|
|
54
|
-
isDark ? 'bg-
|
|
55
|
+
isDark ? 'bg-gray-600 text-white' : 'bg-muted/30',
|
|
55
56
|
// Border styles - strong accent border or standard
|
|
56
|
-
strongBorder ? 'border-t-[10px] border-
|
|
57
|
+
strongBorder ? 'border-t-[10px] border-gray-500' : 'border-t border-border',
|
|
57
58
|
className
|
|
58
59
|
)}
|
|
59
60
|
>
|
|
60
61
|
<div class="mx-auto max-w-7xl px-4 py-12 sm:px-6 lg:px-8">
|
|
61
62
|
{#if links.length > 0}
|
|
62
|
-
<
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
{
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
<
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
class="
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
stroke
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
63
|
+
<nav aria-label="Footer navigation">
|
|
64
|
+
<div class="grid grid-cols-2 gap-6 sm:grid-cols-3 md:gap-8 lg:grid-cols-4">
|
|
65
|
+
{#each links as section}
|
|
66
|
+
<div>
|
|
67
|
+
{#if section.title}
|
|
68
|
+
<h3 class={cn('text-lg font-bold mb-4', isDark ? 'text-white' : 'text-foreground')}>
|
|
69
|
+
{section.title}
|
|
70
|
+
</h3>
|
|
71
|
+
{/if}
|
|
72
|
+
<ul class="mt-4 space-y-2">
|
|
73
|
+
{#each section.items as item}
|
|
74
|
+
<li>
|
|
75
|
+
<a
|
|
76
|
+
href={item.href}
|
|
77
|
+
class={cn(
|
|
78
|
+
'text-sm transition-colors',
|
|
79
|
+
isDark
|
|
80
|
+
? 'text-white hover:text-primary'
|
|
81
|
+
: 'text-muted-foreground hover:text-foreground'
|
|
82
|
+
)}
|
|
83
|
+
target={item.external ? '_blank' : undefined}
|
|
84
|
+
rel={item.external ? 'noopener noreferrer' : undefined}
|
|
85
|
+
>
|
|
86
|
+
{item.name}
|
|
87
|
+
{#if item.external}
|
|
88
|
+
<span class="sr-only">(opens in new tab)</span>
|
|
89
|
+
<svg
|
|
90
|
+
aria-hidden="true"
|
|
91
|
+
class="ml-1 inline-block h-3 w-3"
|
|
92
|
+
fill="none"
|
|
93
|
+
viewBox="0 0 24 24"
|
|
94
|
+
stroke="currentColor"
|
|
95
|
+
>
|
|
96
|
+
<path
|
|
97
|
+
stroke-linecap="round"
|
|
98
|
+
stroke-linejoin="round"
|
|
99
|
+
stroke-width="2"
|
|
100
|
+
d="M10 6H6a2 2 0 00-2 2v10a2 2 0 002 2h10a2 2 0 002-2v-4M14 4h6m0 0v6m0-6L10 14"
|
|
101
|
+
/>
|
|
102
|
+
</svg>
|
|
103
|
+
{/if}
|
|
104
|
+
</a>
|
|
105
|
+
</li>
|
|
106
|
+
{/each}
|
|
107
|
+
</ul>
|
|
108
|
+
</div>
|
|
109
|
+
{/each}
|
|
110
|
+
</div>
|
|
111
|
+
</nav>
|
|
107
112
|
{/if}
|
|
108
113
|
|
|
109
114
|
{#if children}
|
|
110
|
-
<div class={cn('mt-8 border-t pt-8', isDark ? 'border-gray-
|
|
115
|
+
<div class={cn('mt-8 border-t pt-8', isDark ? 'border-gray-500' : 'border-border')}>
|
|
111
116
|
{@render children()}
|
|
112
117
|
</div>
|
|
113
118
|
{/if}
|
|
@@ -115,7 +120,7 @@
|
|
|
115
120
|
<div
|
|
116
121
|
class={cn(
|
|
117
122
|
'mt-8 flex flex-col items-center justify-between gap-4 border-t pt-8 md:flex-row',
|
|
118
|
-
isDark ? 'border-gray-
|
|
123
|
+
isDark ? 'border-gray-500' : 'border-border'
|
|
119
124
|
)}
|
|
120
125
|
>
|
|
121
126
|
{#if showLogo}
|
|
@@ -123,7 +128,7 @@
|
|
|
123
128
|
{/if}
|
|
124
129
|
|
|
125
130
|
<p class={cn('text-center text-sm', isDark ? 'text-gray-400' : 'text-muted-foreground')}>
|
|
126
|
-
{
|
|
131
|
+
{displayCopyright}
|
|
127
132
|
</p>
|
|
128
133
|
</div>
|
|
129
134
|
</div>
|
|
@@ -246,14 +246,14 @@ export declare function paginatedResponseSchema<T extends z.ZodTypeAny>(itemSche
|
|
|
246
246
|
pageSize: z.ZodNumber;
|
|
247
247
|
totalPages: z.ZodNumber;
|
|
248
248
|
}, "strip", z.ZodTypeAny, {
|
|
249
|
-
items: T["_output"][];
|
|
250
249
|
page: number;
|
|
250
|
+
items: T["_output"][];
|
|
251
251
|
pageSize: number;
|
|
252
252
|
total: number;
|
|
253
253
|
totalPages: number;
|
|
254
254
|
}, {
|
|
255
|
-
items: T["_input"][];
|
|
256
255
|
page: number;
|
|
256
|
+
items: T["_input"][];
|
|
257
257
|
pageSize: number;
|
|
258
258
|
total: number;
|
|
259
259
|
totalPages: number;
|
|
@@ -235,8 +235,16 @@ export interface PublicLayoutProps {
|
|
|
235
235
|
copyright?: string;
|
|
236
236
|
/** Custom logo snippet */
|
|
237
237
|
logo?: Snippet;
|
|
238
|
+
/** Logo subtitle for default logo (e.g., "THEME", "MY HOME") */
|
|
239
|
+
logoSubtitle?: string;
|
|
240
|
+
/** Logo environment indicator for default logo */
|
|
241
|
+
logoEnvironment?: 'local' | 'dev' | 'demo';
|
|
238
242
|
/** Custom header end content */
|
|
239
243
|
headerEnd?: Snippet;
|
|
244
|
+
/** Use strong accent border on footer (10px top border) */
|
|
245
|
+
strongFooterBorder?: boolean;
|
|
246
|
+
/** Use dark footer variant */
|
|
247
|
+
darkFooter?: boolean;
|
|
240
248
|
/** Header search configuration */
|
|
241
249
|
headerSearch?: HeaderSearchConfig;
|
|
242
250
|
/** Main content */
|
|
@@ -332,6 +340,10 @@ export interface HeaderProps {
|
|
|
332
340
|
/** Additional classes */
|
|
333
341
|
class?: string;
|
|
334
342
|
}
|
|
343
|
+
/**
|
|
344
|
+
* Footer visual variant
|
|
345
|
+
*/
|
|
346
|
+
export type FooterVariant = 'default' | 'dark';
|
|
335
347
|
/**
|
|
336
348
|
* Props for Footer component
|
|
337
349
|
*/
|
|
@@ -342,6 +354,10 @@ export interface FooterProps {
|
|
|
342
354
|
copyright?: string;
|
|
343
355
|
/** Show logo in footer */
|
|
344
356
|
showLogo?: boolean;
|
|
357
|
+
/** Use strong accent border (10px top border) */
|
|
358
|
+
strongBorder?: boolean;
|
|
359
|
+
/** Dark variant with brand colors */
|
|
360
|
+
variant?: FooterVariant;
|
|
345
361
|
/** Custom content */
|
|
346
362
|
children?: Snippet;
|
|
347
363
|
/** Additional classes */
|