yaxa-svelte 1.0.0
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 +21 -0
- package/README.md +163 -0
- package/dist/assets/favicon.svg +15 -0
- package/dist/components/elements/Avatar.svelte +106 -0
- package/dist/components/elements/Avatar.svelte.d.ts +40 -0
- package/dist/components/elements/AvatarGroup.svelte +18 -0
- package/dist/components/elements/AvatarGroup.svelte.d.ts +8 -0
- package/dist/components/elements/Badge.svelte +202 -0
- package/dist/components/elements/Badge.svelte.d.ts +75 -0
- package/dist/components/elements/Button.svelte +300 -0
- package/dist/components/elements/Button.svelte.d.ts +109 -0
- package/dist/components/elements/ButtonGroup.svelte +22 -0
- package/dist/components/elements/ButtonGroup.svelte.d.ts +9 -0
- package/dist/components/elements/Chip.svelte +117 -0
- package/dist/components/elements/Chip.svelte.d.ts +15 -0
- package/dist/components/elements/DataTable.svelte +222 -0
- package/dist/components/elements/DataTable.svelte.d.ts +43 -0
- package/dist/components/elements/Icon.svelte +87 -0
- package/dist/components/elements/Icon.svelte.d.ts +10 -0
- package/dist/components/elements/Kbd.svelte +37 -0
- package/dist/components/elements/Kbd.svelte.d.ts +32 -0
- package/dist/components/elements/Link.svelte +63 -0
- package/dist/components/elements/Link.svelte.d.ts +15 -0
- package/dist/components/elements/Logo.svelte +77 -0
- package/dist/components/elements/Logo.svelte.d.ts +9 -0
- package/dist/components/elements/Meter.svelte +87 -0
- package/dist/components/elements/Meter.svelte.d.ts +14 -0
- package/dist/components/elements/Progress.svelte +63 -0
- package/dist/components/elements/Progress.svelte.d.ts +49 -0
- package/dist/components/elements/Skeleton.svelte +12 -0
- package/dist/components/elements/Skeleton.svelte.d.ts +6 -0
- package/dist/components/elements/Spinner.svelte +39 -0
- package/dist/components/elements/Spinner.svelte.d.ts +7 -0
- package/dist/components/forms/Checkbox.svelte +77 -0
- package/dist/components/forms/Checkbox.svelte.d.ts +17 -0
- package/dist/components/forms/ColorPicker.svelte +142 -0
- package/dist/components/forms/ColorPicker.svelte.d.ts +10 -0
- package/dist/components/forms/Form.svelte +84 -0
- package/dist/components/forms/Form.svelte.d.ts +14 -0
- package/dist/components/forms/FormField.svelte +56 -0
- package/dist/components/forms/FormField.svelte.d.ts +14 -0
- package/dist/components/forms/Input.svelte +138 -0
- package/dist/components/forms/Input.svelte.d.ts +58 -0
- package/dist/components/forms/RadioGroup.svelte +74 -0
- package/dist/components/forms/RadioGroup.svelte.d.ts +17 -0
- package/dist/components/forms/Select.svelte +91 -0
- package/dist/components/forms/Select.svelte.d.ts +50 -0
- package/dist/components/forms/Slider.svelte +37 -0
- package/dist/components/forms/Slider.svelte.d.ts +12 -0
- package/dist/components/forms/Switch.svelte +81 -0
- package/dist/components/forms/Switch.svelte.d.ts +53 -0
- package/dist/components/forms/Textarea.svelte +73 -0
- package/dist/components/forms/Textarea.svelte.d.ts +64 -0
- package/dist/components/layout/Card.svelte +89 -0
- package/dist/components/layout/Card.svelte.d.ts +64 -0
- package/dist/components/layout/Container.svelte +36 -0
- package/dist/components/layout/Container.svelte.d.ts +37 -0
- package/dist/components/layout/Divider.svelte +45 -0
- package/dist/components/layout/Divider.svelte.d.ts +11 -0
- package/dist/components/layout/Footer.svelte +96 -0
- package/dist/components/layout/Footer.svelte.d.ts +10 -0
- package/dist/components/layout/Header.svelte +175 -0
- package/dist/components/layout/Header.svelte.d.ts +12 -0
- package/dist/components/layout/Section.svelte +62 -0
- package/dist/components/layout/Section.svelte.d.ts +14 -0
- package/dist/components/layout/YaxaApp.svelte +48 -0
- package/dist/components/layout/YaxaApp.svelte.d.ts +12 -0
- package/dist/components/navigation/Breadcrumb.svelte +58 -0
- package/dist/components/navigation/Breadcrumb.svelte.d.ts +13 -0
- package/dist/components/navigation/CommandPalette.svelte +201 -0
- package/dist/components/navigation/CommandPalette.svelte.d.ts +19 -0
- package/dist/components/navigation/DropdownMenu.svelte +75 -0
- package/dist/components/navigation/DropdownMenu.svelte.d.ts +20 -0
- package/dist/components/navigation/Pagination.svelte +106 -0
- package/dist/components/navigation/Pagination.svelte.d.ts +10 -0
- package/dist/components/navigation/Tabs.svelte +91 -0
- package/dist/components/navigation/Tabs.svelte.d.ts +18 -0
- package/dist/components/overlays/Accordion.svelte +54 -0
- package/dist/components/overlays/Accordion.svelte.d.ts +16 -0
- package/dist/components/overlays/Alert.svelte +110 -0
- package/dist/components/overlays/Alert.svelte.d.ts +37 -0
- package/dist/components/overlays/ContextMenu.svelte +67 -0
- package/dist/components/overlays/ContextMenu.svelte.d.ts +21 -0
- package/dist/components/overlays/Modal.svelte +99 -0
- package/dist/components/overlays/Modal.svelte.d.ts +40 -0
- package/dist/components/overlays/Popover.svelte +33 -0
- package/dist/components/overlays/Popover.svelte.d.ts +11 -0
- package/dist/components/overlays/Slideover.svelte +102 -0
- package/dist/components/overlays/Slideover.svelte.d.ts +37 -0
- package/dist/components/overlays/Tooltip.svelte +39 -0
- package/dist/components/overlays/Tooltip.svelte.d.ts +12 -0
- package/dist/components/saas/AuthCard.svelte +273 -0
- package/dist/components/saas/AuthCard.svelte.d.ts +16 -0
- package/dist/components/saas/PricingCard.svelte +166 -0
- package/dist/components/saas/PricingCard.svelte.d.ts +19 -0
- package/dist/components/saas/PricingTable.svelte +139 -0
- package/dist/components/saas/PricingTable.svelte.d.ts +11 -0
- package/dist/components/saas/SubscriptionCard.svelte +162 -0
- package/dist/components/saas/SubscriptionCard.svelte.d.ts +16 -0
- package/dist/components/saas/UserMenu.svelte +137 -0
- package/dist/components/saas/UserMenu.svelte.d.ts +19 -0
- package/dist/components/seo/Favicons.svelte +22 -0
- package/dist/components/seo/Favicons.svelte.d.ts +8 -0
- package/dist/components/seo/OgImage.svelte +61 -0
- package/dist/components/seo/OgImage.svelte.d.ts +12 -0
- package/dist/components/seo/Seo.svelte +170 -0
- package/dist/components/seo/Seo.svelte.d.ts +21 -0
- package/dist/composables/useAuth.svelte.d.ts +23 -0
- package/dist/composables/useAuth.svelte.js +157 -0
- package/dist/composables/useClipboard.svelte.d.ts +9 -0
- package/dist/composables/useClipboard.svelte.js +36 -0
- package/dist/composables/useColorMode.svelte.d.ts +8 -0
- package/dist/composables/useColorMode.svelte.js +20 -0
- package/dist/composables/useDebounce.svelte.d.ts +3 -0
- package/dist/composables/useDebounce.svelte.js +17 -0
- package/dist/composables/useMediaQuery.svelte.d.ts +3 -0
- package/dist/composables/useMediaQuery.svelte.js +17 -0
- package/dist/composables/useShortcuts.svelte.d.ts +10 -0
- package/dist/composables/useShortcuts.svelte.js +50 -0
- package/dist/composables/useToast.d.ts +19 -0
- package/dist/composables/useToast.js +34 -0
- package/dist/index.d.ts +101 -0
- package/dist/index.js +92 -0
- package/dist/server/auth/hook.d.ts +14 -0
- package/dist/server/auth/hook.js +36 -0
- package/dist/server/auth/index.d.ts +39 -0
- package/dist/server/auth/index.js +69 -0
- package/dist/server/db/index.d.ts +18 -0
- package/dist/server/db/index.js +43 -0
- package/dist/server/db/schema-pg.d.ts +977 -0
- package/dist/server/db/schema-pg.js +83 -0
- package/dist/server/db/schema-sqlite.d.ts +1045 -0
- package/dist/server/db/schema-sqlite.js +83 -0
- package/dist/server/db/types.d.ts +44 -0
- package/dist/server/db/types.js +1 -0
- package/dist/server/email/index.d.ts +27 -0
- package/dist/server/email/index.js +79 -0
- package/dist/server/polar/index.d.ts +29 -0
- package/dist/server/polar/index.js +49 -0
- package/dist/server/polar/webhook.d.ts +16 -0
- package/dist/server/polar/webhook.js +118 -0
- package/dist/site/config.d.ts +63 -0
- package/dist/site/config.js +48 -0
- package/dist/site/context.d.ts +11 -0
- package/dist/site/context.js +23 -0
- package/dist/site/hook.d.ts +15 -0
- package/dist/site/hook.js +38 -0
- package/dist/site/manifest.d.ts +6 -0
- package/dist/site/manifest.js +32 -0
- package/dist/site/og.d.ts +14 -0
- package/dist/site/og.js +116 -0
- package/dist/site/robots.d.ts +10 -0
- package/dist/site/robots.js +54 -0
- package/dist/site/schema.d.ts +67 -0
- package/dist/site/schema.js +67 -0
- package/dist/site/seo-helpers.d.ts +36 -0
- package/dist/site/seo-helpers.js +21 -0
- package/dist/site/sitemap-xsl.d.ts +6 -0
- package/dist/site/sitemap-xsl.js +164 -0
- package/dist/site/sitemap.d.ts +20 -0
- package/dist/site/sitemap.js +61 -0
- package/dist/styles/yaxa.css +84 -0
- package/dist/theme/theme.svelte.d.ts +74 -0
- package/dist/theme/theme.svelte.js +421 -0
- package/dist/utils/cn.d.ts +3 -0
- package/dist/utils/cn.js +3 -0
- package/dist/vite/index.d.ts +20 -0
- package/dist/vite/index.js +29 -0
- package/package.json +108 -0
|
@@ -0,0 +1,222 @@
|
|
|
1
|
+
<script module lang="ts">
|
|
2
|
+
export interface Column<T = any> {
|
|
3
|
+
key: keyof T | string;
|
|
4
|
+
label: string;
|
|
5
|
+
sortable?: boolean;
|
|
6
|
+
class?: string;
|
|
7
|
+
}
|
|
8
|
+
</script>
|
|
9
|
+
|
|
10
|
+
<script lang="ts" generics="T extends Record<string, any>">
|
|
11
|
+
import type { Snippet } from 'svelte';
|
|
12
|
+
import Checkbox from '../forms/Checkbox.svelte';
|
|
13
|
+
import Icon from './Icon.svelte';
|
|
14
|
+
import Skeleton from './Skeleton.svelte';
|
|
15
|
+
|
|
16
|
+
interface Props {
|
|
17
|
+
data: T[];
|
|
18
|
+
columns: Column<T>[];
|
|
19
|
+
loading?: boolean;
|
|
20
|
+
selectable?: boolean;
|
|
21
|
+
selected?: T[];
|
|
22
|
+
searchQuery?: string;
|
|
23
|
+
searchKeys?: (keyof T | string)[];
|
|
24
|
+
emptyText?: string;
|
|
25
|
+
class?: string;
|
|
26
|
+
cell?: Snippet<[T, Column<T>]>;
|
|
27
|
+
empty?: Snippet;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
let {
|
|
31
|
+
data = [],
|
|
32
|
+
columns = [],
|
|
33
|
+
loading = false,
|
|
34
|
+
selectable = false,
|
|
35
|
+
selected = $bindable([]),
|
|
36
|
+
searchQuery = '',
|
|
37
|
+
searchKeys = [],
|
|
38
|
+
emptyText = 'No data available',
|
|
39
|
+
class: className = '',
|
|
40
|
+
cell,
|
|
41
|
+
empty
|
|
42
|
+
}: Props = $props();
|
|
43
|
+
|
|
44
|
+
let sortKey = $state<string | null>(null);
|
|
45
|
+
let sortOrder = $state<'asc' | 'desc'>('asc');
|
|
46
|
+
|
|
47
|
+
function handleSort(key: string) {
|
|
48
|
+
if (sortKey === key) {
|
|
49
|
+
sortOrder = sortOrder === 'asc' ? 'desc' : 'asc';
|
|
50
|
+
} else {
|
|
51
|
+
sortKey = key;
|
|
52
|
+
sortOrder = 'asc';
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
let filteredData = $derived.by(() => {
|
|
57
|
+
let result = [...data];
|
|
58
|
+
|
|
59
|
+
// Filter by search query
|
|
60
|
+
if (searchQuery.trim()) {
|
|
61
|
+
const query = searchQuery.toLowerCase().trim();
|
|
62
|
+
const keys = searchKeys.length > 0 ? searchKeys : columns.map((c) => c.key);
|
|
63
|
+
result = result.filter((item) =>
|
|
64
|
+
keys.some((key) => {
|
|
65
|
+
const val = item[key as keyof T];
|
|
66
|
+
return val !== undefined && val !== null && String(val).toLowerCase().includes(query);
|
|
67
|
+
})
|
|
68
|
+
);
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
// Sort
|
|
72
|
+
if (sortKey) {
|
|
73
|
+
result.sort((a, b) => {
|
|
74
|
+
const valA = a[sortKey as keyof T];
|
|
75
|
+
const valB = b[sortKey as keyof T];
|
|
76
|
+
if (valA === valB) return 0;
|
|
77
|
+
if (valA === undefined || valA === null) return 1;
|
|
78
|
+
if (valB === undefined || valB === null) return -1;
|
|
79
|
+
const comparison = valA > valB ? 1 : -1;
|
|
80
|
+
return sortOrder === 'asc' ? comparison : -comparison;
|
|
81
|
+
});
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
return result;
|
|
85
|
+
});
|
|
86
|
+
|
|
87
|
+
let allSelected = $derived(filteredData.length > 0 && selected.length === filteredData.length);
|
|
88
|
+
|
|
89
|
+
function toggleSelectAll(isChecked: boolean) {
|
|
90
|
+
if (isChecked) {
|
|
91
|
+
selected = [...filteredData];
|
|
92
|
+
} else {
|
|
93
|
+
selected = [];
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
function toggleSelectRow(item: T, isChecked: boolean) {
|
|
98
|
+
if (isChecked) {
|
|
99
|
+
if (!selected.includes(item)) {
|
|
100
|
+
selected = [...selected, item];
|
|
101
|
+
}
|
|
102
|
+
} else {
|
|
103
|
+
selected = selected.filter((i) => i !== item);
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
</script>
|
|
107
|
+
|
|
108
|
+
<div
|
|
109
|
+
class="w-full overflow-hidden rounded-xl border border-neutral-200 bg-white dark:border-neutral-800 dark:bg-neutral-950 {className}"
|
|
110
|
+
>
|
|
111
|
+
<div class="overflow-x-auto">
|
|
112
|
+
<table class="w-full text-left text-sm text-neutral-600 dark:text-neutral-300">
|
|
113
|
+
<!-- Table Header -->
|
|
114
|
+
<thead
|
|
115
|
+
class="border-b border-neutral-200 bg-neutral-50/80 text-sm font-semibold tracking-wider text-neutral-600 uppercase dark:border-neutral-800 dark:bg-neutral-900/80 dark:text-neutral-400"
|
|
116
|
+
>
|
|
117
|
+
<tr>
|
|
118
|
+
{#if selectable}
|
|
119
|
+
<th class="w-10 px-4 py-3">
|
|
120
|
+
<Checkbox
|
|
121
|
+
checked={allSelected}
|
|
122
|
+
onchange={toggleSelectAll}
|
|
123
|
+
aria-label="Select all rows"
|
|
124
|
+
/>
|
|
125
|
+
</th>
|
|
126
|
+
{/if}
|
|
127
|
+
{#each columns as column}
|
|
128
|
+
<th class="px-4 py-3 {column.class || ''}">
|
|
129
|
+
{#if column.sortable}
|
|
130
|
+
<button
|
|
131
|
+
type="button"
|
|
132
|
+
onclick={() => handleSort(String(column.key))}
|
|
133
|
+
class="group inline-flex items-center gap-1 font-semibold tracking-wider uppercase transition hover:text-neutral-900 dark:hover:text-white"
|
|
134
|
+
>
|
|
135
|
+
<span>{column.label}</span>
|
|
136
|
+
<span
|
|
137
|
+
class="text-neutral-400 transition-colors group-hover:text-primary-500 {sortKey ===
|
|
138
|
+
String(column.key)
|
|
139
|
+
? 'text-primary-500'
|
|
140
|
+
: ''}"
|
|
141
|
+
>
|
|
142
|
+
{#if sortKey === String(column.key)}
|
|
143
|
+
<Icon name={sortOrder === 'asc' ? 'chevron-up' : 'chevron-down'} size="xs" />
|
|
144
|
+
{:else}
|
|
145
|
+
<Icon name="chevron-down" size="xs" class="opacity-40" />
|
|
146
|
+
{/if}
|
|
147
|
+
</span>
|
|
148
|
+
</button>
|
|
149
|
+
{:else}
|
|
150
|
+
<span>{column.label}</span>
|
|
151
|
+
{/if}
|
|
152
|
+
</th>
|
|
153
|
+
{/each}
|
|
154
|
+
</tr>
|
|
155
|
+
</thead>
|
|
156
|
+
|
|
157
|
+
<!-- Table Body -->
|
|
158
|
+
<tbody class="divide-y divide-neutral-200/80 dark:divide-neutral-800/80">
|
|
159
|
+
{#if loading}
|
|
160
|
+
{#each Array(5)}
|
|
161
|
+
<tr>
|
|
162
|
+
{#if selectable}
|
|
163
|
+
<td class="px-4 py-3.5">
|
|
164
|
+
<Skeleton class="h-4 w-4 rounded" />
|
|
165
|
+
</td>
|
|
166
|
+
{/if}
|
|
167
|
+
{#each columns}
|
|
168
|
+
<td class="px-4 py-3.5">
|
|
169
|
+
<Skeleton class="h-4 w-24 rounded" />
|
|
170
|
+
</td>
|
|
171
|
+
{/each}
|
|
172
|
+
</tr>
|
|
173
|
+
{/each}
|
|
174
|
+
{:else if filteredData.length === 0}
|
|
175
|
+
<tr>
|
|
176
|
+
<td
|
|
177
|
+
colspan={columns.length + (selectable ? 1 : 0)}
|
|
178
|
+
class="px-4 py-12 text-center text-sm text-neutral-500 dark:text-neutral-400"
|
|
179
|
+
>
|
|
180
|
+
{#if empty}
|
|
181
|
+
{@render empty()}
|
|
182
|
+
{:else}
|
|
183
|
+
<div class="flex flex-col items-center justify-center gap-2">
|
|
184
|
+
<Icon name="search" size="md" class="text-neutral-400" />
|
|
185
|
+
<p>{emptyText}</p>
|
|
186
|
+
</div>
|
|
187
|
+
{/if}
|
|
188
|
+
</td>
|
|
189
|
+
</tr>
|
|
190
|
+
{:else}
|
|
191
|
+
{#each filteredData as item}
|
|
192
|
+
{@const isSelected = selected.includes(item)}
|
|
193
|
+
<tr
|
|
194
|
+
class="transition-colors hover:bg-neutral-50/60 dark:hover:bg-neutral-900/50 {isSelected
|
|
195
|
+
? 'bg-primary-50/40 dark:bg-primary-950/20'
|
|
196
|
+
: ''}"
|
|
197
|
+
>
|
|
198
|
+
{#if selectable}
|
|
199
|
+
<td class="w-10 px-4 py-3.5">
|
|
200
|
+
<Checkbox
|
|
201
|
+
checked={isSelected}
|
|
202
|
+
onchange={(checked) => toggleSelectRow(item, checked)}
|
|
203
|
+
aria-label="Select row"
|
|
204
|
+
/>
|
|
205
|
+
</td>
|
|
206
|
+
{/if}
|
|
207
|
+
{#each columns as column}
|
|
208
|
+
<td class="px-4 py-3.5 {column.class || ''}">
|
|
209
|
+
{#if cell}
|
|
210
|
+
{@render cell(item, column)}
|
|
211
|
+
{:else}
|
|
212
|
+
{item[column.key as keyof T] ?? '—'}
|
|
213
|
+
{/if}
|
|
214
|
+
</td>
|
|
215
|
+
{/each}
|
|
216
|
+
</tr>
|
|
217
|
+
{/each}
|
|
218
|
+
{/if}
|
|
219
|
+
</tbody>
|
|
220
|
+
</table>
|
|
221
|
+
</div>
|
|
222
|
+
</div>
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
export interface Column<T = any> {
|
|
2
|
+
key: keyof T | string;
|
|
3
|
+
label: string;
|
|
4
|
+
sortable?: boolean;
|
|
5
|
+
class?: string;
|
|
6
|
+
}
|
|
7
|
+
import type { Snippet } from 'svelte';
|
|
8
|
+
declare function $$render<T extends Record<string, any>>(): {
|
|
9
|
+
props: {
|
|
10
|
+
data: T[];
|
|
11
|
+
columns: Column<T>[];
|
|
12
|
+
loading?: boolean;
|
|
13
|
+
selectable?: boolean;
|
|
14
|
+
selected?: T[];
|
|
15
|
+
searchQuery?: string;
|
|
16
|
+
searchKeys?: (keyof T | string)[];
|
|
17
|
+
emptyText?: string;
|
|
18
|
+
class?: string;
|
|
19
|
+
cell?: Snippet<[T, Column<T>]>;
|
|
20
|
+
empty?: Snippet;
|
|
21
|
+
};
|
|
22
|
+
exports: {};
|
|
23
|
+
bindings: "selected";
|
|
24
|
+
slots: {};
|
|
25
|
+
events: {};
|
|
26
|
+
};
|
|
27
|
+
declare class __sveltets_Render<T extends Record<string, any>> {
|
|
28
|
+
props(): ReturnType<typeof $$render<T>>['props'];
|
|
29
|
+
events(): ReturnType<typeof $$render<T>>['events'];
|
|
30
|
+
slots(): ReturnType<typeof $$render<T>>['slots'];
|
|
31
|
+
bindings(): "selected";
|
|
32
|
+
exports(): {};
|
|
33
|
+
}
|
|
34
|
+
interface $$IsomorphicComponent {
|
|
35
|
+
new <T extends Record<string, any>>(options: import('svelte').ComponentConstructorOptions<ReturnType<__sveltets_Render<T>['props']>>): import('svelte').SvelteComponent<ReturnType<__sveltets_Render<T>['props']>, ReturnType<__sveltets_Render<T>['events']>, ReturnType<__sveltets_Render<T>['slots']>> & {
|
|
36
|
+
$$bindings?: ReturnType<__sveltets_Render<T>['bindings']>;
|
|
37
|
+
} & ReturnType<__sveltets_Render<T>['exports']>;
|
|
38
|
+
<T extends Record<string, any>>(internal: unknown, props: ReturnType<__sveltets_Render<T>['props']> & {}): ReturnType<__sveltets_Render<T>['exports']>;
|
|
39
|
+
z_$$bindings?: ReturnType<__sveltets_Render<any>['bindings']>;
|
|
40
|
+
}
|
|
41
|
+
declare const DataTable: $$IsomorphicComponent;
|
|
42
|
+
type DataTable<T extends Record<string, any>> = InstanceType<typeof DataTable<T>>;
|
|
43
|
+
export default DataTable;
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import type { Snippet } from 'svelte';
|
|
3
|
+
|
|
4
|
+
interface Props {
|
|
5
|
+
name?: string;
|
|
6
|
+
size?: 'xs' | 'sm' | 'md' | 'lg' | 'xl' | number;
|
|
7
|
+
class?: string;
|
|
8
|
+
children?: Snippet;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
let { name, size = 'md', class: className = '', children }: Props = $props();
|
|
12
|
+
|
|
13
|
+
let sizeClass = $derived.by(() => {
|
|
14
|
+
if (typeof size === 'number') return `w-[${size}px] h-[${size}px]`;
|
|
15
|
+
switch (size) {
|
|
16
|
+
case 'xs':
|
|
17
|
+
return 'w-3.5 h-3.5';
|
|
18
|
+
case 'sm':
|
|
19
|
+
return 'w-4 h-4';
|
|
20
|
+
case 'lg':
|
|
21
|
+
return 'w-6 h-6';
|
|
22
|
+
case 'xl':
|
|
23
|
+
return 'w-8 h-8';
|
|
24
|
+
case 'md':
|
|
25
|
+
default:
|
|
26
|
+
return 'w-5 h-5';
|
|
27
|
+
}
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
// Common built-in SVGs for immediate zero-config use
|
|
31
|
+
const builtInIcons: Record<string, string> = {
|
|
32
|
+
check:
|
|
33
|
+
'<path d="M20 6L9 17l-5-5" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" fill="none"/>',
|
|
34
|
+
cross:
|
|
35
|
+
'<path d="M18 6L6 18M6 6l12 12" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" fill="none"/>',
|
|
36
|
+
'chevron-down':
|
|
37
|
+
'<path d="M6 9l6 6 6-6" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" fill="none"/>',
|
|
38
|
+
'chevron-up':
|
|
39
|
+
'<path d="M18 15l-6-6-6 6" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" fill="none"/>',
|
|
40
|
+
'chevron-right':
|
|
41
|
+
'<path d="M9 18l6-6-6-6" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" fill="none"/>',
|
|
42
|
+
'chevron-left':
|
|
43
|
+
'<path d="M15 18l-6-6 6-6" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" fill="none"/>',
|
|
44
|
+
search:
|
|
45
|
+
'<path d="M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" fill="none"/>',
|
|
46
|
+
sun: '<circle cx="12" cy="12" r="4" stroke="currentColor" stroke-width="2" fill="none"/><path d="M12 2v2M12 20v2M4.93 4.93l1.41 1.41M17.66 17.66l1.41 1.41M2 12h2M20 12h2M6.34 17.66l-1.41 1.41M19.07 4.93l-1.41 1.41" stroke="currentColor" stroke-width="2" stroke-linecap="round"/>',
|
|
47
|
+
moon: '<path d="M21 12.79A9 9 0 1111.21 3 7 7 0 0021 12.79z" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" fill="none"/>',
|
|
48
|
+
computer:
|
|
49
|
+
'<rect x="2" y="3" width="20" height="14" rx="2" stroke="currentColor" stroke-width="2" fill="none"/><line x1="8" y1="21" x2="16" y2="21" stroke="currentColor" stroke-width="2" stroke-linecap="round"/><line x1="12" y1="17" x2="12" y2="21" stroke="currentColor" stroke-width="2"/>',
|
|
50
|
+
sparkles:
|
|
51
|
+
'<path d="M12 2v4M12 18v4M4.93 4.93l2.83 2.83M16.24 16.24l2.83 2.83M2 12h4M18 12h4M4.93 19.07l2.83-2.83M16.24 7.76l2.83-2.83" stroke="currentColor" stroke-width="2" stroke-linecap="round"/>',
|
|
52
|
+
info: '<circle cx="12" cy="12" r="10" stroke="currentColor" stroke-width="2" fill="none"/><line x1="12" y1="16" x2="12" y2="12" stroke="currentColor" stroke-width="2" stroke-linecap="round"/><line x1="12" y1="8" x2="12.01" y2="8" stroke="currentColor" stroke-width="2" stroke-linecap="round"/>',
|
|
53
|
+
alert:
|
|
54
|
+
'<path d="M10.29 3.86L1.82 18a2 2 0 001.71 3h16.94a2 2 0 001.71-3L13.71 3.86a2 2 0 00-3.42 0zM12 9v4m0 4h.01" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" fill="none"/>',
|
|
55
|
+
'external-link':
|
|
56
|
+
'<path d="M18 13v6a2 2 0 01-2 2H5a2 2 0 01-2-2V8a2 2 0 012-2h6M15 3h6v6M10 14L21 3" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" fill="none"/>',
|
|
57
|
+
copy: '<rect x="9" y="9" width="13" height="13" rx="2" stroke="currentColor" stroke-width="2" fill="none"/><path d="M5 15H4a2 2 0 01-2-2V4a2 2 0 012-2h9a2 2 0 012 2v1" stroke="currentColor" stroke-width="2" stroke-linecap="round" fill="none"/>',
|
|
58
|
+
github:
|
|
59
|
+
'<path d="M9 19c-5 1.5-5-2.5-7-3m14 6v-3.87a3.37 3.37 0 00-.94-2.61c3.14-.35 6.44-1.54 6.44-7A5.44 5.44 0 0020 4.77 5.07 5.07 0 0019.91 1S18.73.65 16 2.48a13.38 13.38 0 00-7 0C6.27.65 5.09 1 5.09 1A5.07 5.07 0 005 4.77a5.44 5.44 0 00-1.5 3.78c0 5.42 3.3 6.61 6.44 7A3.37 3.37 0 009 18.13V22" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" fill="none"/>',
|
|
60
|
+
twitter:
|
|
61
|
+
'<path d="M23 3a10.9 10.9 0 01-3.14 1.53 4.48 4.48 0 00-7.86 3v1A10.66 10.66 0 013 4s-4 9 5 13a11.64 11.64 0 01-7 2c9 5 20 0 20-11.5a4.5 4.5 0 00-.08-.83A7.72 7.72 0 0023 3z" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" fill="none"/>'
|
|
62
|
+
};
|
|
63
|
+
</script>
|
|
64
|
+
|
|
65
|
+
{#if children}
|
|
66
|
+
<span class="inline-flex shrink-0 items-center justify-center {sizeClass} {className}">
|
|
67
|
+
{@render children()}
|
|
68
|
+
</span>
|
|
69
|
+
{:else if name && builtInIcons[name]}
|
|
70
|
+
<svg
|
|
71
|
+
class="inline-flex shrink-0 items-center justify-center {sizeClass} {className}"
|
|
72
|
+
viewBox="0 0 24 24"
|
|
73
|
+
fill="none"
|
|
74
|
+
aria-hidden="true"
|
|
75
|
+
>
|
|
76
|
+
{@html builtInIcons[name]}
|
|
77
|
+
</svg>
|
|
78
|
+
{:else}
|
|
79
|
+
<svg
|
|
80
|
+
class="inline-flex shrink-0 items-center justify-center {sizeClass} {className}"
|
|
81
|
+
viewBox="0 0 24 24"
|
|
82
|
+
fill="none"
|
|
83
|
+
aria-hidden="true"
|
|
84
|
+
>
|
|
85
|
+
<circle cx="12" cy="12" r="9" stroke="currentColor" stroke-width="2" stroke-dasharray="4 4" />
|
|
86
|
+
</svg>
|
|
87
|
+
{/if}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { Snippet } from 'svelte';
|
|
2
|
+
interface Props {
|
|
3
|
+
name?: string;
|
|
4
|
+
size?: 'xs' | 'sm' | 'md' | 'lg' | 'xl' | number;
|
|
5
|
+
class?: string;
|
|
6
|
+
children?: Snippet;
|
|
7
|
+
}
|
|
8
|
+
declare const Icon: import("svelte").Component<Props, {}, "">;
|
|
9
|
+
type Icon = ReturnType<typeof Icon>;
|
|
10
|
+
export default Icon;
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
<script module lang="ts">
|
|
2
|
+
import { tv, type VariantProps } from '../../utils/cn';
|
|
3
|
+
import type { Snippet } from 'svelte';
|
|
4
|
+
|
|
5
|
+
export const kbdVariants = tv({
|
|
6
|
+
base: 'inline-flex items-center justify-center font-mono font-medium rounded border border-neutral-300 bg-neutral-100 text-neutral-700 shadow-xs dark:border-neutral-700 dark:bg-neutral-800 dark:text-neutral-300 select-none',
|
|
7
|
+
variants: {
|
|
8
|
+
size: {
|
|
9
|
+
xs: 'h-4 min-w-[16px] px-1 text-[10px]',
|
|
10
|
+
sm: 'h-5 min-w-[20px] px-1.5 text-xs',
|
|
11
|
+
md: 'h-6 min-w-[24px] px-2 text-xs',
|
|
12
|
+
lg: 'h-7 min-w-[28px] px-2.5 text-sm'
|
|
13
|
+
}
|
|
14
|
+
},
|
|
15
|
+
defaultVariants: {
|
|
16
|
+
size: 'sm'
|
|
17
|
+
}
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
export type KbdProps = VariantProps<typeof kbdVariants> & {
|
|
21
|
+
value?: string;
|
|
22
|
+
class?: string;
|
|
23
|
+
children?: Snippet;
|
|
24
|
+
};
|
|
25
|
+
</script>
|
|
26
|
+
|
|
27
|
+
<script lang="ts">
|
|
28
|
+
let { value, size = 'sm', class: className = '', children }: KbdProps = $props();
|
|
29
|
+
</script>
|
|
30
|
+
|
|
31
|
+
<kbd class={kbdVariants({ size, class: className })}>
|
|
32
|
+
{#if value}
|
|
33
|
+
{value}
|
|
34
|
+
{:else if children}
|
|
35
|
+
{@render children()}
|
|
36
|
+
{/if}
|
|
37
|
+
</kbd>
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { type VariantProps } from '../../utils/cn';
|
|
2
|
+
import type { Snippet } from 'svelte';
|
|
3
|
+
export declare const kbdVariants: import("tailwind-variants").TVReturnType<{
|
|
4
|
+
size: {
|
|
5
|
+
xs: "h-4 min-w-[16px] px-1 text-[10px]";
|
|
6
|
+
sm: "h-5 min-w-[20px] px-1.5 text-xs";
|
|
7
|
+
md: "h-6 min-w-[24px] px-2 text-xs";
|
|
8
|
+
lg: "h-7 min-w-[28px] px-2.5 text-sm";
|
|
9
|
+
};
|
|
10
|
+
}, undefined, "inline-flex items-center justify-center font-mono font-medium rounded border border-neutral-300 bg-neutral-100 text-neutral-700 shadow-xs dark:border-neutral-700 dark:bg-neutral-800 dark:text-neutral-300 select-none", {
|
|
11
|
+
size: {
|
|
12
|
+
xs: "h-4 min-w-[16px] px-1 text-[10px]";
|
|
13
|
+
sm: "h-5 min-w-[20px] px-1.5 text-xs";
|
|
14
|
+
md: "h-6 min-w-[24px] px-2 text-xs";
|
|
15
|
+
lg: "h-7 min-w-[28px] px-2.5 text-sm";
|
|
16
|
+
};
|
|
17
|
+
}, undefined, import("tailwind-variants").TVReturnTypeLike<{
|
|
18
|
+
size: {
|
|
19
|
+
xs: "h-4 min-w-[16px] px-1 text-[10px]";
|
|
20
|
+
sm: "h-5 min-w-[20px] px-1.5 text-xs";
|
|
21
|
+
md: "h-6 min-w-[24px] px-2 text-xs";
|
|
22
|
+
lg: "h-7 min-w-[28px] px-2.5 text-sm";
|
|
23
|
+
};
|
|
24
|
+
}, undefined>>;
|
|
25
|
+
export type KbdProps = VariantProps<typeof kbdVariants> & {
|
|
26
|
+
value?: string;
|
|
27
|
+
class?: string;
|
|
28
|
+
children?: Snippet;
|
|
29
|
+
};
|
|
30
|
+
declare const Kbd: import("svelte").Component<KbdProps, {}, "">;
|
|
31
|
+
type Kbd = ReturnType<typeof Kbd>;
|
|
32
|
+
export default Kbd;
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import type { Snippet } from 'svelte';
|
|
3
|
+
import type { HTMLAnchorAttributes } from 'svelte/elements';
|
|
4
|
+
import { page } from '$app/state';
|
|
5
|
+
import Icon from './Icon.svelte';
|
|
6
|
+
|
|
7
|
+
interface Props extends HTMLAnchorAttributes {
|
|
8
|
+
href: string;
|
|
9
|
+
activeClass?: string;
|
|
10
|
+
inactiveClass?: string;
|
|
11
|
+
exact?: boolean;
|
|
12
|
+
external?: boolean;
|
|
13
|
+
showExternalIcon?: boolean;
|
|
14
|
+
class?: string;
|
|
15
|
+
children?: Snippet;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
let {
|
|
19
|
+
href,
|
|
20
|
+
activeClass = 'text-primary-600 dark:text-primary-400 font-semibold',
|
|
21
|
+
inactiveClass = 'text-neutral-600 dark:text-neutral-400 hover:text-neutral-900 dark:hover:text-neutral-100',
|
|
22
|
+
exact = false,
|
|
23
|
+
external,
|
|
24
|
+
showExternalIcon = false,
|
|
25
|
+
class: className = '',
|
|
26
|
+
children,
|
|
27
|
+
...restProps
|
|
28
|
+
}: Props = $props();
|
|
29
|
+
|
|
30
|
+
let isExternal = $derived(
|
|
31
|
+
external ?? (href.startsWith('http://') || href.startsWith('https://') || href.startsWith('//'))
|
|
32
|
+
);
|
|
33
|
+
|
|
34
|
+
let isActive = $derived.by(() => {
|
|
35
|
+
if (isExternal) return false;
|
|
36
|
+
try {
|
|
37
|
+
const currentPath = page.url.pathname;
|
|
38
|
+
if (exact) return currentPath === href;
|
|
39
|
+
return currentPath === href || (href !== '/' && currentPath.startsWith(href));
|
|
40
|
+
} catch {
|
|
41
|
+
return false;
|
|
42
|
+
}
|
|
43
|
+
});
|
|
44
|
+
</script>
|
|
45
|
+
|
|
46
|
+
<a
|
|
47
|
+
{href}
|
|
48
|
+
class="inline-flex items-center gap-1 transition-colors duration-150 {isActive
|
|
49
|
+
? activeClass
|
|
50
|
+
: inactiveClass} {className}"
|
|
51
|
+
aria-current={isActive ? 'page' : undefined}
|
|
52
|
+
target={isExternal ? '_blank' : undefined}
|
|
53
|
+
rel={isExternal ? 'noopener noreferrer' : undefined}
|
|
54
|
+
{...restProps}
|
|
55
|
+
>
|
|
56
|
+
{#if children}
|
|
57
|
+
{@render children()}
|
|
58
|
+
{/if}
|
|
59
|
+
|
|
60
|
+
{#if isExternal && showExternalIcon}
|
|
61
|
+
<Icon name="external-link" size="xs" />
|
|
62
|
+
{/if}
|
|
63
|
+
</a>
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type { Snippet } from 'svelte';
|
|
2
|
+
import type { HTMLAnchorAttributes } from 'svelte/elements';
|
|
3
|
+
interface Props extends HTMLAnchorAttributes {
|
|
4
|
+
href: string;
|
|
5
|
+
activeClass?: string;
|
|
6
|
+
inactiveClass?: string;
|
|
7
|
+
exact?: boolean;
|
|
8
|
+
external?: boolean;
|
|
9
|
+
showExternalIcon?: boolean;
|
|
10
|
+
class?: string;
|
|
11
|
+
children?: Snippet;
|
|
12
|
+
}
|
|
13
|
+
declare const Link: import("svelte").Component<Props, {}, "">;
|
|
14
|
+
type Link = ReturnType<typeof Link>;
|
|
15
|
+
export default Link;
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
interface Props {
|
|
3
|
+
size?: 'xs' | 'sm' | 'md' | 'lg' | 'xl' | number;
|
|
4
|
+
showText?: boolean;
|
|
5
|
+
text?: string;
|
|
6
|
+
class?: string;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
let { size = 'md', showText = false, text = 'Yaxa', class: className = '' }: Props = $props();
|
|
10
|
+
|
|
11
|
+
let sizeClasses = $derived.by(() => {
|
|
12
|
+
if (typeof size === 'number') {
|
|
13
|
+
return {
|
|
14
|
+
svg: `w-[${size}px] h-[${size}px]`,
|
|
15
|
+
text: 'text-base font-bold'
|
|
16
|
+
};
|
|
17
|
+
}
|
|
18
|
+
switch (size) {
|
|
19
|
+
case 'xs':
|
|
20
|
+
return { svg: 'h-5 w-5', text: 'text-xs font-bold' };
|
|
21
|
+
case 'sm':
|
|
22
|
+
return { svg: 'h-6 w-6', text: 'text-sm font-bold' };
|
|
23
|
+
case 'lg':
|
|
24
|
+
return { svg: 'h-9 w-9', text: 'text-xl font-extrabold' };
|
|
25
|
+
case 'xl':
|
|
26
|
+
return { svg: 'h-11 w-11', text: 'text-2xl font-extrabold' };
|
|
27
|
+
case 'md':
|
|
28
|
+
default:
|
|
29
|
+
return { svg: 'h-7 w-7', text: 'text-base font-bold' };
|
|
30
|
+
}
|
|
31
|
+
});
|
|
32
|
+
</script>
|
|
33
|
+
|
|
34
|
+
<div class="inline-flex items-center gap-2.5 {className}">
|
|
35
|
+
<svg
|
|
36
|
+
class="shrink-0 transition-transform hover:scale-105 {sizeClasses.svg}"
|
|
37
|
+
viewBox="0 0 100 100"
|
|
38
|
+
fill="none"
|
|
39
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
40
|
+
aria-hidden="true"
|
|
41
|
+
>
|
|
42
|
+
<defs>
|
|
43
|
+
<linearGradient id="yaxa-flame-grad" x1="0%" y1="0%" x2="100%" y2="100%">
|
|
44
|
+
<stop offset="0%" stop-color="#ff3e00" />
|
|
45
|
+
<stop offset="100%" stop-color="#ea580c" />
|
|
46
|
+
</linearGradient>
|
|
47
|
+
</defs>
|
|
48
|
+
|
|
49
|
+
<!-- 1. Outer Flame Layer (Thick Orange Contour Ribbon) -->
|
|
50
|
+
<path
|
|
51
|
+
d="M24 24 L76 76"
|
|
52
|
+
stroke="url(#yaxa-flame-grad)"
|
|
53
|
+
stroke-width="22"
|
|
54
|
+
stroke-linecap="round"
|
|
55
|
+
/>
|
|
56
|
+
<path
|
|
57
|
+
d="M76 24 L56 44 M44 56 L24 76"
|
|
58
|
+
stroke="url(#yaxa-flame-grad)"
|
|
59
|
+
stroke-width="22"
|
|
60
|
+
stroke-linecap="round"
|
|
61
|
+
/>
|
|
62
|
+
|
|
63
|
+
<!-- 2. Inner Core Layer (White Stadium Ribbon - Svelte Style) -->
|
|
64
|
+
<path d="M24 24 L76 76" stroke="#ffffff" stroke-width="8" stroke-linecap="round" />
|
|
65
|
+
<path
|
|
66
|
+
d="M76 24 L58 42 M42 58 L24 76"
|
|
67
|
+
stroke="#ffffff"
|
|
68
|
+
stroke-width="8"
|
|
69
|
+
stroke-linecap="round"
|
|
70
|
+
/>
|
|
71
|
+
</svg>
|
|
72
|
+
{#if showText}
|
|
73
|
+
<span class="tracking-tight text-neutral-900 dark:text-white {sizeClasses.text}">
|
|
74
|
+
{text}
|
|
75
|
+
</span>
|
|
76
|
+
{/if}
|
|
77
|
+
</div>
|