@softwareone/spi-sv5-library 1.5.3 → 1.5.5
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/Footer/Footer.svelte +2 -2
- package/dist/Header/Header.svelte +23 -21
- package/dist/Header/Header.svelte.d.ts +5 -5
- package/dist/Header/HeaderAccount.svelte +150 -50
- package/dist/Header/HeaderAccount.svelte.d.ts +6 -4
- package/dist/Menu/Menu.svelte +9 -10
- package/dist/Menu/Menu.svelte.d.ts +1 -1
- package/dist/Menu/MenuItem.svelte +3 -3
- package/dist/Waffle/Waffle.svelte +1 -1
- package/dist/Waffle/Waffle.svelte.d.ts +1 -1
- package/package.json +1 -1
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
let { homeUrl = '/' }: FooterProps = $props();
|
|
6
6
|
</script>
|
|
7
7
|
|
|
8
|
-
<
|
|
8
|
+
<footer class="footer-section">
|
|
9
9
|
<a href={homeUrl} title="Home">
|
|
10
10
|
<img alt="SoftwareOne logo" class="logo-image" src="/softwareone-logo-white.svg" />
|
|
11
11
|
</a>
|
|
@@ -31,7 +31,7 @@
|
|
|
31
31
|
</li>
|
|
32
32
|
<li>© 2025 SoftwareOne. All rights reserved</li>
|
|
33
33
|
</ul>
|
|
34
|
-
</
|
|
34
|
+
</footer>
|
|
35
35
|
|
|
36
36
|
<style>
|
|
37
37
|
.footer-section {
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
|
-
import type {
|
|
3
|
-
|
|
2
|
+
import type { MenuItem } from '../index.js';
|
|
3
|
+
import Menu from '../Menu/Menu.svelte';
|
|
4
|
+
import Waffle from '../Waffle/Waffle.svelte';
|
|
5
|
+
import type { WaffleItem } from '../Waffle/waffleState.svelte.js';
|
|
4
6
|
import HeaderAccount from './HeaderAccount.svelte';
|
|
5
7
|
import HeaderLoader from './HeaderLoader.svelte';
|
|
6
8
|
import HeaderLogo from './HeaderLogo.svelte';
|
|
@@ -9,13 +11,12 @@
|
|
|
9
11
|
title?: string;
|
|
10
12
|
homeUrl?: string;
|
|
11
13
|
hideAccount?: boolean;
|
|
12
|
-
hideHelp?: boolean;
|
|
13
|
-
hideNotification?: boolean;
|
|
14
14
|
accountName?: string;
|
|
15
15
|
userName?: string;
|
|
16
16
|
hideLoader?: boolean;
|
|
17
|
-
|
|
18
|
-
|
|
17
|
+
menuItems?: MenuItem[];
|
|
18
|
+
waffleItems?: WaffleItem[];
|
|
19
|
+
profileMenuItems?: MenuItem[];
|
|
19
20
|
}
|
|
20
21
|
|
|
21
22
|
let {
|
|
@@ -25,8 +26,9 @@
|
|
|
25
26
|
accountName = '',
|
|
26
27
|
userName = '',
|
|
27
28
|
hideLoader,
|
|
28
|
-
|
|
29
|
-
|
|
29
|
+
menuItems,
|
|
30
|
+
waffleItems,
|
|
31
|
+
profileMenuItems
|
|
30
32
|
}: HeaderProps = $props();
|
|
31
33
|
|
|
32
34
|
let showWaffle = $state(false);
|
|
@@ -52,12 +54,12 @@
|
|
|
52
54
|
|
|
53
55
|
<svelte:window onkeydown={handleKeydown} />
|
|
54
56
|
|
|
55
|
-
<
|
|
57
|
+
<header class="header-container">
|
|
56
58
|
<nav class="header-section">
|
|
57
59
|
{#if !hideLoader}
|
|
58
60
|
<HeaderLoader />
|
|
59
61
|
{/if}
|
|
60
|
-
{#if
|
|
62
|
+
{#if waffleItems}
|
|
61
63
|
<button
|
|
62
64
|
type="button"
|
|
63
65
|
class={[showWaffle && 'active', 'header-button']}
|
|
@@ -67,13 +69,13 @@
|
|
|
67
69
|
>
|
|
68
70
|
<span class="material-icons icon-span">apps</span>
|
|
69
71
|
</button>
|
|
70
|
-
{
|
|
72
|
+
<Waffle items={waffleItems} bind:showWaffle />
|
|
71
73
|
{/if}
|
|
72
|
-
{#if
|
|
74
|
+
{#if menuItems}
|
|
73
75
|
<button type="button" class="header-button" onclick={toggleMenu} aria-label="menu button">
|
|
74
76
|
<span class="material-icons icon-span menu-icon">menu</span>
|
|
75
77
|
</button>
|
|
76
|
-
{
|
|
78
|
+
<Menu {menuItems} bind:showMenu />
|
|
77
79
|
{/if}
|
|
78
80
|
<a href={homeUrl} title="Home">
|
|
79
81
|
<HeaderLogo />
|
|
@@ -83,12 +85,12 @@
|
|
|
83
85
|
</h2>
|
|
84
86
|
</nav>
|
|
85
87
|
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
<HeaderAccount {accountName} {userName} />
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
</
|
|
88
|
+
{#if !hideAccount}
|
|
89
|
+
<nav class="header-section">
|
|
90
|
+
<HeaderAccount {accountName} {userName} {profileMenuItems} />
|
|
91
|
+
</nav>
|
|
92
|
+
{/if}
|
|
93
|
+
</header>
|
|
92
94
|
|
|
93
95
|
<style>
|
|
94
96
|
.header-button {
|
|
@@ -128,9 +130,9 @@
|
|
|
128
130
|
gap: 24px;
|
|
129
131
|
justify-content: space-between;
|
|
130
132
|
align-items: center;
|
|
131
|
-
padding:
|
|
133
|
+
padding: 0 24px;
|
|
132
134
|
background: #fff;
|
|
133
|
-
height:
|
|
135
|
+
height: 85px;
|
|
134
136
|
border-bottom: 3px solid #aeb1b9;
|
|
135
137
|
position: relative;
|
|
136
138
|
z-index: 50;
|
|
@@ -1,15 +1,15 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { MenuItem } from '../index.js';
|
|
2
|
+
import type { WaffleItem } from '../Waffle/waffleState.svelte.js';
|
|
2
3
|
interface HeaderProps {
|
|
3
4
|
title?: string;
|
|
4
5
|
homeUrl?: string;
|
|
5
6
|
hideAccount?: boolean;
|
|
6
|
-
hideHelp?: boolean;
|
|
7
|
-
hideNotification?: boolean;
|
|
8
7
|
accountName?: string;
|
|
9
8
|
userName?: string;
|
|
10
9
|
hideLoader?: boolean;
|
|
11
|
-
|
|
12
|
-
|
|
10
|
+
menuItems?: MenuItem[];
|
|
11
|
+
waffleItems?: WaffleItem[];
|
|
12
|
+
profileMenuItems?: MenuItem[];
|
|
13
13
|
}
|
|
14
14
|
declare const Header: import("svelte").Component<HeaderProps, {}, "">;
|
|
15
15
|
type Header = ReturnType<typeof Header>;
|
|
@@ -1,85 +1,185 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
|
-
import {
|
|
2
|
+
import { fade } from 'svelte/transition';
|
|
3
|
+
import { goto } from '$app/navigation';
|
|
4
|
+
import { Avatar, type MenuItem } from '../index.js';
|
|
3
5
|
|
|
4
|
-
interface
|
|
5
|
-
accountName
|
|
6
|
-
userName
|
|
6
|
+
interface Props {
|
|
7
|
+
accountName: string;
|
|
8
|
+
userName: string;
|
|
9
|
+
profileMenuItems?: MenuItem[];
|
|
7
10
|
}
|
|
8
11
|
|
|
9
|
-
let { accountName
|
|
12
|
+
let { accountName, userName, profileMenuItems }: Props = $props();
|
|
13
|
+
|
|
14
|
+
let showProfileItems = $state(false);
|
|
15
|
+
|
|
16
|
+
const onClickProfileItem = (url: string) => {
|
|
17
|
+
handleProfile();
|
|
18
|
+
goto(url);
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
const handleProfile = () => {
|
|
22
|
+
showProfileItems = !showProfileItems;
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
const handleKeydown = (event: KeyboardEvent) => {
|
|
26
|
+
if (event.key === 'Escape' && showProfileItems) {
|
|
27
|
+
showProfileItems = false;
|
|
28
|
+
}
|
|
29
|
+
};
|
|
10
30
|
</script>
|
|
11
31
|
|
|
12
|
-
<
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
32
|
+
<svelte:window onkeydown={handleKeydown} />
|
|
33
|
+
|
|
34
|
+
{#snippet profile()}
|
|
35
|
+
<Avatar text={userName} />
|
|
16
36
|
<div class="account-info">
|
|
17
|
-
<
|
|
18
|
-
<
|
|
19
|
-
<div class="account-more-name">Operations | {userName}</div>
|
|
20
|
-
</div>
|
|
37
|
+
<p class="account-name">{accountName}</p>
|
|
38
|
+
<p class="account-more-name">Operations | {userName}</p>
|
|
21
39
|
</div>
|
|
40
|
+
{/snippet}
|
|
41
|
+
|
|
42
|
+
<div class="container">
|
|
43
|
+
{#if profileMenuItems}
|
|
44
|
+
<button
|
|
45
|
+
onclick={() => (showProfileItems = !showProfileItems)}
|
|
46
|
+
type="button"
|
|
47
|
+
class="account-container account-button"
|
|
48
|
+
aria-expanded={showProfileItems}
|
|
49
|
+
>
|
|
50
|
+
{@render profile()}
|
|
51
|
+
</button>
|
|
52
|
+
{:else}
|
|
53
|
+
<div class="account-container">
|
|
54
|
+
{@render profile()}
|
|
55
|
+
</div>
|
|
56
|
+
{/if}
|
|
57
|
+
|
|
58
|
+
{#if showProfileItems}
|
|
59
|
+
<div
|
|
60
|
+
class="account-backdrop"
|
|
61
|
+
onclick={handleProfile}
|
|
62
|
+
onkeydown={handleProfile}
|
|
63
|
+
role="button"
|
|
64
|
+
transition:fade={{ duration: 200 }}
|
|
65
|
+
tabindex="0"
|
|
66
|
+
aria-label="Close profile menu"
|
|
67
|
+
></div>
|
|
68
|
+
<menu class="account-dropdown" transition:fade={{ delay: 50, duration: 250 }}>
|
|
69
|
+
{#each profileMenuItems as item}
|
|
70
|
+
<li>
|
|
71
|
+
<button
|
|
72
|
+
class="account-menu-item"
|
|
73
|
+
type="button"
|
|
74
|
+
onclick={() => {
|
|
75
|
+
onClickProfileItem(item.url);
|
|
76
|
+
}}
|
|
77
|
+
>
|
|
78
|
+
{item.text}
|
|
79
|
+
</button>
|
|
80
|
+
</li>
|
|
81
|
+
{/each}
|
|
82
|
+
</menu>
|
|
83
|
+
{/if}
|
|
22
84
|
</div>
|
|
23
85
|
|
|
24
86
|
<style>
|
|
87
|
+
.container {
|
|
88
|
+
position: relative;
|
|
89
|
+
display: none;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
@media (min-width: 768px) {
|
|
93
|
+
.container {
|
|
94
|
+
display: flex;
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
|
|
25
98
|
.account-container {
|
|
26
99
|
display: flex;
|
|
27
|
-
|
|
100
|
+
width: 256px;
|
|
28
101
|
align-items: center;
|
|
102
|
+
padding: 8px;
|
|
29
103
|
gap: 16px;
|
|
30
|
-
border-radius: 8px;
|
|
31
|
-
background: #fff;
|
|
32
104
|
}
|
|
33
105
|
|
|
34
|
-
.account-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
height:
|
|
38
|
-
|
|
39
|
-
|
|
106
|
+
.account-button {
|
|
107
|
+
border-radius: 6px;
|
|
108
|
+
border: none;
|
|
109
|
+
height: 66px;
|
|
110
|
+
background: transparent;
|
|
111
|
+
cursor: pointer;
|
|
112
|
+
transition: background-color 0.2s ease-in-out;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
.account-button:hover {
|
|
116
|
+
background: #e0e5e8;
|
|
40
117
|
}
|
|
41
118
|
|
|
42
119
|
.account-info {
|
|
43
120
|
display: flex;
|
|
44
121
|
flex-direction: column;
|
|
45
|
-
align
|
|
122
|
+
text-align: left;
|
|
123
|
+
flex: 1;
|
|
124
|
+
word-break: break-words;
|
|
46
125
|
}
|
|
47
126
|
|
|
48
127
|
.account-name {
|
|
49
|
-
display: -webkit-box;
|
|
50
|
-
-webkit-box-orient: vertical;
|
|
51
|
-
-webkit-line-clamp: 1;
|
|
52
|
-
line-clamp: 1;
|
|
53
|
-
width: auto;
|
|
54
|
-
max-width: auto;
|
|
55
|
-
overflow: hidden;
|
|
56
|
-
color: #000;
|
|
57
|
-
text-overflow: ellipsis;
|
|
58
|
-
font-size: 14px;
|
|
59
|
-
font-style: normal;
|
|
60
128
|
font-weight: 500;
|
|
129
|
+
font-size: 14px;
|
|
61
130
|
line-height: 20px;
|
|
62
131
|
}
|
|
63
132
|
|
|
64
|
-
.account-more {
|
|
133
|
+
.account-more-name {
|
|
134
|
+
font-weight: 400;
|
|
135
|
+
font-size: 12px;
|
|
136
|
+
color: #6b7280;
|
|
137
|
+
line-height: normal;
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
.account-backdrop {
|
|
141
|
+
position: fixed;
|
|
142
|
+
inset: 0;
|
|
143
|
+
background: rgba(243, 244, 246, 0.5);
|
|
144
|
+
cursor: pointer;
|
|
145
|
+
z-index: 40;
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
.account-dropdown {
|
|
149
|
+
position: absolute;
|
|
65
150
|
display: flex;
|
|
66
|
-
|
|
67
|
-
|
|
151
|
+
flex-direction: column;
|
|
152
|
+
width: 250px;
|
|
153
|
+
top: 70px;
|
|
154
|
+
gap: 8px;
|
|
155
|
+
padding: 16px;
|
|
156
|
+
background: white;
|
|
157
|
+
border: 1px solid #f3f4f6;
|
|
158
|
+
border-radius: 0 0 10px 10px;
|
|
159
|
+
box-shadow: 0 25px 50px -12px rgba(0, 0, 0, 0.25);
|
|
160
|
+
z-index: 40;
|
|
68
161
|
}
|
|
69
162
|
|
|
70
|
-
.account-
|
|
71
|
-
|
|
72
|
-
width: auto;
|
|
73
|
-
max-width: auto;
|
|
74
|
-
-webkit-box-orient: vertical;
|
|
75
|
-
-webkit-line-clamp: 1;
|
|
76
|
-
line-clamp: 1;
|
|
77
|
-
overflow: hidden;
|
|
78
|
-
color: #6b7180;
|
|
79
|
-
text-overflow: ellipsis;
|
|
80
|
-
font-size: 12px;
|
|
81
|
-
font-style: normal;
|
|
163
|
+
.account-menu-item {
|
|
164
|
+
width: 100%;
|
|
82
165
|
font-weight: 400;
|
|
83
|
-
|
|
166
|
+
font-size: 14px;
|
|
167
|
+
text-align: left;
|
|
168
|
+
line-height: 20px;
|
|
169
|
+
padding: 8px;
|
|
170
|
+
border-radius: 8px;
|
|
171
|
+
border: none;
|
|
172
|
+
background: transparent;
|
|
173
|
+
cursor: pointer;
|
|
174
|
+
transition: background-color 0.2s ease;
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
.account-menu-item:hover {
|
|
178
|
+
background: #f4f6f8;
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
.account-menu-item:focus,
|
|
182
|
+
.account-menu-item:focus-visible {
|
|
183
|
+
background: #eaecff;
|
|
84
184
|
}
|
|
85
185
|
</style>
|
|
@@ -1,7 +1,9 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
1
|
+
import { type MenuItem } from '../index.js';
|
|
2
|
+
interface Props {
|
|
3
|
+
accountName: string;
|
|
4
|
+
userName: string;
|
|
5
|
+
profileMenuItems?: MenuItem[];
|
|
4
6
|
}
|
|
5
|
-
declare const HeaderAccount: import("svelte").Component<
|
|
7
|
+
declare const HeaderAccount: import("svelte").Component<Props, {}, "">;
|
|
6
8
|
type HeaderAccount = ReturnType<typeof HeaderAccount>;
|
|
7
9
|
export default HeaderAccount;
|
package/dist/Menu/Menu.svelte
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
|
-
import { goto } from '$app/navigation';
|
|
3
2
|
import { page } from '$app/state';
|
|
3
|
+
import { fade } from 'svelte/transition';
|
|
4
4
|
|
|
5
5
|
import MainMenuItem from './MenuItem.svelte';
|
|
6
6
|
import type { MenuItem } from './SidebarState.svelte';
|
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
showMenu: boolean;
|
|
11
11
|
}
|
|
12
12
|
|
|
13
|
-
let { menuItems, showMenu }: MenuProps = $props();
|
|
13
|
+
let { menuItems, showMenu = $bindable(false) }: MenuProps = $props();
|
|
14
14
|
|
|
15
15
|
let activeItem = $state('');
|
|
16
16
|
|
|
@@ -28,10 +28,6 @@
|
|
|
28
28
|
return regex.test(pathname);
|
|
29
29
|
};
|
|
30
30
|
|
|
31
|
-
const onClickMenuItem = (menuItem: MenuItem) => {
|
|
32
|
-
onHandleMenu();
|
|
33
|
-
goto(menuItem.url);
|
|
34
|
-
};
|
|
35
31
|
|
|
36
32
|
const onHandleMenu = () => {
|
|
37
33
|
showMenu = !showMenu;
|
|
@@ -45,21 +41,24 @@
|
|
|
45
41
|
</script>
|
|
46
42
|
|
|
47
43
|
{#if showMenu}
|
|
48
|
-
<
|
|
44
|
+
<div
|
|
49
45
|
class="menu-principal"
|
|
50
46
|
onclick={onHandleMenu}
|
|
51
47
|
onkeypress={onHandleMenu}
|
|
48
|
+
transition:fade={{ duration: 200 }}
|
|
49
|
+
role="button"
|
|
50
|
+
tabindex="0"
|
|
52
51
|
aria-label="menu principal"
|
|
53
|
-
></
|
|
52
|
+
></div>
|
|
54
53
|
|
|
55
|
-
<nav class="menu-nav">
|
|
54
|
+
<nav class="menu-nav" transition:fade={{ duration: 250 }}>
|
|
56
55
|
<menu class="menu-list">
|
|
57
56
|
{#each menuItems as menuItem}
|
|
58
57
|
<MainMenuItem
|
|
59
58
|
item={menuItem}
|
|
60
59
|
isCollapsed={false}
|
|
61
60
|
activeItem={activeItem === menuItem.text}
|
|
62
|
-
onClick={
|
|
61
|
+
onClick={onHandleMenu}
|
|
63
62
|
/>
|
|
64
63
|
{/each}
|
|
65
64
|
</menu>
|
|
@@ -3,6 +3,6 @@ interface MenuProps {
|
|
|
3
3
|
menuItems: MenuItem[];
|
|
4
4
|
showMenu: boolean;
|
|
5
5
|
}
|
|
6
|
-
declare const Menu: import("svelte").Component<MenuProps, {}, "">;
|
|
6
|
+
declare const Menu: import("svelte").Component<MenuProps, {}, "showMenu">;
|
|
7
7
|
type Menu = ReturnType<typeof Menu>;
|
|
8
8
|
export default Menu;
|
|
@@ -14,8 +14,8 @@
|
|
|
14
14
|
|
|
15
15
|
<li>
|
|
16
16
|
<Tooltip content={isCollapsed ? item.text : ''} position="right">
|
|
17
|
-
<
|
|
18
|
-
|
|
17
|
+
<a
|
|
18
|
+
href={item.url}
|
|
19
19
|
class={[
|
|
20
20
|
'item',
|
|
21
21
|
isCollapsed ? 'collapsed' : 'expanded',
|
|
@@ -25,7 +25,7 @@
|
|
|
25
25
|
>
|
|
26
26
|
<span class="material-icons-outlined icon-span">{item.icon}</span>
|
|
27
27
|
<h2 class="item-name-span" class:hidden={isCollapsed}>{item.text}</h2>
|
|
28
|
-
</
|
|
28
|
+
</a>
|
|
29
29
|
</Tooltip>
|
|
30
30
|
</li>
|
|
31
31
|
|
|
@@ -3,6 +3,6 @@ interface Props {
|
|
|
3
3
|
items?: WaffleItem[];
|
|
4
4
|
showWaffle?: boolean;
|
|
5
5
|
}
|
|
6
|
-
declare const Waffle: import("svelte").Component<Props, {}, "">;
|
|
6
|
+
declare const Waffle: import("svelte").Component<Props, {}, "showWaffle">;
|
|
7
7
|
type Waffle = ReturnType<typeof Waffle>;
|
|
8
8
|
export default Waffle;
|