@softwareone/spi-sv5-library 1.3.1 → 1.4.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/Form/Label.svelte +1 -3
- package/dist/Form/Select/Select.svelte +110 -95
- package/dist/Form/Toggle/Toggle.svelte +56 -21
- package/dist/Form/Toggle/Toggle.svelte.d.ts +3 -0
- package/dist/Header/Header.svelte +81 -24
- package/dist/Header/Header.svelte.d.ts +2 -1
- package/dist/Home/Home.svelte +6 -12
- package/dist/Menu/Menu.svelte +9 -50
- package/dist/Menu/Menu.svelte.d.ts +1 -1
- package/dist/Menu/MenuItem.svelte +2 -14
- package/dist/Menu/MenuItem.svelte.d.ts +0 -1
- package/dist/Modal/Modal.svelte +32 -23
- package/dist/Modal/ModalContent.svelte +7 -4
- package/dist/Modal/ModalContent.svelte.d.ts +1 -0
- package/dist/Modal/ModalHeader.svelte +14 -10
- package/dist/Modal/modalState.svelte.d.ts +2 -0
- package/dist/Processing/Processing.svelte +89 -0
- package/dist/Processing/Processing.svelte.d.ts +4 -0
- package/dist/Processing/processingState.svelte.d.ts +6 -0
- package/dist/Processing/processingState.svelte.js +1 -0
- package/dist/ProgressWizard/ProgressWizard.svelte +0 -1
- package/dist/Spinner/Spinner.svelte +1 -0
- package/dist/Switcher/Switcher.svelte +78 -0
- package/dist/Switcher/Switcher.svelte.d.ts +8 -0
- package/dist/Switcher/switcherState.svelte.d.ts +4 -0
- package/dist/Switcher/switcherState.svelte.js +1 -0
- package/dist/Waffle/Waffle.svelte +95 -0
- package/dist/Waffle/Waffle.svelte.d.ts +8 -0
- package/dist/Waffle/WaffleItems.svelte +82 -0
- package/dist/Waffle/WaffleItems.svelte.d.ts +9 -0
- package/dist/Waffle/waffleState.svelte.d.ts +6 -0
- package/dist/Waffle/waffleState.svelte.js +1 -0
- package/dist/index.d.ts +6 -1
- package/dist/index.js +4 -1
- package/package.json +1 -1
package/dist/Menu/Menu.svelte
CHANGED
|
@@ -6,21 +6,13 @@
|
|
|
6
6
|
import type { MenuItem } from './SidebarState.svelte';
|
|
7
7
|
|
|
8
8
|
interface MenuProps {
|
|
9
|
-
disableMenuButton?: boolean;
|
|
10
9
|
menuItems: MenuItem[];
|
|
10
|
+
showMenu: boolean;
|
|
11
11
|
}
|
|
12
12
|
|
|
13
|
-
let showMenu:
|
|
14
|
-
let isMainMenu: boolean = $state(true);
|
|
15
|
-
let activeItem: string = $state('');
|
|
13
|
+
let { menuItems, showMenu }: MenuProps = $props();
|
|
16
14
|
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
$effect(() => {
|
|
20
|
-
if (showMenu) {
|
|
21
|
-
setActiveMenuItem();
|
|
22
|
-
}
|
|
23
|
-
});
|
|
15
|
+
let activeItem = $state('');
|
|
24
16
|
|
|
25
17
|
const setActiveMenuItem = () => {
|
|
26
18
|
activeItem = menuItems.find((menuItem: MenuItem) => isActiveMenuItem(menuItem.url))?.text || '';
|
|
@@ -44,18 +36,13 @@
|
|
|
44
36
|
const onHandleMenu = () => {
|
|
45
37
|
showMenu = !showMenu;
|
|
46
38
|
};
|
|
47
|
-
</script>
|
|
48
39
|
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
aria-label="menu button"
|
|
56
|
-
>
|
|
57
|
-
<span class="material-icons icon-span">menu</span>
|
|
58
|
-
</button>
|
|
40
|
+
$effect(() => {
|
|
41
|
+
if (showMenu) {
|
|
42
|
+
setActiveMenuItem();
|
|
43
|
+
}
|
|
44
|
+
});
|
|
45
|
+
</script>
|
|
59
46
|
|
|
60
47
|
{#if showMenu}
|
|
61
48
|
<button
|
|
@@ -72,7 +59,6 @@
|
|
|
72
59
|
item={menuItem}
|
|
73
60
|
isCollapsed={false}
|
|
74
61
|
activeItem={activeItem === menuItem.text}
|
|
75
|
-
{isMainMenu}
|
|
76
62
|
onClick={onClickMenuItem}
|
|
77
63
|
/>
|
|
78
64
|
{/each}
|
|
@@ -81,28 +67,6 @@
|
|
|
81
67
|
{/if}
|
|
82
68
|
|
|
83
69
|
<style>
|
|
84
|
-
.menu-button {
|
|
85
|
-
display: flex;
|
|
86
|
-
justify-content: center;
|
|
87
|
-
align-items: center;
|
|
88
|
-
border-radius: 50%;
|
|
89
|
-
background: white;
|
|
90
|
-
z-index: 40;
|
|
91
|
-
cursor: pointer;
|
|
92
|
-
border: none;
|
|
93
|
-
width: 40px;
|
|
94
|
-
height: 40px;
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
.menu-button:hover {
|
|
98
|
-
background: #e0e5e8;
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
.icon-span {
|
|
102
|
-
font-size: 32px;
|
|
103
|
-
color: #6b7180;
|
|
104
|
-
}
|
|
105
|
-
|
|
106
70
|
.menu-principal {
|
|
107
71
|
position: fixed;
|
|
108
72
|
inset: 0;
|
|
@@ -138,11 +102,6 @@
|
|
|
138
102
|
overflow-x: hidden;
|
|
139
103
|
}
|
|
140
104
|
|
|
141
|
-
.disabled-menu {
|
|
142
|
-
cursor: not-allowed;
|
|
143
|
-
opacity: 0.5;
|
|
144
|
-
}
|
|
145
|
-
|
|
146
105
|
@media (min-width: 768px) {
|
|
147
106
|
.menu-list {
|
|
148
107
|
min-width: 220px;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { MenuItem } from './SidebarState.svelte';
|
|
2
2
|
interface MenuProps {
|
|
3
|
-
disableMenuButton?: boolean;
|
|
4
3
|
menuItems: MenuItem[];
|
|
4
|
+
showMenu: boolean;
|
|
5
5
|
}
|
|
6
6
|
declare const Menu: import("svelte").Component<MenuProps, {}, "">;
|
|
7
7
|
type Menu = ReturnType<typeof Menu>;
|
|
@@ -7,10 +7,9 @@
|
|
|
7
7
|
isCollapsed: boolean;
|
|
8
8
|
onClick?: (item: MenuItem) => void;
|
|
9
9
|
activeItem: boolean;
|
|
10
|
-
isMainMenu?: boolean;
|
|
11
10
|
}
|
|
12
11
|
|
|
13
|
-
let { item, isCollapsed = false, onClick, activeItem
|
|
12
|
+
let { item, isCollapsed = false, onClick, activeItem }: MenuItemProps = $props();
|
|
14
13
|
</script>
|
|
15
14
|
|
|
16
15
|
<li>
|
|
@@ -20,8 +19,7 @@
|
|
|
20
19
|
class={[
|
|
21
20
|
'item',
|
|
22
21
|
isCollapsed ? 'collapsed' : 'expanded',
|
|
23
|
-
activeItem && `active-${isCollapsed ? 'collapsed' : 'expanded'}
|
|
24
|
-
isMainMenu && 'main-menu'
|
|
22
|
+
activeItem && `active-${isCollapsed ? 'collapsed' : 'expanded'}`
|
|
25
23
|
]}
|
|
26
24
|
onclick={() => onClick?.(item)}
|
|
27
25
|
>
|
|
@@ -108,16 +106,6 @@
|
|
|
108
106
|
color: #472aff;
|
|
109
107
|
}
|
|
110
108
|
|
|
111
|
-
.main-menu.expanded:hover:not(.active-expanded),
|
|
112
|
-
.main-menu.collapsed:hover:not(.active-collapsed) {
|
|
113
|
-
background-color: #eaecff;
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
.main-menu:hover .item-name-span,
|
|
117
|
-
.main-menu:hover .icon-span {
|
|
118
|
-
color: #472aff;
|
|
119
|
-
}
|
|
120
|
-
|
|
121
109
|
.item.collapsed:focus,
|
|
122
110
|
.item.collapsed:focus-visible {
|
|
123
111
|
outline: none;
|
package/dist/Modal/Modal.svelte
CHANGED
|
@@ -11,9 +11,11 @@
|
|
|
11
11
|
title,
|
|
12
12
|
width = 'xs',
|
|
13
13
|
errorIcon,
|
|
14
|
+
hideHeader,
|
|
14
15
|
onclose = () => {},
|
|
15
16
|
children,
|
|
16
|
-
footer
|
|
17
|
+
footer,
|
|
18
|
+
disablePadding
|
|
17
19
|
}: ModalProps = $props();
|
|
18
20
|
|
|
19
21
|
const onHandleClose = () => {
|
|
@@ -22,34 +24,37 @@
|
|
|
22
24
|
};
|
|
23
25
|
</script>
|
|
24
26
|
|
|
25
|
-
<div class="modal-
|
|
26
|
-
<div
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
27
|
+
<div class="modal-backdrop">
|
|
28
|
+
<div class="modal-container {width}">
|
|
29
|
+
<div
|
|
30
|
+
onclose={onHandleClose}
|
|
31
|
+
class="modal"
|
|
32
|
+
transition:scale={{
|
|
33
|
+
duration: 150,
|
|
34
|
+
start: 0.95
|
|
35
|
+
}}
|
|
36
|
+
>
|
|
37
|
+
<ModalHeader {title} {errorIcon} {hideHeader} onclose={onHandleClose} />
|
|
38
|
+
<ModalContent content={children} {disablePadding} />
|
|
39
|
+
<ModalFooter {footer} onclose={onHandleClose} />
|
|
40
|
+
</div>
|
|
37
41
|
</div>
|
|
38
42
|
</div>
|
|
39
43
|
|
|
40
44
|
<style>
|
|
41
|
-
.modal-
|
|
45
|
+
.modal-backdrop {
|
|
42
46
|
display: flex;
|
|
43
47
|
position: fixed;
|
|
44
48
|
top: 0;
|
|
45
49
|
left: 0;
|
|
46
50
|
z-index: 1000;
|
|
51
|
+
justify-content: center;
|
|
47
52
|
width: 100%;
|
|
48
53
|
height: 100%;
|
|
49
54
|
background-color: #e0e5e880;
|
|
50
55
|
}
|
|
51
56
|
|
|
52
|
-
.modal {
|
|
57
|
+
.modal-container {
|
|
53
58
|
width: var(--modal-width);
|
|
54
59
|
max-height: 90%;
|
|
55
60
|
border-radius: 16px;
|
|
@@ -62,36 +67,40 @@
|
|
|
62
67
|
0px 4px 5px 0px rgba(51, 56, 64, 0.14);
|
|
63
68
|
}
|
|
64
69
|
|
|
65
|
-
.modal
|
|
70
|
+
.modal {
|
|
71
|
+
position: relative;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
.modal-container.xs {
|
|
66
75
|
--modal-width: 500px;
|
|
67
76
|
}
|
|
68
77
|
|
|
69
|
-
.modal.md {
|
|
78
|
+
.modal-container.md {
|
|
70
79
|
--modal-width: 600px;
|
|
71
80
|
}
|
|
72
81
|
|
|
73
|
-
.modal.lg {
|
|
82
|
+
.modal-container.lg {
|
|
74
83
|
--modal-width: 800px;
|
|
75
84
|
}
|
|
76
85
|
|
|
77
|
-
.modal.xl {
|
|
86
|
+
.modal-container.xl {
|
|
78
87
|
--modal-width: 1000px;
|
|
79
88
|
}
|
|
80
89
|
|
|
81
|
-
.modal::-webkit-scrollbar {
|
|
90
|
+
.modal-container::-webkit-scrollbar {
|
|
82
91
|
width: 10px;
|
|
83
92
|
}
|
|
84
93
|
|
|
85
|
-
.modal::-webkit-scrollbar-thumb {
|
|
94
|
+
.modal-container::-webkit-scrollbar-thumb {
|
|
86
95
|
background: #888;
|
|
87
96
|
border-radius: 10px;
|
|
88
97
|
}
|
|
89
98
|
|
|
90
|
-
.modal::-webkit-scrollbar-thumb:hover {
|
|
99
|
+
.modal-container::-webkit-scrollbar-thumb:hover {
|
|
91
100
|
background: #555;
|
|
92
101
|
}
|
|
93
102
|
|
|
94
|
-
:global(html:has(.modal-
|
|
103
|
+
:global(html:has(.modal-backdrop)) {
|
|
95
104
|
overflow: hidden;
|
|
96
105
|
}
|
|
97
106
|
</style>
|
|
@@ -3,24 +3,27 @@
|
|
|
3
3
|
|
|
4
4
|
interface ModalContentProps {
|
|
5
5
|
content?: Snippet;
|
|
6
|
+
disablePadding?: boolean;
|
|
6
7
|
}
|
|
7
8
|
|
|
8
|
-
let { content }: ModalContentProps = $props();
|
|
9
|
+
let { content, disablePadding = false }: ModalContentProps = $props();
|
|
9
10
|
</script>
|
|
10
11
|
|
|
11
|
-
<div class="modal-content">
|
|
12
|
+
<div class="modal-content" class:padding={!disablePadding}>
|
|
12
13
|
{@render content?.()}
|
|
13
14
|
</div>
|
|
14
15
|
|
|
15
16
|
<style>
|
|
16
17
|
.modal-content {
|
|
17
18
|
display: flex;
|
|
18
|
-
padding: 24px;
|
|
19
19
|
flex-direction: column;
|
|
20
20
|
align-items: flex-start;
|
|
21
21
|
gap: 24px;
|
|
22
22
|
align-self: stretch;
|
|
23
23
|
background: #fff;
|
|
24
|
-
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
.padding {
|
|
27
|
+
padding: 24px;
|
|
25
28
|
}
|
|
26
29
|
</style>
|
|
@@ -4,20 +4,23 @@
|
|
|
4
4
|
let {
|
|
5
5
|
title = '',
|
|
6
6
|
errorIcon = false,
|
|
7
|
+
hideHeader = false,
|
|
7
8
|
onclose
|
|
8
9
|
}: ModalHeaderProps & { onclose: VoidFunction } = $props();
|
|
9
10
|
</script>
|
|
10
11
|
|
|
11
|
-
|
|
12
|
-
<
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
12
|
+
{#if !hideHeader}
|
|
13
|
+
<header class="modal-header">
|
|
14
|
+
<div class="modal-header-title">
|
|
15
|
+
{#if errorIcon}
|
|
16
|
+
<span class="icon error material-icons-outlined">report</span>
|
|
17
|
+
{/if}
|
|
18
|
+
<h2>{title}</h2>
|
|
19
|
+
</div>
|
|
20
|
+
<button type="button" class="close-button material-icons-outlined" onclick={onclose}>close</button
|
|
21
|
+
>
|
|
22
|
+
</header>
|
|
23
|
+
{/if}
|
|
21
24
|
|
|
22
25
|
<style>
|
|
23
26
|
.modal-header,
|
|
@@ -29,6 +32,7 @@
|
|
|
29
32
|
.modal-header {
|
|
30
33
|
padding: 24px;
|
|
31
34
|
align-self: stretch;
|
|
35
|
+
border-bottom: 1px solid #aeb1b9;
|
|
32
36
|
}
|
|
33
37
|
|
|
34
38
|
.modal-header-title > .icon {
|
|
@@ -4,10 +4,12 @@ export interface ModalProps extends ModalHeaderProps, ModalFooterProps {
|
|
|
4
4
|
width?: WidthModal;
|
|
5
5
|
children?: Snippet;
|
|
6
6
|
onclose?: VoidFunction;
|
|
7
|
+
disablePadding?: boolean;
|
|
7
8
|
}
|
|
8
9
|
export interface ModalHeaderProps {
|
|
9
10
|
title?: string;
|
|
10
11
|
errorIcon?: boolean;
|
|
12
|
+
hideHeader?: boolean;
|
|
11
13
|
}
|
|
12
14
|
export interface ModalFooterProps {
|
|
13
15
|
footer?: Snippet;
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import Modal from '../Modal/Modal.svelte';
|
|
3
|
+
import type { ProcessingProps } from './processingState.svelte.js';
|
|
4
|
+
|
|
5
|
+
let {
|
|
6
|
+
title = 'Processing your request',
|
|
7
|
+
text = '',
|
|
8
|
+
show = $bindable(true),
|
|
9
|
+
asModal = false
|
|
10
|
+
}: ProcessingProps = $props();
|
|
11
|
+
</script>
|
|
12
|
+
|
|
13
|
+
{#snippet processingContent()}
|
|
14
|
+
<div class="processing-header">
|
|
15
|
+
<span class="material-icons-outlined processing-icon">autorenew</span>
|
|
16
|
+
<div class="processing-content">
|
|
17
|
+
<h2 class="processing-title">{title}</h2>
|
|
18
|
+
{#if text}
|
|
19
|
+
<p class="processing-text">{text}</p>
|
|
20
|
+
{/if}
|
|
21
|
+
</div>
|
|
22
|
+
</div>
|
|
23
|
+
{/snippet}
|
|
24
|
+
|
|
25
|
+
{#if show}
|
|
26
|
+
{#if asModal}
|
|
27
|
+
<Modal bind:showModal={show} width="xs" hideHeader>
|
|
28
|
+
<div class="modal-processing-content">
|
|
29
|
+
{@render processingContent()}
|
|
30
|
+
</div>
|
|
31
|
+
</Modal>
|
|
32
|
+
{:else}
|
|
33
|
+
{@render processingContent()}
|
|
34
|
+
{/if}
|
|
35
|
+
{/if}
|
|
36
|
+
|
|
37
|
+
<style>
|
|
38
|
+
.processing-header {
|
|
39
|
+
display: flex;
|
|
40
|
+
flex-direction: column;
|
|
41
|
+
align-items: center;
|
|
42
|
+
text-align: center;
|
|
43
|
+
gap: 24px;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
.processing-content {
|
|
47
|
+
display: flex;
|
|
48
|
+
flex-direction: column;
|
|
49
|
+
gap: 8px;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
.processing-title {
|
|
53
|
+
font-size: 18px;
|
|
54
|
+
font-weight: 700;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
.processing-text {
|
|
58
|
+
font-size: 16px;
|
|
59
|
+
white-space: pre-line;
|
|
60
|
+
line-height: 1.5;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
.processing-icon {
|
|
64
|
+
background: linear-gradient(256deg, #00c9cd -2.41%, #472aff 31.72%, #392d9c 65.86%, #000 100%);
|
|
65
|
+
background-clip: text;
|
|
66
|
+
-webkit-background-clip: text;
|
|
67
|
+
-webkit-text-fill-color: transparent;
|
|
68
|
+
font-size: 32px;
|
|
69
|
+
animation: rotate 2s linear infinite;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
@keyframes rotate {
|
|
73
|
+
from {
|
|
74
|
+
transform: rotate(0deg);
|
|
75
|
+
}
|
|
76
|
+
to {
|
|
77
|
+
transform: rotate(360deg);
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
.modal-processing-content {
|
|
82
|
+
display: flex;
|
|
83
|
+
flex-direction: column;
|
|
84
|
+
justify-content: center;
|
|
85
|
+
align-items: center;
|
|
86
|
+
min-height: 200px;
|
|
87
|
+
width: 100%;
|
|
88
|
+
}
|
|
89
|
+
</style>
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import { type SwitcherOption } from '../index.js';
|
|
3
|
+
|
|
4
|
+
interface SwitcherProps {
|
|
5
|
+
options: string[] | SwitcherOption[];
|
|
6
|
+
value?: string | null;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
let { options, value = $bindable() }: SwitcherProps = $props();
|
|
10
|
+
|
|
11
|
+
const isStringArray = (items: string[] | SwitcherOption[]): items is string[] =>
|
|
12
|
+
typeof items[0] === 'string';
|
|
13
|
+
|
|
14
|
+
const originalOptions = $derived<SwitcherOption[]>(
|
|
15
|
+
isStringArray(options) ? options.map((option) => ({ label: option, value: option })) : options
|
|
16
|
+
);
|
|
17
|
+
</script>
|
|
18
|
+
|
|
19
|
+
<div class="switcher-container">
|
|
20
|
+
{#each originalOptions as option}
|
|
21
|
+
<button
|
|
22
|
+
type="button"
|
|
23
|
+
class={['switcher-option', option.value === value && 'active']}
|
|
24
|
+
onclick={() => (value = option.value)}
|
|
25
|
+
>
|
|
26
|
+
{option.label}
|
|
27
|
+
</button>
|
|
28
|
+
{/each}
|
|
29
|
+
</div>
|
|
30
|
+
|
|
31
|
+
<style>
|
|
32
|
+
.switcher-container {
|
|
33
|
+
--primary-color: #472aff;
|
|
34
|
+
--white: #fff;
|
|
35
|
+
--info-1: #eaecff;
|
|
36
|
+
--gray-1: #f4f6f8;
|
|
37
|
+
--gray-3: #aeb1b9;
|
|
38
|
+
--gray-4: #6b7180;
|
|
39
|
+
|
|
40
|
+
display: flex;
|
|
41
|
+
flex-wrap: wrap;
|
|
42
|
+
width: fit-content;
|
|
43
|
+
padding: 4px;
|
|
44
|
+
gap: 12px;
|
|
45
|
+
border: 1px solid var(--gray-3);
|
|
46
|
+
border-radius: 8px;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
.switcher-container > .switcher-option {
|
|
50
|
+
cursor: pointer;
|
|
51
|
+
border: none;
|
|
52
|
+
padding: 4px 20px;
|
|
53
|
+
font-size: 14px;
|
|
54
|
+
color: var(--gray-4);
|
|
55
|
+
font-weight: 500;
|
|
56
|
+
border-radius: 8px;
|
|
57
|
+
background: none;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
.switcher-container > .switcher-option:hover {
|
|
61
|
+
background: var(--gray-1);
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
.switcher-container > .switcher-option:focus-visible {
|
|
65
|
+
box-shadow: 0px 0px 0px 3px #959bff;
|
|
66
|
+
outline: none;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
.switcher-container > .switcher-option.active {
|
|
70
|
+
color: var(--white);
|
|
71
|
+
background: var(--primary-color);
|
|
72
|
+
transition: background 0.2s ease-in-out;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
.switcher-container > .switcher-option.active:hover {
|
|
76
|
+
background: #3520bf;
|
|
77
|
+
}
|
|
78
|
+
</style>
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { type SwitcherOption } from '../index.js';
|
|
2
|
+
interface SwitcherProps {
|
|
3
|
+
options: string[] | SwitcherOption[];
|
|
4
|
+
value?: string | null;
|
|
5
|
+
}
|
|
6
|
+
declare const Switcher: import("svelte").Component<SwitcherProps, {}, "value">;
|
|
7
|
+
type Switcher = ReturnType<typeof Switcher>;
|
|
8
|
+
export default Switcher;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import { fade } from 'svelte/transition';
|
|
3
|
+
import type { WaffleItem } from './waffleState.svelte.js';
|
|
4
|
+
import WaffleItems from './WaffleItems.svelte';
|
|
5
|
+
|
|
6
|
+
interface Props {
|
|
7
|
+
items?: WaffleItem[];
|
|
8
|
+
showWaffle?: boolean;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
let { items = [], showWaffle = false }: Props = $props();
|
|
12
|
+
|
|
13
|
+
const handleTileClick = (item: WaffleItem) => {
|
|
14
|
+
onHandleWaffle();
|
|
15
|
+
window.open(item.url, '_blank', 'noopener,noreferrer');
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
const onHandleWaffle = () => {
|
|
19
|
+
showWaffle = !showWaffle;
|
|
20
|
+
};
|
|
21
|
+
</script>
|
|
22
|
+
|
|
23
|
+
{#if showWaffle}
|
|
24
|
+
<div
|
|
25
|
+
class="waffle-backdrop"
|
|
26
|
+
onclick={onHandleWaffle}
|
|
27
|
+
onkeydown={onHandleWaffle}
|
|
28
|
+
transition:fade={{ duration: 200 }}
|
|
29
|
+
role="button"
|
|
30
|
+
tabindex="0"
|
|
31
|
+
aria-label="Close waffle menu"
|
|
32
|
+
></div>
|
|
33
|
+
|
|
34
|
+
<aside
|
|
35
|
+
class="waffle-dropdown"
|
|
36
|
+
transition:fade={{ duration: 250 }}
|
|
37
|
+
role="dialog"
|
|
38
|
+
aria-labelledby="waffle-title"
|
|
39
|
+
aria-modal="true"
|
|
40
|
+
>
|
|
41
|
+
<h2 class="waffle-title">SoftwareOne Cloud</h2>
|
|
42
|
+
|
|
43
|
+
<div class="waffle-content">
|
|
44
|
+
<ul class="waffle-grid" role="list">
|
|
45
|
+
{#each items as item (item.title)}
|
|
46
|
+
<li role="listitem">
|
|
47
|
+
<WaffleItems {...item} onclickwaffleitems={() => handleTileClick(item)} />
|
|
48
|
+
</li>
|
|
49
|
+
{/each}
|
|
50
|
+
</ul>
|
|
51
|
+
</div>
|
|
52
|
+
</aside>
|
|
53
|
+
{/if}
|
|
54
|
+
|
|
55
|
+
<style>
|
|
56
|
+
.waffle-backdrop {
|
|
57
|
+
position: fixed;
|
|
58
|
+
inset: 0;
|
|
59
|
+
background: rgba(243, 244, 246, 0.5);
|
|
60
|
+
cursor: pointer;
|
|
61
|
+
z-index: 30;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
.waffle-dropdown {
|
|
65
|
+
position: absolute;
|
|
66
|
+
display: flex;
|
|
67
|
+
flex-direction: column;
|
|
68
|
+
border-radius: 8px;
|
|
69
|
+
background: #fff;
|
|
70
|
+
box-shadow:
|
|
71
|
+
0 10px 15px -3px rgba(0, 0, 0, 0.1),
|
|
72
|
+
0 4px 6px -2px rgba(0, 0, 0, 0.05);
|
|
73
|
+
top: 80px;
|
|
74
|
+
left: 0;
|
|
75
|
+
z-index: 40;
|
|
76
|
+
width: 600px;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
.waffle-content {
|
|
80
|
+
padding: 20px 24px 24px 24px;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
.waffle-title {
|
|
84
|
+
padding: 24px 24px 0 24px;
|
|
85
|
+
font-size: 14px;
|
|
86
|
+
font-weight: 600;
|
|
87
|
+
text-align: center;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
.waffle-grid {
|
|
91
|
+
display: grid;
|
|
92
|
+
grid-template-columns: repeat(3, 1fr);
|
|
93
|
+
gap: 16px;
|
|
94
|
+
}
|
|
95
|
+
</style>
|