@softwareone/spi-sv5-library 0.1.3 → 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.
Files changed (55) hide show
  1. package/dist/Avatar/Avatar.svelte +33 -0
  2. package/dist/Avatar/Avatar.svelte.d.ts +10 -0
  3. package/dist/Breadcrumbs/Breadcrumbs.svelte +10 -20
  4. package/dist/Button/Button.svelte +59 -119
  5. package/dist/Button/Button.svelte.d.ts +8 -6
  6. package/dist/Card/Card.svelte +18 -44
  7. package/dist/Card/Card.svelte.d.ts +1 -1
  8. package/dist/Chips/Chips.svelte +25 -28
  9. package/dist/Chips/Chips.svelte.d.ts +2 -1
  10. package/dist/Chips/chipsState.svelte.d.ts +7 -0
  11. package/dist/Chips/chipsState.svelte.js +8 -0
  12. package/dist/ErrorPage/ErrorPage.svelte +98 -0
  13. package/dist/ErrorPage/ErrorPage.svelte.d.ts +8 -0
  14. package/dist/Footer/Footer.svelte +29 -135
  15. package/dist/Footer/Footer.svelte.d.ts +1 -1
  16. package/dist/Form/Input/Input.svelte +398 -0
  17. package/dist/Form/Input/Input.svelte.d.ts +14 -0
  18. package/dist/Form/Input/InputIcon.svelte +97 -0
  19. package/dist/Form/Input/InputIcon.svelte.d.ts +9 -0
  20. package/dist/Form/TextArea/TextArea.svelte +258 -0
  21. package/dist/Form/TextArea/TextArea.svelte.d.ts +13 -0
  22. package/dist/Form/Toggle/Toggle.svelte +120 -0
  23. package/dist/{Toggle → Form/Toggle}/Toggle.svelte.d.ts +4 -3
  24. package/dist/Header/Header.svelte +55 -133
  25. package/dist/Header/Header.svelte.d.ts +2 -1
  26. package/dist/Header/HeaderAccount.svelte +6 -29
  27. package/dist/HighlightPanel/HighlightPanel.svelte +125 -0
  28. package/dist/HighlightPanel/HighlightPanel.svelte.d.ts +10 -0
  29. package/dist/HighlightPanel/highlightPanelState.svelte.d.ts +35 -0
  30. package/dist/HighlightPanel/highlightPanelState.svelte.js +13 -0
  31. package/dist/Menu/Menu.svelte +158 -0
  32. package/dist/Menu/Menu.svelte.d.ts +8 -0
  33. package/dist/Menu/MenuItem.svelte +153 -0
  34. package/dist/Menu/MenuItem.svelte.d.ts +11 -0
  35. package/dist/Menu/Sidebar.svelte +228 -0
  36. package/dist/Menu/Sidebar.svelte.d.ts +11 -0
  37. package/dist/Menu/SidebarState.svelte.d.ts +6 -0
  38. package/dist/Menu/SidebarState.svelte.js +1 -0
  39. package/dist/Modal/Modal.svelte +2 -3
  40. package/dist/Modal/ModalContent.svelte +11 -18
  41. package/dist/Modal/ModalFooter.svelte +10 -14
  42. package/dist/Modal/ModalHeader.svelte +7 -9
  43. package/dist/ProgressWizard/ProgressWizard.svelte +19 -34
  44. package/dist/Tabs/Tabs.svelte +111 -0
  45. package/dist/Tabs/Tabs.svelte.d.ts +8 -0
  46. package/dist/Tabs/tabsState.svelte.d.ts +7 -0
  47. package/dist/Tabs/tabsState.svelte.js +1 -0
  48. package/dist/Toast/Toast.svelte +7 -12
  49. package/dist/Tooltip/Tooltip.svelte +168 -0
  50. package/dist/Tooltip/Tooltip.svelte.d.ts +13 -0
  51. package/dist/assets/icons/feedback.svg +5 -0
  52. package/dist/index.d.ts +25 -8
  53. package/dist/index.js +23 -9
  54. package/package.json +2 -1
  55. package/dist/Toggle/Toggle.svelte +0 -170
