@juspay/svelte-ui-components 2.10.0 → 2.11.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/README.md +337 -77
- package/dist/Accordion/Accordion.svelte +4 -2
- package/dist/Accordion/Accordion.svelte.d.ts +2 -4
- package/dist/Accordion/properties.d.ts +6 -0
- package/dist/Accordion/properties.js +1 -0
- package/dist/Animations/ModalAnimation.svelte +11 -9
- package/dist/Avatar/Avatar.svelte +122 -0
- package/dist/Avatar/Avatar.svelte.d.ts +4 -0
- package/dist/Avatar/properties.d.ts +15 -0
- package/dist/Avatar/properties.js +1 -0
- package/dist/Badge/Badge.svelte +2 -2
- package/dist/Badge/properties.d.ts +1 -0
- package/dist/Banner/Banner.svelte +132 -48
- package/dist/Banner/Banner.svelte.d.ts +1 -1
- package/dist/Banner/properties.d.ts +8 -3
- package/dist/Book/Book.svelte +281 -0
- package/dist/Book/Book.svelte.d.ts +4 -0
- package/dist/Book/properties.d.ts +24 -0
- package/dist/Book/properties.js +1 -0
- package/dist/BrandLoader/BrandLoader.svelte +3 -3
- package/dist/BrandLoader/properties.d.ts +1 -0
- package/dist/Browser/Browser.svelte +193 -0
- package/dist/Browser/Browser.svelte.d.ts +3 -0
- package/dist/Browser/properties.d.ts +16 -0
- package/dist/Browser/properties.js +1 -0
- package/dist/Button/Button.svelte +20 -7
- package/dist/Button/properties.d.ts +7 -4
- package/dist/Calendar/Calendar.svelte +476 -0
- package/dist/Calendar/Calendar.svelte.d.ts +4 -0
- package/dist/Calendar/properties.d.ts +30 -0
- package/dist/Calendar/properties.js +1 -0
- package/dist/Carousel/Carousel.svelte +19 -16
- package/dist/Carousel/properties.d.ts +1 -0
- package/dist/CheckListItem/CheckListItem.svelte +31 -26
- package/dist/CheckListItem/properties.d.ts +4 -1
- package/dist/Checkbox/Checkbox.svelte +157 -0
- package/dist/Checkbox/Checkbox.svelte.d.ts +4 -0
- package/dist/Checkbox/properties.d.ts +17 -0
- package/dist/Checkbox/properties.js +1 -0
- package/dist/Choicebox/Choicebox.svelte +85 -0
- package/dist/Choicebox/Choicebox.svelte.d.ts +4 -0
- package/dist/Choicebox/properties.d.ts +14 -0
- package/dist/Choicebox/properties.js +1 -0
- package/dist/CommandMenu/CommandMenu.svelte +452 -0
- package/dist/CommandMenu/CommandMenu.svelte.d.ts +4 -0
- package/dist/CommandMenu/properties.d.ts +26 -0
- package/dist/CommandMenu/properties.js +1 -0
- package/dist/ContextMenu/ContextMenu.svelte +308 -0
- package/dist/ContextMenu/ContextMenu.svelte.d.ts +4 -0
- package/dist/ContextMenu/properties.d.ts +26 -0
- package/dist/ContextMenu/properties.js +1 -0
- package/dist/Gauge/Gauge.svelte +70 -0
- package/dist/Gauge/Gauge.svelte.d.ts +4 -0
- package/dist/Gauge/properties.d.ts +9 -0
- package/dist/Gauge/properties.js +1 -0
- package/dist/GridItem/GridItem.svelte +5 -4
- package/dist/GridItem/properties.d.ts +1 -0
- package/dist/Icon/Icon.svelte +3 -3
- package/dist/Icon/properties.d.ts +1 -0
- package/dist/IconStack/IconStack.svelte +3 -3
- package/dist/IconStack/properties.d.ts +1 -0
- package/dist/Img/Img.svelte +5 -3
- package/dist/Img/properties.d.ts +5 -1
- package/dist/Input/Input.svelte +12 -6
- package/dist/Input/properties.d.ts +1 -0
- package/dist/InputButton/InputButton.svelte +4 -3
- package/dist/InputButton/properties.d.ts +5 -6
- package/dist/KeyboardInput/KeyboardInput.svelte +93 -0
- package/dist/KeyboardInput/KeyboardInput.svelte.d.ts +4 -0
- package/dist/KeyboardInput/properties.d.ts +12 -0
- package/dist/KeyboardInput/properties.js +1 -0
- package/dist/ListItem/ListItem.svelte +31 -28
- package/dist/ListItem/properties.d.ts +1 -0
- package/dist/Loader/Loader.svelte +10 -6
- package/dist/Loader/Loader.svelte.d.ts +3 -25
- package/dist/Loader/properties.d.ts +3 -0
- package/dist/Loader/properties.js +1 -0
- package/dist/LoadingDots/LoadingDots.svelte +64 -0
- package/dist/LoadingDots/LoadingDots.svelte.d.ts +3 -0
- package/dist/LoadingDots/properties.d.ts +8 -0
- package/dist/LoadingDots/properties.js +1 -0
- package/dist/Menu/Menu.svelte +349 -0
- package/dist/Menu/Menu.svelte.d.ts +4 -0
- package/dist/Menu/properties.d.ts +24 -0
- package/dist/Menu/properties.js +1 -0
- package/dist/Modal/Modal.svelte +10 -9
- package/dist/Modal/properties.d.ts +1 -0
- package/dist/Pagination/Pagination.svelte +152 -0
- package/dist/Pagination/Pagination.svelte.d.ts +4 -0
- package/dist/Pagination/properties.d.ts +14 -0
- package/dist/Pagination/properties.js +1 -0
- package/dist/Phone/Phone.svelte +234 -0
- package/dist/Phone/Phone.svelte.d.ts +3 -0
- package/dist/Phone/properties.d.ts +11 -0
- package/dist/Phone/properties.js +1 -0
- package/dist/Pill/Pill.svelte +130 -0
- package/dist/Pill/Pill.svelte.d.ts +4 -0
- package/dist/Pill/properties.d.ts +16 -0
- package/dist/Pill/properties.js +1 -0
- package/dist/Progress/Progress.svelte +68 -0
- package/dist/Progress/Progress.svelte.d.ts +4 -0
- package/dist/Progress/properties.d.ts +10 -0
- package/dist/Progress/properties.js +1 -0
- package/dist/Radio/Radio.svelte +128 -0
- package/dist/Radio/Radio.svelte.d.ts +4 -0
- package/dist/Radio/properties.d.ts +15 -0
- package/dist/Radio/properties.js +1 -0
- package/dist/RelativeTime/RelativeTime.svelte +117 -0
- package/dist/RelativeTime/RelativeTime.svelte.d.ts +4 -0
- package/dist/RelativeTime/properties.d.ts +13 -0
- package/dist/RelativeTime/properties.js +1 -0
- package/dist/Scroller/Scroller.svelte +389 -0
- package/dist/Scroller/Scroller.svelte.d.ts +4 -0
- package/dist/Scroller/properties.d.ts +30 -0
- package/dist/Scroller/properties.js +1 -0
- package/dist/Select/Select.svelte +382 -344
- package/dist/Select/Select.svelte.d.ts +1 -1
- package/dist/Select/properties.d.ts +16 -26
- package/dist/Sheet/Sheet.svelte +264 -0
- package/dist/Sheet/Sheet.svelte.d.ts +4 -0
- package/dist/Sheet/properties.d.ts +19 -0
- package/dist/Sheet/properties.js +1 -0
- package/dist/Shimmer/Shimmer.svelte +44 -0
- package/dist/Shimmer/Shimmer.svelte.d.ts +4 -0
- package/dist/Shimmer/properties.d.ts +4 -0
- package/dist/Shimmer/properties.js +1 -0
- package/dist/Slider/Slider.svelte +144 -0
- package/dist/Slider/Slider.svelte.d.ts +4 -0
- package/dist/Slider/properties.d.ts +17 -0
- package/dist/Slider/properties.js +1 -0
- package/dist/Snippet/Snippet.svelte +123 -0
- package/dist/Snippet/Snippet.svelte.d.ts +4 -0
- package/dist/Snippet/properties.d.ts +15 -0
- package/dist/Snippet/properties.js +1 -0
- package/dist/SplitButton/SplitButton.svelte +135 -0
- package/dist/SplitButton/SplitButton.svelte.d.ts +4 -0
- package/dist/SplitButton/properties.d.ts +17 -0
- package/dist/SplitButton/properties.js +1 -0
- package/dist/Status/Status.svelte +5 -3
- package/dist/Status/properties.d.ts +1 -0
- package/dist/Stepper/Step.svelte +3 -3
- package/dist/Stepper/Stepper.svelte +3 -3
- package/dist/Stepper/properties.d.ts +2 -0
- package/dist/Table/Table.svelte +15 -8
- package/dist/Table/properties.d.ts +1 -0
- package/dist/Tabs/Tabs.svelte +240 -0
- package/dist/Tabs/Tabs.svelte.d.ts +4 -0
- package/dist/Tabs/properties.d.ts +16 -0
- package/dist/Tabs/properties.js +1 -0
- package/dist/ThemeSwitcher/ThemeSwitcher.svelte +249 -0
- package/dist/ThemeSwitcher/ThemeSwitcher.svelte.d.ts +4 -0
- package/dist/ThemeSwitcher/properties.d.ts +19 -0
- package/dist/ThemeSwitcher/properties.js +1 -0
- package/dist/Toast/Toast.svelte +25 -30
- package/dist/Toast/properties.d.ts +1 -0
- package/dist/Toggle/Toggle.svelte +2 -2
- package/dist/Toggle/properties.d.ts +1 -0
- package/dist/Toolbar/Toolbar.svelte +8 -7
- package/dist/Toolbar/properties.d.ts +1 -0
- package/dist/Tooltip/Tooltip.svelte +153 -0
- package/dist/Tooltip/Tooltip.svelte.d.ts +4 -0
- package/dist/Tooltip/properties.d.ts +13 -0
- package/dist/Tooltip/properties.js +1 -0
- package/dist/assets/battery.svg +5 -0
- package/dist/assets/checkmark.svg +3 -0
- package/dist/assets/chevron-down-sm.svg +3 -0
- package/dist/assets/chevron-down.svg +3 -0
- package/dist/assets/chevron-left-lg.svg +3 -0
- package/dist/assets/chevron-left.svg +3 -0
- package/dist/assets/chevron-right-lg.svg +3 -0
- package/dist/assets/chevron-right.svg +3 -0
- package/dist/assets/chevron-up.svg +3 -0
- package/dist/assets/close.svg +4 -0
- package/dist/assets/copy.svg +4 -0
- package/dist/assets/error-circle.svg +5 -0
- package/dist/assets/lock.svg +3 -0
- package/dist/assets/minus.svg +3 -0
- package/dist/assets/monitor.svg +5 -0
- package/dist/assets/moon.svg +3 -0
- package/dist/assets/palette.svg +7 -0
- package/dist/assets/search.svg +4 -0
- package/dist/assets/signal.svg +6 -0
- package/dist/assets/sun.svg +11 -0
- package/dist/assets/wifi.svg +3 -0
- package/dist/index.d.ts +55 -0
- package/dist/index.js +27 -0
- package/dist/utils.d.ts +2 -0
- package/dist/utils.js +18 -4
- package/package.json +8 -1
|
@@ -0,0 +1,249 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import { onMount, tick } from 'svelte';
|
|
3
|
+
import type { ThemeSwitcherOption, ThemeSwitcherProperties } from './properties';
|
|
4
|
+
import { getStorageItem, setStorageItem } from '../utils';
|
|
5
|
+
import sunSvg from '../assets/sun.svg?raw';
|
|
6
|
+
import moonSvg from '../assets/moon.svg?raw';
|
|
7
|
+
import monitorSvg from '../assets/monitor.svg?raw';
|
|
8
|
+
import paletteSvg from '../assets/palette.svg?raw';
|
|
9
|
+
|
|
10
|
+
const DEFAULT_OPTIONS: ThemeSwitcherOption[] = [
|
|
11
|
+
{ value: 'light', label: 'Light theme' },
|
|
12
|
+
{ value: 'dark', label: 'Dark theme' },
|
|
13
|
+
{ value: 'system', label: 'System theme' }
|
|
14
|
+
];
|
|
15
|
+
|
|
16
|
+
const KNOWN_ICONS: Record<string, string> = {
|
|
17
|
+
light: sunSvg,
|
|
18
|
+
dark: moonSvg,
|
|
19
|
+
system: monitorSvg
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
function getDefaultIcon(value: string): string {
|
|
23
|
+
return KNOWN_ICONS[value] ?? paletteSvg;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
let {
|
|
27
|
+
options = DEFAULT_OPTIONS,
|
|
28
|
+
value,
|
|
29
|
+
mode,
|
|
30
|
+
storageKey = 'theme-preference',
|
|
31
|
+
testId,
|
|
32
|
+
classes,
|
|
33
|
+
onchange
|
|
34
|
+
}: ThemeSwitcherProperties = $props();
|
|
35
|
+
|
|
36
|
+
let currentValue: string = $state(value ?? 'system');
|
|
37
|
+
let systemPreference: string = $state('light');
|
|
38
|
+
|
|
39
|
+
let hasSystemOption = $derived(options.some((o) => o.value === 'system'));
|
|
40
|
+
let effectiveMode = $derived(mode ?? (options.length <= 2 ? 'toggle' : 'segment'));
|
|
41
|
+
let currentIndex = $derived(options.findIndex((o) => o.value === currentValue));
|
|
42
|
+
|
|
43
|
+
let segmentButtons: HTMLButtonElement[] = $state([]);
|
|
44
|
+
let indicatorLeft: number = $state(0);
|
|
45
|
+
let indicatorWidth: number = $state(0);
|
|
46
|
+
|
|
47
|
+
function updateIndicator(): void {
|
|
48
|
+
const btn = segmentButtons.at(currentIndex);
|
|
49
|
+
if (btn instanceof HTMLButtonElement) {
|
|
50
|
+
indicatorLeft = btn.offsetLeft;
|
|
51
|
+
indicatorWidth = btn.offsetWidth;
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
function applyValue(newValue: string): void {
|
|
56
|
+
currentValue = newValue;
|
|
57
|
+
if (typeof storageKey === 'string' && storageKey.length > 0) {
|
|
58
|
+
setStorageItem(storageKey, newValue);
|
|
59
|
+
}
|
|
60
|
+
const resolved = newValue === 'system' ? systemPreference : newValue;
|
|
61
|
+
onchange?.(newValue, resolved);
|
|
62
|
+
tick().then(updateIndicator);
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
function handleToggle(): void {
|
|
66
|
+
const nextIndex = (currentIndex + 1) % options.length;
|
|
67
|
+
const nextOption = options.at(nextIndex);
|
|
68
|
+
if (typeof nextOption === 'object' && nextOption !== null) {
|
|
69
|
+
applyValue(nextOption.value);
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
onMount(() => {
|
|
74
|
+
systemPreference = window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light';
|
|
75
|
+
|
|
76
|
+
if (typeof storageKey === 'string' && storageKey.length > 0) {
|
|
77
|
+
const stored = getStorageItem(storageKey);
|
|
78
|
+
if (
|
|
79
|
+
typeof stored === 'string' &&
|
|
80
|
+
stored.length > 0 &&
|
|
81
|
+
options.some((o) => o.value === stored)
|
|
82
|
+
) {
|
|
83
|
+
currentValue = stored;
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
if (typeof value === 'string' && value !== '') {
|
|
88
|
+
currentValue = value;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
onchange?.(currentValue, currentValue === 'system' ? systemPreference : currentValue);
|
|
92
|
+
tick().then(updateIndicator);
|
|
93
|
+
|
|
94
|
+
if (hasSystemOption) {
|
|
95
|
+
const mediaQuery = window.matchMedia('(prefers-color-scheme: dark)');
|
|
96
|
+
const handler = (e: MediaQueryListEvent) => {
|
|
97
|
+
systemPreference = e.matches ? 'dark' : 'light';
|
|
98
|
+
if (currentValue === 'system') {
|
|
99
|
+
onchange?.(currentValue, systemPreference);
|
|
100
|
+
}
|
|
101
|
+
};
|
|
102
|
+
mediaQuery.addEventListener('change', handler);
|
|
103
|
+
return () => {
|
|
104
|
+
mediaQuery.removeEventListener('change', handler);
|
|
105
|
+
};
|
|
106
|
+
}
|
|
107
|
+
});
|
|
108
|
+
</script>
|
|
109
|
+
|
|
110
|
+
{#if effectiveMode === 'toggle'}
|
|
111
|
+
<button
|
|
112
|
+
class="toggle-button {classes ?? ''}"
|
|
113
|
+
onclick={handleToggle}
|
|
114
|
+
aria-label="Switch theme"
|
|
115
|
+
data-pw={typeof testId === 'string' ? testId : null}
|
|
116
|
+
>
|
|
117
|
+
{#each options as option, i (option.value)}
|
|
118
|
+
<span class="icon" class:active={i === currentIndex}>
|
|
119
|
+
{#if typeof option.icon === 'function'}
|
|
120
|
+
{@render option.icon()}
|
|
121
|
+
{:else}
|
|
122
|
+
<!-- eslint-disable svelte/no-at-html-tags -->
|
|
123
|
+
{@html getDefaultIcon(option.value)}
|
|
124
|
+
{/if}
|
|
125
|
+
</span>
|
|
126
|
+
{/each}
|
|
127
|
+
</button>
|
|
128
|
+
{:else}
|
|
129
|
+
<div class="segment-control {classes ?? ''}" data-pw={typeof testId === 'string' ? testId : null}>
|
|
130
|
+
<div
|
|
131
|
+
class="segment-indicator"
|
|
132
|
+
style="left: {indicatorLeft}px; width: {indicatorWidth}px;"
|
|
133
|
+
></div>
|
|
134
|
+
{#each options as option, i (option.value)}
|
|
135
|
+
<button
|
|
136
|
+
bind:this={segmentButtons[i]}
|
|
137
|
+
class="segment-button"
|
|
138
|
+
class:selected={currentValue === option.value}
|
|
139
|
+
onclick={() => applyValue(option.value)}
|
|
140
|
+
aria-label={option.label ?? option.value}
|
|
141
|
+
>
|
|
142
|
+
<span class="icon">
|
|
143
|
+
{#if typeof option.icon === 'function'}
|
|
144
|
+
{@render option.icon()}
|
|
145
|
+
{:else}
|
|
146
|
+
<!-- eslint-disable svelte/no-at-html-tags -->
|
|
147
|
+
{@html getDefaultIcon(option.value)}
|
|
148
|
+
{/if}
|
|
149
|
+
</span>
|
|
150
|
+
</button>
|
|
151
|
+
{/each}
|
|
152
|
+
</div>
|
|
153
|
+
{/if}
|
|
154
|
+
|
|
155
|
+
<style>
|
|
156
|
+
.toggle-button {
|
|
157
|
+
position: relative;
|
|
158
|
+
display: inline-flex;
|
|
159
|
+
align-items: center;
|
|
160
|
+
justify-content: center;
|
|
161
|
+
width: var(--theme-switcher-size, 36px);
|
|
162
|
+
height: var(--theme-switcher-size, 36px);
|
|
163
|
+
padding: 0;
|
|
164
|
+
border: none;
|
|
165
|
+
border-radius: var(--theme-switcher-border-radius, 8px);
|
|
166
|
+
background-color: var(--theme-switcher-bg, transparent);
|
|
167
|
+
cursor: pointer;
|
|
168
|
+
color: var(--theme-switcher-icon-color, #374151);
|
|
169
|
+
transition: background-color var(--theme-switcher-transition-duration, 0.3s);
|
|
170
|
+
font-family: inherit;
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
.toggle-button:hover {
|
|
174
|
+
background-color: var(--theme-switcher-bg-hover, #f3f4f6);
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
.icon {
|
|
178
|
+
display: inline-flex;
|
|
179
|
+
align-items: center;
|
|
180
|
+
justify-content: center;
|
|
181
|
+
width: var(--theme-switcher-icon-size, 18px);
|
|
182
|
+
height: var(--theme-switcher-icon-size, 18px);
|
|
183
|
+
transition:
|
|
184
|
+
opacity var(--theme-switcher-transition-duration, 0.3s),
|
|
185
|
+
transform var(--theme-switcher-transition-duration, 0.3s);
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
.icon :global(svg) {
|
|
189
|
+
width: 100%;
|
|
190
|
+
height: 100%;
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
.toggle-button .icon {
|
|
194
|
+
position: absolute;
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
.toggle-button .icon:not(.active) {
|
|
198
|
+
opacity: 0;
|
|
199
|
+
transform: scale(0.5) rotate(90deg);
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
.toggle-button .icon.active {
|
|
203
|
+
opacity: 1;
|
|
204
|
+
transform: scale(1) rotate(0deg);
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
.segment-control {
|
|
208
|
+
position: relative;
|
|
209
|
+
display: inline-flex;
|
|
210
|
+
align-items: center;
|
|
211
|
+
gap: var(--theme-switcher-segment-gap, 2px);
|
|
212
|
+
padding: var(--theme-switcher-segment-padding, 4px);
|
|
213
|
+
background-color: var(--theme-switcher-segment-bg, #f3f4f6);
|
|
214
|
+
border-radius: var(--theme-switcher-border-radius, 8px);
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
.segment-indicator {
|
|
218
|
+
position: absolute;
|
|
219
|
+
top: var(--theme-switcher-segment-padding, 4px);
|
|
220
|
+
bottom: var(--theme-switcher-segment-padding, 4px);
|
|
221
|
+
border-radius: var(--theme-switcher-segment-border-radius, 6px);
|
|
222
|
+
background-color: var(--theme-switcher-segment-active-bg, #ffffff);
|
|
223
|
+
box-shadow: var(--theme-switcher-segment-shadow, 0 1px 2px rgba(0, 0, 0, 0.1));
|
|
224
|
+
transition:
|
|
225
|
+
left var(--theme-switcher-transition-duration, 0.3s),
|
|
226
|
+
width var(--theme-switcher-transition-duration, 0.3s);
|
|
227
|
+
z-index: 0;
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
.segment-button {
|
|
231
|
+
position: relative;
|
|
232
|
+
z-index: 1;
|
|
233
|
+
display: inline-flex;
|
|
234
|
+
align-items: center;
|
|
235
|
+
justify-content: center;
|
|
236
|
+
padding: var(--theme-switcher-segment-button-padding, 6px 10px);
|
|
237
|
+
border: none;
|
|
238
|
+
border-radius: var(--theme-switcher-segment-border-radius, 6px);
|
|
239
|
+
background: transparent;
|
|
240
|
+
cursor: pointer;
|
|
241
|
+
color: var(--theme-switcher-icon-color, #374151);
|
|
242
|
+
transition: color var(--theme-switcher-transition-duration, 0.3s);
|
|
243
|
+
font-family: inherit;
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
.segment-button.selected {
|
|
247
|
+
color: var(--theme-switcher-icon-color-active, #1f2937);
|
|
248
|
+
}
|
|
249
|
+
</style>
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import type { Snippet } from 'svelte';
|
|
2
|
+
export type ThemeSwitcherOption = {
|
|
3
|
+
value: string;
|
|
4
|
+
label?: string;
|
|
5
|
+
icon?: Snippet;
|
|
6
|
+
};
|
|
7
|
+
export type ThemeSwitcherMode = 'toggle' | 'segment';
|
|
8
|
+
export type ThemeSwitcherProperties = OptionalThemeSwitcherProperties & ThemeSwitcherEventProperties;
|
|
9
|
+
export type OptionalThemeSwitcherProperties = {
|
|
10
|
+
options?: ThemeSwitcherOption[];
|
|
11
|
+
value?: string;
|
|
12
|
+
mode?: ThemeSwitcherMode;
|
|
13
|
+
storageKey?: string;
|
|
14
|
+
testId?: string;
|
|
15
|
+
classes?: string;
|
|
16
|
+
};
|
|
17
|
+
export type ThemeSwitcherEventProperties = {
|
|
18
|
+
onchange?: (value: string, resolvedValue: string) => void;
|
|
19
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
package/dist/Toast/Toast.svelte
CHANGED
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
import type { ToastDirection, ToastProperties } from './properties';
|
|
4
4
|
import type { FlyAnimationConfig } from '../types';
|
|
5
5
|
import { onMount } from 'svelte';
|
|
6
|
+
import Img from '../Img/Img.svelte';
|
|
6
7
|
|
|
7
8
|
let {
|
|
8
9
|
duration = 2000,
|
|
@@ -22,7 +23,8 @@
|
|
|
22
23
|
subTextTestId,
|
|
23
24
|
closeIconTestId,
|
|
24
25
|
onToastHide,
|
|
25
|
-
bottomContent
|
|
26
|
+
bottomContent,
|
|
27
|
+
classes
|
|
26
28
|
}: ToastProperties = $props();
|
|
27
29
|
|
|
28
30
|
const animationConfig: FlyAnimationConfig = $derived(getAnimationConfig(overlapPage, direction));
|
|
@@ -38,48 +40,35 @@
|
|
|
38
40
|
onToastHide?.();
|
|
39
41
|
}
|
|
40
42
|
|
|
41
|
-
/**
|
|
42
|
-
* Function to generate animation configuration for toast animations.
|
|
43
|
-
* @param {ToastDirection | null} toastDirection - Direction of the toast animation.
|
|
44
|
-
* @param {boolean} overlapPage - Flag indicating whether toast should overlap page content.
|
|
45
|
-
* @returns {FlyAnimationConfig} Animation configuration object.
|
|
46
|
-
*/
|
|
47
43
|
function getAnimationConfig(
|
|
48
44
|
overlapPage: boolean,
|
|
49
45
|
toastDirection?: ToastDirection
|
|
50
46
|
): FlyAnimationConfig {
|
|
51
|
-
// Initializing variables to store animation offsets
|
|
52
47
|
let inX: number = 0;
|
|
53
48
|
let inY: number = 0;
|
|
54
49
|
let outX: number = 0;
|
|
55
50
|
let outY: number = 0;
|
|
56
51
|
|
|
57
|
-
// Determining animation offsets based on toast direction
|
|
58
|
-
// Multiplying by -1 effectively flips the direction of movement along the specified axis, ensuring that the toast animation moves in the intended direction based on the chosen toast direction.
|
|
59
52
|
switch (toastDirection) {
|
|
60
53
|
case 'left-to-right':
|
|
61
|
-
// Calculating horizontal offsets for left-to-right animation
|
|
62
54
|
inX = -1 * (inAnimationOffset ?? 500);
|
|
63
55
|
outX = -1 * (outAnimationOffset ?? 500);
|
|
64
56
|
break;
|
|
65
57
|
case 'right-to-left':
|
|
66
|
-
// Calculating horizontal offsets for right-to-left animation
|
|
67
58
|
inX = inAnimationOffset ?? 500;
|
|
68
59
|
outX = outAnimationOffset ?? 500;
|
|
69
60
|
break;
|
|
70
61
|
case 'bottom-to-top':
|
|
71
|
-
// Calculating vertical offsets for bottom-to-top animation
|
|
72
62
|
inY = inAnimationOffset ?? (overlapPage ? 500 : 20);
|
|
73
63
|
outY = outAnimationOffset ?? (overlapPage ? 500 : 20);
|
|
74
64
|
break;
|
|
75
65
|
case 'top-to-bottom':
|
|
76
66
|
default:
|
|
77
|
-
// Calculating vertical offsets for top-to-bottom animation
|
|
78
67
|
inY = -1 * (inAnimationOffset ?? (overlapPage ? 500 : 20));
|
|
79
68
|
outY = -1 * (outAnimationOffset ?? (overlapPage ? 100 : 20));
|
|
80
69
|
break;
|
|
81
70
|
}
|
|
82
|
-
|
|
71
|
+
|
|
83
72
|
return {
|
|
84
73
|
in: {
|
|
85
74
|
x: inX,
|
|
@@ -108,31 +97,33 @@
|
|
|
108
97
|
|
|
109
98
|
{#if showToast}
|
|
110
99
|
<div
|
|
111
|
-
class="toast {type ?? ''}"
|
|
100
|
+
class="toast {type ?? ''} {classes ?? ''}"
|
|
112
101
|
class:no-page-overlap={!overlapPage}
|
|
102
|
+
role="alert"
|
|
103
|
+
aria-live="assertive"
|
|
113
104
|
in:fly={animationConfig.in}
|
|
114
105
|
out:fly={animationConfig.out}
|
|
115
106
|
onoutroend={handleAnimationEnd}
|
|
116
107
|
data-pw={testId}
|
|
117
108
|
>
|
|
118
|
-
{#if leftIcon}
|
|
109
|
+
{#if typeof leftIcon === 'string' && leftIcon.length > 0}
|
|
119
110
|
<div class="toast-icon-wrapper">
|
|
120
|
-
<
|
|
111
|
+
<Img src={leftIcon} alt="" />
|
|
121
112
|
</div>
|
|
122
113
|
{/if}
|
|
123
114
|
|
|
124
115
|
<div class="toast-message" data-pw={messageTestId}>
|
|
125
116
|
{message}
|
|
126
|
-
{#if subtext}
|
|
117
|
+
{#if typeof subtext === 'string' && subtext.length > 0}
|
|
127
118
|
<div class="toast-subtext" data-pw={subTextTestId}>{subtext}</div>
|
|
128
119
|
{/if}
|
|
129
120
|
|
|
130
|
-
{#if bottomContent}
|
|
121
|
+
{#if typeof bottomContent === 'function'}
|
|
131
122
|
{@render bottomContent()}
|
|
132
123
|
{/if}
|
|
133
124
|
</div>
|
|
134
125
|
|
|
135
|
-
{#if rightIcon}
|
|
126
|
+
{#if typeof rightIcon === 'string' && rightIcon.length > 0}
|
|
136
127
|
<div
|
|
137
128
|
class="close-button"
|
|
138
129
|
tabindex="0"
|
|
@@ -146,7 +137,7 @@
|
|
|
146
137
|
}}
|
|
147
138
|
data-pw={closeIconTestId}
|
|
148
139
|
>
|
|
149
|
-
<
|
|
140
|
+
<Img src={rightIcon} alt="Close" />
|
|
150
141
|
</div>
|
|
151
142
|
{/if}
|
|
152
143
|
</div>
|
|
@@ -156,13 +147,13 @@
|
|
|
156
147
|
.toast {
|
|
157
148
|
padding: var(--toast-padding, 10px);
|
|
158
149
|
font-size: var(--toast-font-size, 14px);
|
|
159
|
-
font-family: var(--toast-font-family);
|
|
150
|
+
font-family: var(--toast-font-family, inherit);
|
|
160
151
|
font-weight: var(--toast-font-weight);
|
|
161
|
-
height: var(--toast-height,
|
|
152
|
+
height: var(--toast-height, fit-content);
|
|
162
153
|
border-radius: var(--toast-border-radius, 0px);
|
|
163
154
|
border: var(--toast-border, none);
|
|
164
155
|
border-style: var(--toast-border-style);
|
|
165
|
-
width: var(--toast-width,
|
|
156
|
+
width: var(--toast-width, fit-content);
|
|
166
157
|
align-items: var(--toast-align-items, center);
|
|
167
158
|
margin: var(--toast-margin, 0px 10px 10px 10px);
|
|
168
159
|
justify-content: var(--toast-justify-content, space-between);
|
|
@@ -188,12 +179,11 @@
|
|
|
188
179
|
margin: var(--toast-icon-margin, 0px 6px 0px 0px);
|
|
189
180
|
padding: var(--toast-icon-wrapper-padding, 1px);
|
|
190
181
|
align-items: center;
|
|
191
|
-
}
|
|
192
182
|
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
filter: var(--toast-icon-filter);
|
|
196
|
-
border-radius: var(--toast-icon-border-radius, 50%);
|
|
183
|
+
--image-height: var(--toast-icon-height, 100%);
|
|
184
|
+
--image-width: fit-content;
|
|
185
|
+
--image-filter: var(--toast-icon-filter, none);
|
|
186
|
+
--image-border-radius: var(--toast-icon-border-radius, 50%);
|
|
197
187
|
}
|
|
198
188
|
|
|
199
189
|
.toast-message {
|
|
@@ -220,6 +210,11 @@
|
|
|
220
210
|
align-items: var(--toast-close-button-align-items, center);
|
|
221
211
|
justify-content: var(--toast-close-button-justify-content, center);
|
|
222
212
|
padding: var(--toast-close-button-padding, 1px);
|
|
213
|
+
|
|
214
|
+
--image-height: var(--toast-icon-height, 100%);
|
|
215
|
+
--image-width: fit-content;
|
|
216
|
+
--image-filter: var(--toast-icon-filter, none);
|
|
217
|
+
--image-border-radius: var(--toast-icon-border-radius, 50%);
|
|
223
218
|
}
|
|
224
219
|
|
|
225
220
|
.success {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
2
|
import type { ToggleProperties } from './properties';
|
|
3
3
|
|
|
4
|
-
let { checked = false, text = '', onclick }: ToggleProperties = $props();
|
|
4
|
+
let { checked = false, text = '', classes, onclick }: ToggleProperties = $props();
|
|
5
5
|
|
|
6
6
|
function handleCheckboxClick(e: MouseEvent): void {
|
|
7
7
|
if (e.target instanceof HTMLInputElement && typeof e.target.checked === 'boolean') {
|
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
}
|
|
12
12
|
</script>
|
|
13
13
|
|
|
14
|
-
<div class="container">
|
|
14
|
+
<div class="container {classes ?? ''}">
|
|
15
15
|
<div class="text" hidden={text.length === 0}>{text}</div>
|
|
16
16
|
<label class="switch">
|
|
17
17
|
<input class="input-checkbox" type="checkbox" {checked} onclick={handleCheckboxClick} />
|
|
@@ -9,37 +9,38 @@
|
|
|
9
9
|
centerContent,
|
|
10
10
|
rightContent,
|
|
11
11
|
additionalContent,
|
|
12
|
+
classes,
|
|
12
13
|
onbackClick,
|
|
13
14
|
onkeydown
|
|
14
15
|
}: ToolbarProperties = $props();
|
|
15
16
|
</script>
|
|
16
17
|
|
|
17
|
-
<div class="toolbar">
|
|
18
|
+
<div class="toolbar {classes ?? ''}">
|
|
18
19
|
<div class="content">
|
|
19
|
-
{#if leftContent}
|
|
20
|
+
{#if typeof leftContent === 'function'}
|
|
20
21
|
{@render leftContent()}
|
|
21
|
-
{:else if showBackButton && backIcon}
|
|
22
|
+
{:else if showBackButton && typeof backIcon === 'string' && backIcon.length > 0}
|
|
22
23
|
<div class="back" onclick={onbackClick} {onkeydown} role="button" tabindex="0">
|
|
23
24
|
<img src={backIcon} alt="Back" />
|
|
24
25
|
</div>
|
|
25
26
|
{/if}
|
|
26
|
-
{#if centerContent}
|
|
27
|
+
{#if typeof centerContent === 'function'}
|
|
27
28
|
<div class="center-content">
|
|
28
29
|
{@render centerContent()}
|
|
29
30
|
</div>
|
|
30
|
-
{:else if text}
|
|
31
|
+
{:else if typeof text === 'string' && text.length > 0}
|
|
31
32
|
<div class="text">
|
|
32
33
|
{text}
|
|
33
34
|
</div>
|
|
34
35
|
{/if}
|
|
35
|
-
{#if rightContent}
|
|
36
|
+
{#if typeof rightContent === 'function'}
|
|
36
37
|
<div class="right-content">
|
|
37
38
|
{@render rightContent()}
|
|
38
39
|
</div>
|
|
39
40
|
{/if}
|
|
40
41
|
</div>
|
|
41
42
|
<div class="additional-content">
|
|
42
|
-
{#if additionalContent}
|
|
43
|
+
{#if typeof additionalContent === 'function'}
|
|
43
44
|
{@render additionalContent()}
|
|
44
45
|
{/if}
|
|
45
46
|
</div>
|
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import type { TooltipProperties } from './properties';
|
|
3
|
+
|
|
4
|
+
let {
|
|
5
|
+
text,
|
|
6
|
+
position = 'top',
|
|
7
|
+
delay = 0,
|
|
8
|
+
testId,
|
|
9
|
+
classes,
|
|
10
|
+
children
|
|
11
|
+
}: TooltipProperties = $props();
|
|
12
|
+
|
|
13
|
+
let visible = $state(false);
|
|
14
|
+
let delayTimeout = $state<ReturnType<typeof setTimeout> | null>(null);
|
|
15
|
+
|
|
16
|
+
function showTooltip() {
|
|
17
|
+
if (delay > 0) {
|
|
18
|
+
delayTimeout = setTimeout(() => {
|
|
19
|
+
visible = true;
|
|
20
|
+
}, delay);
|
|
21
|
+
} else {
|
|
22
|
+
visible = true;
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
function hideTooltip() {
|
|
27
|
+
if (delayTimeout !== null) {
|
|
28
|
+
clearTimeout(delayTimeout);
|
|
29
|
+
delayTimeout = null;
|
|
30
|
+
}
|
|
31
|
+
visible = false;
|
|
32
|
+
}
|
|
33
|
+
</script>
|
|
34
|
+
|
|
35
|
+
<div
|
|
36
|
+
class="tooltip-container {classes ?? ''}"
|
|
37
|
+
role="none"
|
|
38
|
+
onmouseenter={showTooltip}
|
|
39
|
+
onmouseleave={hideTooltip}
|
|
40
|
+
onfocusin={showTooltip}
|
|
41
|
+
onfocusout={hideTooltip}
|
|
42
|
+
data-pw={testId}
|
|
43
|
+
>
|
|
44
|
+
{@render children()}
|
|
45
|
+
{#if visible}
|
|
46
|
+
<div class="tooltip-bubble {position}" role="tooltip">
|
|
47
|
+
<div class="tooltip-arrow"></div>
|
|
48
|
+
<span class="tooltip-text">{text}</span>
|
|
49
|
+
</div>
|
|
50
|
+
{/if}
|
|
51
|
+
</div>
|
|
52
|
+
|
|
53
|
+
<style>
|
|
54
|
+
.tooltip-container {
|
|
55
|
+
position: relative;
|
|
56
|
+
display: var(--tooltip-container-display, inline-flex);
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
.tooltip-bubble {
|
|
60
|
+
position: absolute;
|
|
61
|
+
z-index: var(--tooltip-z-index, 1000);
|
|
62
|
+
max-width: var(--tooltip-max-width, 200px);
|
|
63
|
+
background: var(--tooltip-background, #333333);
|
|
64
|
+
color: var(--tooltip-color, #ffffff);
|
|
65
|
+
font-size: var(--tooltip-font-size, 12px);
|
|
66
|
+
font-weight: var(--tooltip-font-weight, 400);
|
|
67
|
+
font-family: var(--tooltip-font-family);
|
|
68
|
+
padding: var(--tooltip-padding, 6px 10px);
|
|
69
|
+
border-radius: var(--tooltip-border-radius, 4px);
|
|
70
|
+
border: var(--tooltip-border, none);
|
|
71
|
+
box-shadow: var(--tooltip-box-shadow, 0 2px 6px rgba(0, 0, 0, 0.15));
|
|
72
|
+
white-space: normal;
|
|
73
|
+
word-wrap: break-word;
|
|
74
|
+
pointer-events: none;
|
|
75
|
+
opacity: 1;
|
|
76
|
+
transition: opacity var(--tooltip-opacity-duration, 0.15s) ease-in-out;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
.tooltip-arrow {
|
|
80
|
+
position: absolute;
|
|
81
|
+
width: 0;
|
|
82
|
+
height: 0;
|
|
83
|
+
border-style: solid;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
/* Top position */
|
|
87
|
+
.top {
|
|
88
|
+
bottom: calc(100% + var(--tooltip-offset, 8px));
|
|
89
|
+
left: 50%;
|
|
90
|
+
transform: translateX(-50%);
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
.top .tooltip-arrow {
|
|
94
|
+
top: 100%;
|
|
95
|
+
left: 50%;
|
|
96
|
+
transform: translateX(-50%);
|
|
97
|
+
border-width: var(--tooltip-arrow-size, 5px) var(--tooltip-arrow-size, 5px) 0
|
|
98
|
+
var(--tooltip-arrow-size, 5px);
|
|
99
|
+
border-color: var(--tooltip-arrow-color, var(--tooltip-background, #333333)) transparent
|
|
100
|
+
transparent transparent;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
/* Bottom position */
|
|
104
|
+
.bottom {
|
|
105
|
+
top: calc(100% + var(--tooltip-offset, 8px));
|
|
106
|
+
left: 50%;
|
|
107
|
+
transform: translateX(-50%);
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
.bottom .tooltip-arrow {
|
|
111
|
+
bottom: 100%;
|
|
112
|
+
left: 50%;
|
|
113
|
+
transform: translateX(-50%);
|
|
114
|
+
border-width: 0 var(--tooltip-arrow-size, 5px) var(--tooltip-arrow-size, 5px)
|
|
115
|
+
var(--tooltip-arrow-size, 5px);
|
|
116
|
+
border-color: transparent transparent
|
|
117
|
+
var(--tooltip-arrow-color, var(--tooltip-background, #333333)) transparent;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
/* Left position */
|
|
121
|
+
.left {
|
|
122
|
+
right: calc(100% + var(--tooltip-offset, 8px));
|
|
123
|
+
top: 50%;
|
|
124
|
+
transform: translateY(-50%);
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
.left .tooltip-arrow {
|
|
128
|
+
left: 100%;
|
|
129
|
+
top: 50%;
|
|
130
|
+
transform: translateY(-50%);
|
|
131
|
+
border-width: var(--tooltip-arrow-size, 5px) 0 var(--tooltip-arrow-size, 5px)
|
|
132
|
+
var(--tooltip-arrow-size, 5px);
|
|
133
|
+
border-color: transparent transparent transparent
|
|
134
|
+
var(--tooltip-arrow-color, var(--tooltip-background, #333333));
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
/* Right position */
|
|
138
|
+
.right {
|
|
139
|
+
left: calc(100% + var(--tooltip-offset, 8px));
|
|
140
|
+
top: 50%;
|
|
141
|
+
transform: translateY(-50%);
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
.right .tooltip-arrow {
|
|
145
|
+
right: 100%;
|
|
146
|
+
top: 50%;
|
|
147
|
+
transform: translateY(-50%);
|
|
148
|
+
border-width: var(--tooltip-arrow-size, 5px) var(--tooltip-arrow-size, 5px)
|
|
149
|
+
var(--tooltip-arrow-size, 5px) 0;
|
|
150
|
+
border-color: transparent var(--tooltip-arrow-color, var(--tooltip-background, #333333))
|
|
151
|
+
transparent transparent;
|
|
152
|
+
}
|
|
153
|
+
</style>
|