sv5ui 2.2.0 → 2.3.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/dist/components/Error/Error.svelte +89 -0
- package/dist/components/Error/Error.svelte.d.ts +5 -0
- package/dist/components/Error/error.types.d.ts +87 -0
- package/dist/components/Error/error.types.js +1 -0
- package/dist/components/Error/error.variants.d.ts +66 -0
- package/dist/components/Error/error.variants.js +16 -0
- package/dist/components/Error/index.d.ts +2 -0
- package/dist/components/Error/index.js +1 -0
- package/dist/components/Footer/Footer.svelte +71 -0
- package/dist/components/Footer/Footer.svelte.d.ts +5 -0
- package/dist/components/Footer/FooterColumns.svelte +110 -0
- package/dist/components/Footer/FooterColumns.svelte.d.ts +5 -0
- package/dist/components/Footer/footer-columns.types.d.ts +73 -0
- package/dist/components/Footer/footer-columns.types.js +1 -0
- package/dist/components/Footer/footer-columns.variants.d.ts +108 -0
- package/dist/components/Footer/footer-columns.variants.js +23 -0
- package/dist/components/Footer/footer.types.d.ts +46 -0
- package/dist/components/Footer/footer.types.js +1 -0
- package/dist/components/Footer/footer.variants.d.ts +66 -0
- package/dist/components/Footer/footer.variants.js +16 -0
- package/dist/components/Footer/index.d.ts +4 -0
- package/dist/components/Footer/index.js +2 -0
- package/dist/components/Header/Header.svelte +177 -0
- package/dist/components/Header/Header.svelte.d.ts +5 -0
- package/dist/components/Header/header.types.d.ts +124 -0
- package/dist/components/Header/header.types.js +1 -0
- package/dist/components/Header/header.variants.d.ts +108 -0
- package/dist/components/Header/header.variants.js +32 -0
- package/dist/components/Header/index.d.ts +2 -0
- package/dist/components/Header/index.js +1 -0
- package/dist/components/Main/Main.svelte +20 -0
- package/dist/components/Main/Main.svelte.d.ts +5 -0
- package/dist/components/Main/index.d.ts +2 -0
- package/dist/components/Main/index.js +1 -0
- package/dist/components/Main/main.types.d.ts +27 -0
- package/dist/components/Main/main.types.js +1 -0
- package/dist/components/Main/main.variants.d.ts +30 -0
- package/dist/components/Main/main.variants.js +10 -0
- package/dist/components/Tour/Tour.svelte +459 -0
- package/dist/components/Tour/Tour.svelte.d.ts +5 -0
- package/dist/components/Tour/index.d.ts +2 -0
- package/dist/components/Tour/index.js +1 -0
- package/dist/components/Tour/tour.types.d.ts +457 -0
- package/dist/components/Tour/tour.types.js +1 -0
- package/dist/components/Tour/tour.variants.d.ts +208 -0
- package/dist/components/Tour/tour.variants.js +56 -0
- package/dist/config.d.ts +2 -0
- package/dist/config.js +2 -0
- package/dist/hooks/index.d.ts +1 -0
- package/dist/hooks/index.js +1 -0
- package/dist/hooks/useTour/index.d.ts +1 -0
- package/dist/hooks/useTour/index.js +1 -0
- package/dist/hooks/useTour/useTour.svelte.d.ts +29 -0
- package/dist/hooks/useTour/useTour.svelte.js +194 -0
- package/dist/index.d.ts +5 -0
- package/dist/index.js +5 -0
- package/dist/theme.css +3 -0
- package/package.json +1 -1
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import { tv } from 'tailwind-variants';
|
|
2
|
+
export const tourVariants = tv({
|
|
3
|
+
slots: {
|
|
4
|
+
overlay: 'fixed inset-0 z-[var(--sv5ui-tour-overlay-z,100)]',
|
|
5
|
+
spotlight: [
|
|
6
|
+
'fixed top-0 left-0 z-[var(--sv5ui-tour-overlay-z,100)] pointer-events-none',
|
|
7
|
+
'shadow-[0_0_0_9999px_rgba(0,0,0,0.5)]'
|
|
8
|
+
],
|
|
9
|
+
panel: [
|
|
10
|
+
'z-[var(--sv5ui-tour-panel-z,101)] flex flex-col',
|
|
11
|
+
'bg-surface-container-lowest text-on-surface ring ring-surface-container-highest',
|
|
12
|
+
'rounded-xl shadow-xl focus:outline-none',
|
|
13
|
+
'w-[var(--sv5ui-tour-w)] max-w-[calc(100vw-2rem)]'
|
|
14
|
+
],
|
|
15
|
+
arrow: 'bg-surface-container-lowest border-surface-container-highest',
|
|
16
|
+
header: 'relative flex items-start justify-between gap-2 p-4 pb-0',
|
|
17
|
+
title: 'font-semibold text-sm leading-snug',
|
|
18
|
+
description: 'text-sm text-on-surface-variant',
|
|
19
|
+
body: 'px-4 py-3 text-sm text-on-surface-variant',
|
|
20
|
+
footer: 'flex items-center justify-between gap-3 p-4 pt-0',
|
|
21
|
+
progress: 'flex items-center gap-1.5',
|
|
22
|
+
progressDot: 'size-1.5 rounded-full bg-on-surface-variant/30 transition-colors',
|
|
23
|
+
nav: 'flex items-center gap-2 ml-auto',
|
|
24
|
+
prevButton: '',
|
|
25
|
+
nextButton: '',
|
|
26
|
+
skipButton: 'text-on-surface-variant',
|
|
27
|
+
closeButton: 'shrink-0 -mt-1 -mr-1'
|
|
28
|
+
},
|
|
29
|
+
variants: {
|
|
30
|
+
size: {
|
|
31
|
+
sm: { panel: '[--sv5ui-tour-w:280px]' },
|
|
32
|
+
md: { panel: '[--sv5ui-tour-w:340px]' },
|
|
33
|
+
lg: { panel: '[--sv5ui-tour-w:420px]' }
|
|
34
|
+
},
|
|
35
|
+
transition: {
|
|
36
|
+
true: {
|
|
37
|
+
panel: [
|
|
38
|
+
'data-[state=open]:animate-in data-[state=open]:fade-in-0 data-[state=open]:zoom-in-95',
|
|
39
|
+
'data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95'
|
|
40
|
+
],
|
|
41
|
+
spotlight: 'transition-transform duration-300 ease-out'
|
|
42
|
+
}
|
|
43
|
+
},
|
|
44
|
+
active: {
|
|
45
|
+
true: { progressDot: 'bg-primary' }
|
|
46
|
+
}
|
|
47
|
+
},
|
|
48
|
+
defaultVariants: {
|
|
49
|
+
size: 'md',
|
|
50
|
+
transition: true
|
|
51
|
+
}
|
|
52
|
+
});
|
|
53
|
+
export const tourDefaults = {
|
|
54
|
+
defaultVariants: tourVariants.defaultVariants,
|
|
55
|
+
slots: {}
|
|
56
|
+
};
|
package/dist/config.d.ts
CHANGED
package/dist/config.js
CHANGED
|
@@ -31,6 +31,8 @@ export const iconsDefaults = {
|
|
|
31
31
|
chevronsRight: 'lucide:chevrons-right',
|
|
32
32
|
ellipsis: 'lucide:ellipsis',
|
|
33
33
|
close: 'lucide:x',
|
|
34
|
+
menu: 'lucide:menu',
|
|
35
|
+
external: 'lucide:arrow-up-right',
|
|
34
36
|
check: 'lucide:check',
|
|
35
37
|
light: 'lucide:sun',
|
|
36
38
|
dark: 'lucide:moon',
|
package/dist/hooks/index.d.ts
CHANGED
package/dist/hooks/index.js
CHANGED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { useTour } from './useTour.svelte.js';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { useTour } from './useTour.svelte.js';
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import type { TourController, UseTourOptions } from '../../components/Tour/tour.types.js';
|
|
2
|
+
/**
|
|
3
|
+
* Headless controller for the {@link import('../../components/Tour/tour.types.js').TourProps Tour}
|
|
4
|
+
* component. Pure reactive state — no `$effect` — so it is safe to create
|
|
5
|
+
* conditionally and renders nothing on the server.
|
|
6
|
+
*
|
|
7
|
+
* Drive the tour through the returned {@link TourController}, and pass it to
|
|
8
|
+
* `<Tour controller={tour} />`. Persistence (when enabled) keeps an in-progress
|
|
9
|
+
* tour alive across reloads and SPA navigations, which is what makes multi-page
|
|
10
|
+
* tours possible.
|
|
11
|
+
*
|
|
12
|
+
* @example
|
|
13
|
+
* ```svelte
|
|
14
|
+
* <script>
|
|
15
|
+
* import { useTour, Tour } from 'sv5ui'
|
|
16
|
+
* import { goto } from '$app/navigation'
|
|
17
|
+
*
|
|
18
|
+
* const tour = useTour({
|
|
19
|
+
* steps,
|
|
20
|
+
* persist: true,
|
|
21
|
+
* onStepChange: (i) => { if (steps[i].route) goto(steps[i].route) }
|
|
22
|
+
* })
|
|
23
|
+
* </script>
|
|
24
|
+
*
|
|
25
|
+
* <Button onclick={() => tour.start()}>Start</Button>
|
|
26
|
+
* <Tour {steps} controller={tour} />
|
|
27
|
+
* ```
|
|
28
|
+
*/
|
|
29
|
+
export declare function useTour(options: UseTourOptions): TourController;
|
|
@@ -0,0 +1,194 @@
|
|
|
1
|
+
function normalizePersist(persist) {
|
|
2
|
+
if (!persist)
|
|
3
|
+
return null;
|
|
4
|
+
const opts = persist === true ? {} : persist;
|
|
5
|
+
return { key: opts.key ?? 'sv5ui-tour', storage: opts.storage ?? 'local' };
|
|
6
|
+
}
|
|
7
|
+
/**
|
|
8
|
+
* Headless controller for the {@link import('../../components/Tour/tour.types.js').TourProps Tour}
|
|
9
|
+
* component. Pure reactive state — no `$effect` — so it is safe to create
|
|
10
|
+
* conditionally and renders nothing on the server.
|
|
11
|
+
*
|
|
12
|
+
* Drive the tour through the returned {@link TourController}, and pass it to
|
|
13
|
+
* `<Tour controller={tour} />`. Persistence (when enabled) keeps an in-progress
|
|
14
|
+
* tour alive across reloads and SPA navigations, which is what makes multi-page
|
|
15
|
+
* tours possible.
|
|
16
|
+
*
|
|
17
|
+
* @example
|
|
18
|
+
* ```svelte
|
|
19
|
+
* <script>
|
|
20
|
+
* import { useTour, Tour } from 'sv5ui'
|
|
21
|
+
* import { goto } from '$app/navigation'
|
|
22
|
+
*
|
|
23
|
+
* const tour = useTour({
|
|
24
|
+
* steps,
|
|
25
|
+
* persist: true,
|
|
26
|
+
* onStepChange: (i) => { if (steps[i].route) goto(steps[i].route) }
|
|
27
|
+
* })
|
|
28
|
+
* </script>
|
|
29
|
+
*
|
|
30
|
+
* <Button onclick={() => tour.start()}>Start</Button>
|
|
31
|
+
* <Tour {steps} controller={tour} />
|
|
32
|
+
* ```
|
|
33
|
+
*/
|
|
34
|
+
export function useTour(options) {
|
|
35
|
+
const defaultStep = options.defaultStep ?? 0;
|
|
36
|
+
const persist = normalizePersist(options.persist);
|
|
37
|
+
let open = $state(false);
|
|
38
|
+
let index = $state(defaultStep);
|
|
39
|
+
let completed = false;
|
|
40
|
+
function getSteps() {
|
|
41
|
+
return options.steps;
|
|
42
|
+
}
|
|
43
|
+
function clamp(i) {
|
|
44
|
+
const last = getSteps().length - 1;
|
|
45
|
+
if (last < 0)
|
|
46
|
+
return 0;
|
|
47
|
+
return Math.max(0, Math.min(i, last));
|
|
48
|
+
}
|
|
49
|
+
function resolveIndex(step) {
|
|
50
|
+
if (typeof step === 'number')
|
|
51
|
+
return clamp(step);
|
|
52
|
+
const found = getSteps().findIndex((s) => s.id === step);
|
|
53
|
+
return found >= 0 ? found : index;
|
|
54
|
+
}
|
|
55
|
+
function nextEnabled(from, dir) {
|
|
56
|
+
const steps = getSteps();
|
|
57
|
+
let i = from + dir;
|
|
58
|
+
while (i >= 0 && i < steps.length) {
|
|
59
|
+
if (!steps[i]?.disabled)
|
|
60
|
+
return i;
|
|
61
|
+
i += dir;
|
|
62
|
+
}
|
|
63
|
+
return null;
|
|
64
|
+
}
|
|
65
|
+
function firstEnabled(from) {
|
|
66
|
+
if (!getSteps()[from]?.disabled)
|
|
67
|
+
return from;
|
|
68
|
+
return nextEnabled(from, 1) ?? nextEnabled(from, -1) ?? from;
|
|
69
|
+
}
|
|
70
|
+
function persistSave() {
|
|
71
|
+
if (!persist || typeof window === 'undefined')
|
|
72
|
+
return;
|
|
73
|
+
try {
|
|
74
|
+
const store = persist.storage === 'session' ? sessionStorage : localStorage;
|
|
75
|
+
if (open) {
|
|
76
|
+
store.setItem(persist.key, JSON.stringify({ open: true, index }));
|
|
77
|
+
}
|
|
78
|
+
else {
|
|
79
|
+
store.removeItem(persist.key);
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
catch {
|
|
83
|
+
void 0;
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
if (persist && typeof window !== 'undefined') {
|
|
87
|
+
try {
|
|
88
|
+
const store = persist.storage === 'session' ? sessionStorage : localStorage;
|
|
89
|
+
const raw = store.getItem(persist.key);
|
|
90
|
+
if (raw) {
|
|
91
|
+
const parsed = JSON.parse(raw);
|
|
92
|
+
if (parsed?.open) {
|
|
93
|
+
open = true;
|
|
94
|
+
index = clamp(parsed.index ?? defaultStep);
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
catch {
|
|
99
|
+
void 0;
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
function changeIndex(target) {
|
|
103
|
+
const prev = index;
|
|
104
|
+
index = target;
|
|
105
|
+
persistSave();
|
|
106
|
+
if (target !== prev)
|
|
107
|
+
options.onStepChange?.(target, prev);
|
|
108
|
+
}
|
|
109
|
+
function start(step) {
|
|
110
|
+
const base = step !== undefined ? resolveIndex(step) : clamp(index);
|
|
111
|
+
const target = firstEnabled(base);
|
|
112
|
+
completed = false;
|
|
113
|
+
const prev = open ? index : -1;
|
|
114
|
+
index = target;
|
|
115
|
+
if (!open) {
|
|
116
|
+
open = true;
|
|
117
|
+
persistSave();
|
|
118
|
+
options.onStart?.();
|
|
119
|
+
}
|
|
120
|
+
else {
|
|
121
|
+
persistSave();
|
|
122
|
+
}
|
|
123
|
+
if (target !== prev)
|
|
124
|
+
options.onStepChange?.(target, prev);
|
|
125
|
+
}
|
|
126
|
+
function stop() {
|
|
127
|
+
if (!open)
|
|
128
|
+
return;
|
|
129
|
+
const at = index;
|
|
130
|
+
open = false;
|
|
131
|
+
persistSave();
|
|
132
|
+
if (!completed)
|
|
133
|
+
options.onSkip?.(at);
|
|
134
|
+
}
|
|
135
|
+
function next() {
|
|
136
|
+
if (!open)
|
|
137
|
+
return;
|
|
138
|
+
const ni = nextEnabled(index, 1);
|
|
139
|
+
if (ni === null) {
|
|
140
|
+
completed = true;
|
|
141
|
+
options.onComplete?.();
|
|
142
|
+
open = false;
|
|
143
|
+
persistSave();
|
|
144
|
+
return;
|
|
145
|
+
}
|
|
146
|
+
changeIndex(ni);
|
|
147
|
+
}
|
|
148
|
+
function prev() {
|
|
149
|
+
if (!open)
|
|
150
|
+
return;
|
|
151
|
+
const pi = nextEnabled(index, -1);
|
|
152
|
+
if (pi === null)
|
|
153
|
+
return;
|
|
154
|
+
changeIndex(pi);
|
|
155
|
+
}
|
|
156
|
+
function goTo(step) {
|
|
157
|
+
if (!open) {
|
|
158
|
+
start(step);
|
|
159
|
+
return;
|
|
160
|
+
}
|
|
161
|
+
changeIndex(firstEnabled(resolveIndex(step)));
|
|
162
|
+
}
|
|
163
|
+
return {
|
|
164
|
+
start,
|
|
165
|
+
stop,
|
|
166
|
+
next,
|
|
167
|
+
prev,
|
|
168
|
+
goTo,
|
|
169
|
+
get isActive() {
|
|
170
|
+
return open;
|
|
171
|
+
},
|
|
172
|
+
get currentIndex() {
|
|
173
|
+
return open ? index : -1;
|
|
174
|
+
},
|
|
175
|
+
get totalSteps() {
|
|
176
|
+
return getSteps().length;
|
|
177
|
+
},
|
|
178
|
+
get hasPrev() {
|
|
179
|
+
return open && nextEnabled(index, -1) !== null;
|
|
180
|
+
},
|
|
181
|
+
get hasNext() {
|
|
182
|
+
return open && nextEnabled(index, 1) !== null;
|
|
183
|
+
},
|
|
184
|
+
get isFirst() {
|
|
185
|
+
return nextEnabled(index, -1) === null;
|
|
186
|
+
},
|
|
187
|
+
get isLast() {
|
|
188
|
+
return nextEnabled(index, 1) === null;
|
|
189
|
+
},
|
|
190
|
+
get currentStepData() {
|
|
191
|
+
return open ? getSteps()[index] : undefined;
|
|
192
|
+
}
|
|
193
|
+
};
|
|
194
|
+
}
|
package/dist/index.d.ts
CHANGED
|
@@ -14,6 +14,10 @@ export * from './components/Container/index.js';
|
|
|
14
14
|
export * from './components/Timeline/index.js';
|
|
15
15
|
export * from './components/User/index.js';
|
|
16
16
|
export * from './components/Empty/index.js';
|
|
17
|
+
export * from './components/Error/index.js';
|
|
18
|
+
export * from './components/Footer/index.js';
|
|
19
|
+
export * from './components/Header/index.js';
|
|
20
|
+
export * from './components/Main/index.js';
|
|
17
21
|
export * from './components/Skeleton/index.js';
|
|
18
22
|
export * from './components/Drawer/index.js';
|
|
19
23
|
export * from './components/Tooltip/index.js';
|
|
@@ -49,6 +53,7 @@ export * from './components/Toast/index.js';
|
|
|
49
53
|
export * from './components/Carousel/index.js';
|
|
50
54
|
export * from './components/Banner/index.js';
|
|
51
55
|
export * from './components/Stepper/index.js';
|
|
56
|
+
export * from './components/Tour/index.js';
|
|
52
57
|
export * from './hooks/index.js';
|
|
53
58
|
export { defineConfig } from './config.js';
|
|
54
59
|
export type { UIConfig } from './config.js';
|
package/dist/index.js
CHANGED
|
@@ -15,6 +15,10 @@ export * from './components/Container/index.js';
|
|
|
15
15
|
export * from './components/Timeline/index.js';
|
|
16
16
|
export * from './components/User/index.js';
|
|
17
17
|
export * from './components/Empty/index.js';
|
|
18
|
+
export * from './components/Error/index.js';
|
|
19
|
+
export * from './components/Footer/index.js';
|
|
20
|
+
export * from './components/Header/index.js';
|
|
21
|
+
export * from './components/Main/index.js';
|
|
18
22
|
export * from './components/Skeleton/index.js';
|
|
19
23
|
export * from './components/Drawer/index.js';
|
|
20
24
|
export * from './components/Tooltip/index.js';
|
|
@@ -50,6 +54,7 @@ export * from './components/Toast/index.js';
|
|
|
50
54
|
export * from './components/Carousel/index.js';
|
|
51
55
|
export * from './components/Banner/index.js';
|
|
52
56
|
export * from './components/Stepper/index.js';
|
|
57
|
+
export * from './components/Tour/index.js';
|
|
53
58
|
// Composables
|
|
54
59
|
export * from './hooks/index.js';
|
|
55
60
|
// Configuration
|
package/dist/theme.css
CHANGED
|
@@ -86,6 +86,9 @@
|
|
|
86
86
|
--color-inverse-surface: oklch(0.208 0.042 265.75);
|
|
87
87
|
--color-inverse-on-surface: oklch(0.929 0.013 255.51);
|
|
88
88
|
--color-inverse-primary: oklch(0.707 0.165 254.62);
|
|
89
|
+
|
|
90
|
+
/* ========== LAYOUT ========== */
|
|
91
|
+
--ui-header-height: 4rem;
|
|
89
92
|
}
|
|
90
93
|
|
|
91
94
|
/* ============================================
|