@@ -0,0 +1,97 @@
1
+ <script lang="ts">
2
+ type IconType = 'error' | 'success' | 'password';
3
+
4
+ interface Props {
5
+ type: IconType;
6
+ isPasswordVisible?: boolean;
7
+ isDateInput?: boolean;
8
+ }
9
+
10
+ let { type, isPasswordVisible = $bindable(false), isDateInput = false }: Props = $props();
11
+
12
+ const icons: Record<Exclude<IconType, 'password'>, string> = {
13
+ error: 'priority_high',
14
+ success: 'check'
15
+ };
16
+ </script>
17
+
18
+ <div class="form-input-icon">
19
+ {#if type === 'password'}
20
+ <button
21
+ type="button"
22
+ class="form-input-icon-button"
23
+ onclick={() => (isPasswordVisible = !isPasswordVisible)}
24
+ aria-label={isPasswordVisible ? 'Hide password' : 'Show password'}
25
+ >
26
+ <span class="material-icons-outlined form-input-icon form-input-icon--password">
27
+ {isPasswordVisible ? 'visibility_off' : 'visibility'}
28
+ </span>
29
+ </button>
30
+ {:else}
31
+ <span class="material-icons-outlined form-input-icon form-input-icon--{type}"
32
+ class:form-input-icon--date-status={isDateInput && (type === 'error' || type === 'success')}
33
+ >{icons[type]}</span
34
+ >
35
+ {/if}
36
+ </div>
37
+
38
+ <style>
39
+ .form-input-icon {
40
+ display: inline-flex;
41
+ align-items: center;
42
+ justify-content: center;
43
+ font-size: 18px;
44
+ height: 18px;
45
+ line-height: 1;
46
+ position: static;
47
+ transform: none;
48
+ }
49
+
50
+ .form-input-icon--error {
51
+ color: #dc2626;
52
+ }
53
+
54
+ .form-input-icon--success {
55
+ color: #059669;
56
+ }
57
+
58
+ .form-input-icon--password {
59
+ color: inherit;
60
+ }
61
+
62
+ .form-input-icon--date-status {
63
+ margin-right: 40px;
64
+ }
65
+
66
+ @-moz-document url-prefix() {
67
+ .form-input-icon--date-status {
68
+ margin-right: 35px;
69
+ }
70
+ }
71
+
72
+ .form-input-icon-button {
73
+ background: none;
74
+ border: none;
75
+ padding: 4px;
76
+ cursor: pointer;
77
+ display: flex;
78
+ align-items: center;
79
+ justify-content: center;
80
+ color: #000;
81
+ transition: color 0.2s ease;
82
+ width: 24px;
83
+ height: 24px;
84
+ border-radius: 4px;
85
+ position: relative;
86
+ z-index: 1;
87
+ pointer-events: auto;
88
+ }
89
+
90
+ .form-input-icon-button:focus {
91
+ outline: none;
92
+ }
93
+
94
+ .form-input-icon-button:active {
95
+ transform: scale(0.95);
96
+ }
97
+ </style>
@@ -0,0 +1,9 @@
1
+ type IconType = 'error' | 'success' | 'password';
2
+ interface Props {
3
+ type: IconType;
4
+ isPasswordVisible?: boolean;
5
+ isDateInput?: boolean;
6
+ }
7
+ declare const InputIcon: import("svelte").Component<Props, {}, "isPasswordVisible">;
8
+ type InputIcon = ReturnType<typeof InputIcon>;
9
+ export default InputIcon;
@@ -0,0 +1,258 @@
1
+ <script lang="ts">
2
+ import type { HTMLTextareaAttributes } from 'svelte/elements';
3
+
4
+ interface TextAreaProps extends Omit<HTMLTextareaAttributes, 'value'> {
5
+ label?: string;
6
+ value?: string;
7
+ optional?: boolean;
8
+ error?: string;
9
+ description?: string;
10
+ maximumCharactersAllowed?: number;
11
+ resize?: boolean;
12
+ }
13
+
14
+ let {
15
+ label,
16
+ value = $bindable(''),
17
+ optional = false,
18
+ error,
19
+ description,
20
+ maximumCharactersAllowed,
21
+ resize = false,
22
+ id,
23
+ ...props
24
+ }: TextAreaProps = $props();
25
+
26
+ const componentId = $props.id();
27
+ const textareaId = id || componentId;
28
+
29
+ const currentTextLength = $derived(value?.trim().length ?? 0);
30
+ const isOverLimit = $derived(
31
+ maximumCharactersAllowed ? currentTextLength > maximumCharactersAllowed : false
32
+ );
33
+ const errorMessage = $derived(isOverLimit ? 'Character limit exceeded' : error);
34
+ const isInvalid = $derived(!!errorMessage);
35
+ const isValid = $derived(!isInvalid && (!!value || optional));
36
+ </script>
37
+
38
+ <div class="form-container">
39
+ {#if label}
40
+ <div class="form-label-container">
41
+ <label for={textareaId}>{label}</label>
42
+ {#if props.required}
43
+ <span class="form-label-required">Required</span>
44
+ {:else if optional}
45
+ <span class="form-label-optional">Optional</span>
46
+ {/if}
47
+ </div>
48
+ {/if}
49
+
50
+ <div class={['form-textarea-wrapper', isInvalid && 'error', isValid && 'success']}>
51
+ <textarea
52
+ {...props}
53
+ id={textareaId}
54
+ bind:value
55
+ class={[
56
+ 'form-textarea',
57
+ props.disabled && 'form-textarea-disabled',
58
+ props.readonly && 'form-textarea-readonly',
59
+ !resize && 'form-textarea-no-resize'
60
+ ]}
61
+ aria-invalid={isInvalid}
62
+ ></textarea>
63
+ </div>
64
+
65
+ {#if !!(maximumCharactersAllowed || error || description)}
66
+ <div class="form-footer">
67
+ <div class="form-messages">
68
+ {#if description}
69
+ <p class="form-message form-message-description">
70
+ {description}
71
+ </p>
72
+ {/if}
73
+ {#if errorMessage}
74
+ <p class="form-message form-message-error">
75
+ {errorMessage}
76
+ </p>
77
+ {/if}
78
+ </div>
79
+ {#if maximumCharactersAllowed}
80
+ <div class={['form-character-count', isOverLimit && 'error']}>
81
+ {currentTextLength} / {maximumCharactersAllowed}
82
+ </div>
83
+ {/if}
84
+ </div>
85
+ {/if}
86
+ </div>
87
+
88
+ <style>
89
+ .form-container {
90
+ display: flex;
91
+ flex-direction: column;
92
+ gap: 8px;
93
+ font-size: 14px;
94
+ line-height: 20px;
95
+ }
96
+
97
+ .form-label-container {
98
+ display: flex;
99
+ gap: 8px;
100
+ font-weight: 500;
101
+ }
102
+
103
+ .form-label-optional {
104
+ color: #6b7180;
105
+ }
106
+
107
+ .form-label-required {
108
+ color: #dc2626;
109
+ }
110
+
111
+ .form-message {
112
+ font-size: 12px;
113
+ }
114
+
115
+ .form-textarea-wrapper {
116
+ position: relative;
117
+ display: flex;
118
+ width: 100%;
119
+ border-radius: 8px;
120
+ border: 1px solid #6b7180;
121
+ background: #fff;
122
+ transition: all 0.2s ease-in-out;
123
+ overflow: hidden;
124
+ }
125
+
126
+ .form-textarea-wrapper:hover:not(:has(.form-textarea:disabled)):not(
127
+ :has(.form-textarea:read-only)
128
+ ),
129
+ .form-textarea-wrapper:focus-within {
130
+ border-color: #472aff;
131
+ }
132
+
133
+ .form-textarea-wrapper:focus-within {
134
+ box-shadow: 0px 0px 0px 3px rgba(149, 155, 255, 0.3);
135
+ }
136
+
137
+ .form-textarea {
138
+ font-size: 14px;
139
+ line-height: 20px;
140
+ display: flex;
141
+ width: 100%;
142
+ min-height: 80px;
143
+ padding: 8px 16px;
144
+ border: none;
145
+ border-radius: 8px;
146
+ color: #000;
147
+ transition: all 0.2s ease-in-out;
148
+ font-family: inherit;
149
+ }
150
+
151
+ .form-textarea:focus {
152
+ outline: none;
153
+ }
154
+
155
+ .form-textarea-disabled {
156
+ background-color: #f3f4f6;
157
+ border-color: #d1d5db;
158
+ color: #6b7180;
159
+ cursor: not-allowed;
160
+ }
161
+
162
+ .form-textarea-readonly {
163
+ background-color: #f9fafb;
164
+ border-color: #d1d5db;
165
+ cursor: default;
166
+ }
167
+
168
+ .form-textarea-no-resize {
169
+ resize: none;
170
+ }
171
+
172
+ .form-textarea::placeholder,
173
+ .form-textarea:disabled::placeholder {
174
+ color: #6b7180;
175
+ opacity: 1;
176
+ }
177
+
178
+ .form-footer {
179
+ display: flex;
180
+ justify-content: space-between;
181
+ align-items: flex-start;
182
+ gap: 8px;
183
+ }
184
+
185
+ .form-messages {
186
+ display: flex;
187
+ flex-direction: column;
188
+ gap: 4px;
189
+ flex: 1;
190
+ }
191
+
192
+ .form-message-error {
193
+ color: #dc2626;
194
+ }
195
+
196
+ .form-message-description {
197
+ color: #6b7180;
198
+ }
199
+
200
+ .form-character-count {
201
+ font-size: 12px;
202
+ color: #6b7180;
203
+ white-space: nowrap;
204
+ flex-shrink: 0;
205
+ }
206
+
207
+ .form-character-count.error {
208
+ color: #dc2626;
209
+ }
210
+
211
+ .form-textarea-wrapper.error,
212
+ .form-textarea-wrapper.error:hover:not(:has(.form-textarea:disabled)):not(
213
+ :has(.form-textarea:read-only)
214
+ ),
215
+ .form-textarea-wrapper.error:focus-within {
216
+ border-color: #dc2626;
217
+ }
218
+
219
+ .form-textarea-wrapper.error:focus-within {
220
+ box-shadow: 0px 0px 0px 3px rgba(220, 38, 38, 0.2);
221
+ }
222
+
223
+ .form-textarea-wrapper.success {
224
+ border-color: #008556;
225
+ }
226
+
227
+ .form-textarea-wrapper.success:hover:not(:has(.form-textarea:disabled)):not(:has(.form-textarea:read-only)),
228
+ .form-textarea-wrapper.success:focus-within {
229
+ border-color: #10b981;
230
+ }
231
+
232
+ .form-textarea-wrapper.success:focus-within {
233
+ box-shadow: 0px 0px 0px 3px rgba(16, 185, 129, 0.15);
234
+ }
235
+
236
+ .form-textarea-wrapper:has(.form-textarea:disabled),
237
+ .form-textarea-wrapper:has(.form-textarea:read-only) {
238
+ border-color: #d1d5db !important;
239
+ box-shadow: none !important;
240
+ }
241
+
242
+ @media (prefers-contrast: high) {
243
+ .form-textarea {
244
+ border-width: 2px;
245
+ }
246
+
247
+ .form-textarea:focus {
248
+ outline: 2px solid;
249
+ outline-offset: 2px;
250
+ }
251
+ }
252
+
253
+ @media (prefers-reduced-motion: reduce) {
254
+ .form-textarea {
255
+ transition: none;
256
+ }
257
+ }
258
+ </style>
@@ -0,0 +1,13 @@
1
+ import type { HTMLTextareaAttributes } from 'svelte/elements';
2
+ interface TextAreaProps extends Omit<HTMLTextareaAttributes, 'value'> {
3
+ label?: string;
4
+ value?: string;
5
+ optional?: boolean;
6
+ error?: string;
7
+ description?: string;
8
+ maximumCharactersAllowed?: number;
9
+ resize?: boolean;
10
+ }
11
+ declare const TextArea: import("svelte").Component<TextAreaProps, {}, "value">;
12
+ type TextArea = ReturnType<typeof TextArea>;
13
+ export default TextArea;
@@ -0,0 +1,120 @@
1
+ <script lang="ts">
2
+ interface ToggleProps {
3
+ id?: string;
4
+ checked?: boolean;
5
+ disabled?: boolean;
6
+ onchange?: (event: Event) => void;
7
+ }
8
+
9
+ let { id = '', checked = $bindable(false), disabled = false, onchange }: ToggleProps = $props();
10
+ </script>
11
+
12
+ <label class="toggle-container">
13
+ <input
14
+ type="checkbox"
15
+ class="toggle-input"
16
+ bind:checked
17
+ {disabled}
18
+ {id}
19
+ {onchange}
20
+ role="switch"
21
+ />
22
+ <div class={['toggle-slider', checked && 'checked', disabled && 'disabled']}>
23
+ <span class="material-icons-outlined toggle-icon">
24
+ {#if checked}
25
+ done
26
+ {:else}
27
+ close
28
+ {/if}
29
+ </span>
30
+ </div>
31
+ </label>
32
+
33
+ <style>
34
+ .toggle-container {
35
+ position: relative;
36
+ }
37
+
38
+ .toggle-input {
39
+ position: absolute;
40
+ opacity: 0;
41
+ width: 0;
42
+ height: 0;
43
+ }
44
+
45
+ .toggle-slider {
46
+ display: flex;
47
+ width: 40px;
48
+ padding: 2px;
49
+ align-items: center;
50
+ border-radius: 12px;
51
+ border: 2px solid #6b7180;
52
+ background: #fff;
53
+ transition: all 0.3s ease;
54
+ cursor: pointer;
55
+ }
56
+
57
+ .toggle-slider.checked {
58
+ justify-content: flex-end;
59
+ border: 2px solid #472aff;
60
+ background: #472aff;
61
+ }
62
+
63
+ .toggle-slider.disabled {
64
+ cursor: not-allowed;
65
+ border: 2px solid #6b7180;
66
+ background: #e0e5e8;
67
+ }
68
+
69
+ .toggle-slider.disabled.checked {
70
+ border: 2px solid #6b7180;
71
+ background: #6b7180;
72
+ }
73
+
74
+ .toggle-icon {
75
+ display: flex;
76
+ font-size: 12px;
77
+ flex-direction: column;
78
+ align-items: center;
79
+ justify-content: center;
80
+ border-radius: 16px;
81
+ border: 2px solid #6b7180;
82
+ background: #6b7180;
83
+ color: #fff;
84
+ transition: all 0.3s ease;
85
+ cursor: pointer;
86
+ }
87
+
88
+ .toggle-slider.checked .toggle-icon {
89
+ border: 2px solid #fff;
90
+ background: #fff;
91
+ color: #472aff;
92
+ }
93
+
94
+ .toggle-slider.disabled .toggle-icon {
95
+ cursor: not-allowed;
96
+ border: 2px solid #6b7180;
97
+ background: #6b7180;
98
+ color: #fff;
99
+ }
100
+
101
+ .toggle-slider.disabled.checked .toggle-icon {
102
+ border: 2px solid #fff;
103
+ background: #fff;
104
+ color: #6b7180;
105
+ }
106
+
107
+ .toggle-container:hover .toggle-slider:not(.disabled).checked {
108
+ background: #3520bf;
109
+ border: 2px solid #3520bf;
110
+ }
111
+
112
+ .toggle-container:hover .toggle-slider:not(.disabled):not(.checked) {
113
+ border: 2px solid #434952;
114
+ }
115
+
116
+ .toggle-container:hover .toggle-slider:not(.disabled):not(.checked) .toggle-icon {
117
+ border: 2px solid #434952;
118
+ background: #434952;
119
+ }
120
+ </style>
@@ -1,8 +1,9 @@
1
1
  interface ToggleProps {
2
- status?: 'on' | 'off';
2
+ id?: string;
3
+ checked?: boolean;
3
4
  disabled?: boolean;
4
- onToggle?: () => void;
5
+ onchange?: (event: Event) => void;
5
6
  }
6
- declare const Toggle: import("svelte").Component<ToggleProps, {}, "">;
7
+ declare const Toggle: import("svelte").Component<ToggleProps, {}, "checked">;
7
8
  type Toggle = ReturnType<typeof Toggle>;
8
9
  export default Toggle;