@softwareone/spi-sv5-library 0.1.3 → 1.1.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 (72) hide show
  1. package/README.md +75 -19
  2. package/dist/Avatar/Avatar.svelte +33 -0
  3. package/dist/Avatar/Avatar.svelte.d.ts +10 -0
  4. package/dist/Breadcrumbs/Breadcrumbs.svelte +10 -20
  5. package/dist/Button/Button.svelte +66 -115
  6. package/dist/Button/Button.svelte.d.ts +8 -6
  7. package/dist/Card/Card.svelte +18 -44
  8. package/dist/Card/Card.svelte.d.ts +1 -1
  9. package/dist/Chips/Chips.svelte +40 -46
  10. package/dist/Chips/Chips.svelte.d.ts +2 -1
  11. package/dist/Chips/chipsState.svelte.d.ts +7 -0
  12. package/dist/Chips/chipsState.svelte.js +8 -0
  13. package/dist/ErrorPage/ErrorPage.svelte +96 -0
  14. package/dist/ErrorPage/ErrorPage.svelte.d.ts +7 -0
  15. package/dist/Footer/Footer.svelte +29 -135
  16. package/dist/Footer/Footer.svelte.d.ts +1 -1
  17. package/dist/Form/Input/Input.svelte +393 -0
  18. package/dist/Form/Input/Input.svelte.d.ts +14 -0
  19. package/dist/Form/Input/InputIcon.svelte +97 -0
  20. package/dist/Form/Input/InputIcon.svelte.d.ts +9 -0
  21. package/dist/Form/TextArea/TextArea.svelte +260 -0
  22. package/dist/Form/TextArea/TextArea.svelte.d.ts +13 -0
  23. package/dist/Form/Toggle/Toggle.svelte +120 -0
  24. package/dist/{Toggle → Form/Toggle}/Toggle.svelte.d.ts +4 -3
  25. package/dist/Header/Header.svelte +54 -136
  26. package/dist/Header/Header.svelte.d.ts +2 -2
  27. package/dist/Header/HeaderAccount.svelte +14 -35
  28. package/dist/Header/HeaderLoader.svelte +2 -2
  29. package/dist/Header/HeaderLogo.svelte +7 -4
  30. package/dist/Header/HeaderLogo.svelte.d.ts +14 -6
  31. package/dist/HighlightPanel/HighlightPanel.svelte +125 -0
  32. package/dist/HighlightPanel/HighlightPanel.svelte.d.ts +10 -0
  33. package/dist/HighlightPanel/highlightPanelState.svelte.d.ts +35 -0
  34. package/dist/HighlightPanel/highlightPanelState.svelte.js +13 -0
  35. package/dist/Menu/Menu.svelte +158 -0
  36. package/dist/Menu/Menu.svelte.d.ts +8 -0
  37. package/dist/Menu/MenuItem.svelte +149 -0
  38. package/dist/Menu/MenuItem.svelte.d.ts +11 -0
  39. package/dist/Menu/Sidebar.svelte +228 -0
  40. package/dist/Menu/Sidebar.svelte.d.ts +11 -0
  41. package/dist/Menu/SidebarState.svelte.d.ts +6 -0
  42. package/dist/Menu/SidebarState.svelte.js +1 -0
  43. package/dist/Modal/Modal.svelte +81 -29
  44. package/dist/Modal/Modal.svelte.d.ts +2 -9
  45. package/dist/Modal/ModalContent.svelte +8 -88
  46. package/dist/Modal/ModalContent.svelte.d.ts +2 -3
  47. package/dist/Modal/ModalFooter.svelte +21 -66
  48. package/dist/Modal/ModalFooter.svelte.d.ts +5 -5
  49. package/dist/Modal/ModalHeader.svelte +50 -34
  50. package/dist/Modal/ModalHeader.svelte.d.ts +5 -4
  51. package/dist/Modal/modalState.svelte.d.ts +15 -0
  52. package/dist/Modal/modalState.svelte.js +1 -0
  53. package/dist/ProgressWizard/ProgressWizard.svelte +273 -294
  54. package/dist/ProgressWizard/ProgressWizard.svelte.d.ts +11 -13
  55. package/dist/ProgressWizard/progressWizardState.svelte.d.ts +6 -0
  56. package/dist/ProgressWizard/progressWizardState.svelte.js +1 -0
  57. package/dist/Search/Search.svelte +154 -0
  58. package/dist/Search/Search.svelte.d.ts +10 -0
  59. package/dist/Tabs/Tabs.svelte +111 -0
  60. package/dist/Tabs/Tabs.svelte.d.ts +8 -0
  61. package/dist/Tabs/tabsState.svelte.d.ts +7 -0
  62. package/dist/Tabs/tabsState.svelte.js +1 -0
  63. package/dist/Toast/Toast.svelte +116 -49
  64. package/dist/Toast/toastState.svelte.d.ts +7 -3
  65. package/dist/Toast/toastState.svelte.js +13 -10
  66. package/dist/Tooltip/Tooltip.svelte +168 -0
  67. package/dist/Tooltip/Tooltip.svelte.d.ts +13 -0
  68. package/dist/assets/icons/feedback.svg +5 -0
  69. package/dist/index.d.ts +28 -8
  70. package/dist/index.js +24 -9
  71. package/package.json +4 -5
  72. package/dist/Toggle/Toggle.svelte +0 -170
@@ -0,0 +1,393 @@
1
+ <script lang="ts">
2
+ import type { HTMLInputAttributes } from 'svelte/elements';
3
+ import InputIcon from './InputIcon.svelte';
4
+
5
+ type InputType = 'text' | 'password' | 'number' | 'date' | 'money';
6
+
7
+ interface InputProps extends Omit<HTMLInputAttributes, 'type' | 'value'> {
8
+ label?: string;
9
+ type?: InputType;
10
+ value?: string | number | null;
11
+ optional?: boolean;
12
+ error?: string | string[];
13
+ description?: string;
14
+ currency?: string;
15
+ }
16
+
17
+ let {
18
+ label,
19
+ type = 'text',
20
+ value = $bindable(''),
21
+ optional = false,
22
+ error,
23
+ description,
24
+ currency,
25
+ id,
26
+ disabled,
27
+ readonly,
28
+ required,
29
+ oninput,
30
+ ...props
31
+ }: InputProps = $props();
32
+
33
+ let isPasswordVisible = $state(false);
34
+
35
+ const componentId = $props.id();
36
+ const inputId = id || componentId;
37
+
38
+ const isInvalid = $derived(!!error);
39
+ const isValid = $derived(!isInvalid && (!!value || optional));
40
+ const hasStatus = $derived(isInvalid || isValid);
41
+ const showIcon = $derived(hasStatus || ['password', 'money'].includes(type));
42
+ const showDatePicker = $derived(type === 'date');
43
+
44
+ const transformationType = $derived<Record<string, string>>({
45
+ money: 'number',
46
+ password: isPasswordVisible ? 'text' : 'password'
47
+ });
48
+ </script>
49
+
50
+ <div class="form-container">
51
+ {#if label}
52
+ <div class="form-label-container">
53
+ <label for={inputId}>{label}</label>
54
+ {#if required}
55
+ <span class="form-label-required">Required</span>
56
+ {:else if optional}
57
+ <span class="form-label-optional">Optional</span>
58
+ {/if}
59
+ </div>
60
+ {/if}
61
+
62
+ <div
63
+ class={[
64
+ 'form-input-wrapper',
65
+ isInvalid && 'error',
66
+ isValid && 'success',
67
+ type === 'money' && currency && 'money-with-icon'
68
+ ]}
69
+ >
70
+ <input
71
+ bind:value
72
+ {...props}
73
+ id={inputId}
74
+ type={transformationType[type] ?? type}
75
+ {disabled}
76
+ {readonly}
77
+ class={[
78
+ 'form-input',
79
+ disabled && 'form-input-disabled',
80
+ readonly && 'form-input-readonly',
81
+ (showIcon || showDatePicker) && 'form-input-with-icon',
82
+ showDatePicker && 'form-input-date'
83
+ ]}
84
+ aria-invalid={isInvalid}
85
+ />
86
+
87
+ {#if type === 'money' && currency}
88
+ <div class="form-input-currency">{currency}</div>
89
+ {/if}
90
+
91
+ {#if showIcon}
92
+ <div
93
+ class={[
94
+ 'form-input-icon-container',
95
+ type === 'password' && hasStatus && 'form-input-icon-container-password'
96
+ ]}
97
+ >
98
+ {#if hasStatus}
99
+ <InputIcon type={isInvalid ? 'error' : 'success'} isDateInput={showDatePicker} />
100
+ {/if}
101
+
102
+ {#if type === 'password'}
103
+ <InputIcon type="password" bind:isPasswordVisible />
104
+ {/if}
105
+ </div>
106
+ {/if}
107
+ </div>
108
+
109
+ {#if description}
110
+ <p class="form-message form-message-description">
111
+ {description}
112
+ </p>
113
+ {/if}
114
+ {#if isInvalid}
115
+ <p class="form-message form-message-error">
116
+ {Array.isArray(error) ? error[0] : error}
117
+ </p>
118
+ {/if}
119
+ </div>
120
+
121
+ <style>
122
+ .form-container {
123
+ display: flex;
124
+ flex-direction: column;
125
+ gap: 8px;
126
+ font-size: 14px;
127
+ line-height: 20px;
128
+ }
129
+
130
+ .form-label-container {
131
+ display: flex;
132
+ gap: 8px;
133
+ font-weight: 500;
134
+ }
135
+
136
+ .form-label-optional {
137
+ color: #6b7180;
138
+ }
139
+
140
+ .form-label-required {
141
+ color: #dc2626;
142
+ }
143
+
144
+ .form-message {
145
+ font-size: 12px;
146
+ }
147
+
148
+ .form-input-wrapper {
149
+ position: relative;
150
+ display: flex;
151
+ align-items: center;
152
+ width: 100%;
153
+ border-radius: 8px;
154
+ border: 1px solid #6b7180;
155
+ background: #fff;
156
+ transition: all 0.2s ease-in-out;
157
+ }
158
+
159
+ .form-input-wrapper:hover:not(:has(.form-input:disabled)):not(:has(.form-input:read-only)),
160
+ .form-input-wrapper:focus-within {
161
+ border-color: #472aff;
162
+ }
163
+
164
+ .form-input-wrapper:focus-within,
165
+ .form-input-wrapper:not(.money-with-icon):not(.error):not(.success) .form-input:focus-visible {
166
+ box-shadow: 0px 0px 0px 3px rgba(149, 155, 255, 0.3);
167
+ }
168
+
169
+ .form-input-wrapper:not(.money-with-icon):not(.error):not(.success) .form-input:focus-visible {
170
+ outline: none;
171
+ border-color: #472aff;
172
+ }
173
+
174
+ .form-input {
175
+ font-size: 14px;
176
+ line-height: 20px;
177
+ display: flex;
178
+ width: 100%;
179
+ padding: 8px 16px;
180
+ align-items: center;
181
+ border: none;
182
+ border-radius: 8px;
183
+ color: #000;
184
+ transition: all 0.2s ease-in-out;
185
+ text-overflow: ellipsis;
186
+ white-space: nowrap;
187
+ overflow: hidden;
188
+ }
189
+
190
+ .form-input-with-icon {
191
+ padding-right: 52px;
192
+ }
193
+
194
+ .form-input:focus {
195
+ outline: none;
196
+ }
197
+
198
+ .form-input-disabled {
199
+ background-color: #f3f4f6;
200
+ border-color: #d1d5db;
201
+ color: #6b7180;
202
+ cursor: not-allowed;
203
+ }
204
+
205
+ .form-input-readonly {
206
+ background-color: #f9fafb;
207
+ border-color: #d1d5db;
208
+ cursor: default;
209
+ }
210
+
211
+ .form-input-date {
212
+ cursor: pointer;
213
+ position: relative;
214
+ }
215
+
216
+ .form-input-date::-webkit-calendar-picker-indicator {
217
+ opacity: 1;
218
+ cursor: pointer;
219
+ width: 20px;
220
+ height: 20px;
221
+ position: absolute;
222
+ right: 10px;
223
+ top: 50%;
224
+ transform: translateY(-50%);
225
+ }
226
+
227
+ .form-input-date::-moz-calendar-picker-indicator {
228
+ opacity: 1;
229
+ cursor: pointer;
230
+ width: 20px;
231
+ height: 20px;
232
+ position: absolute;
233
+ right: 12px;
234
+ top: 50%;
235
+ transform: translateY(-50%);
236
+ }
237
+
238
+ @-moz-document url-prefix() {
239
+ .form-input-date.form-input-with-icon {
240
+ padding-right: 10px;
241
+ }
242
+ }
243
+
244
+ .form-input-date.form-input-with-icon::-webkit-calendar-picker-indicator,
245
+ .form-input-date.form-input-with-icon::-moz-calendar-picker-indicator {
246
+ right: 40px;
247
+ }
248
+
249
+ .form-input-date.form-input-with-icon::before {
250
+ content: '';
251
+ position: absolute;
252
+ right: 43px;
253
+ top: 0;
254
+ bottom: 0;
255
+ width: 1px;
256
+ background-color: #6b7180;
257
+ z-index: 1;
258
+ }
259
+
260
+ .form-input::placeholder,
261
+ .form-input:disabled::placeholder {
262
+ color: #6b7180;
263
+ opacity: 1;
264
+ }
265
+
266
+ .form-message-error {
267
+ color: #dc2626;
268
+ }
269
+
270
+ .form-message-description {
271
+ color: #6b7180;
272
+ }
273
+
274
+ .form-input-icon-container {
275
+ position: absolute;
276
+ right: 12px;
277
+ top: 50%;
278
+ transform: translateY(-50%);
279
+ display: flex;
280
+ align-items: center;
281
+ justify-content: center;
282
+ gap: 24px;
283
+ pointer-events: none;
284
+ }
285
+
286
+ .form-input-icon-container-password {
287
+ gap: 8px;
288
+ }
289
+
290
+ .form-input-wrapper:has(.form-input-icon-container-password) .form-input {
291
+ padding-right: 72px;
292
+ }
293
+
294
+ .form-input-icon-container :global(.form-input-icon) {
295
+ position: static;
296
+ transform: none;
297
+ }
298
+
299
+ .form-input-wrapper:not(.money-with-icon):not(.error):not(.success) .form-input:focus-visible {
300
+ outline: none;
301
+ border-color: #472aff;
302
+ box-shadow: 0px 0px 0px 3px rgba(149, 155, 255, 0.3);
303
+ }
304
+
305
+ .form-input-currency {
306
+ display: flex;
307
+ align-items: center;
308
+ padding: 0 10px 0 10px;
309
+ color: #000;
310
+ font-size: 12px;
311
+ font-weight: 400;
312
+ height: 100%;
313
+ flex-shrink: 0;
314
+ position: relative;
315
+ }
316
+
317
+ .form-input-currency::before {
318
+ content: '';
319
+ position: absolute;
320
+ left: 0;
321
+ top: -8px;
322
+ bottom: -8px;
323
+ width: 1px;
324
+ background-color: #6b7180;
325
+ z-index: 1;
326
+ }
327
+
328
+ .form-input-wrapper:focus-within {
329
+ border-color: #472aff;
330
+ box-shadow: 0px 0px 0px 3px rgba(149, 155, 255, 0.3);
331
+ }
332
+
333
+ .form-input-wrapper.error,
334
+ .form-input-wrapper.error:hover:not(:has(.form-input:disabled)):not(:has(.form-input:read-only)),
335
+ .form-input-wrapper.error:focus-within {
336
+ border-color: #dc2626;
337
+ }
338
+
339
+ .form-input-wrapper.error:focus-within {
340
+ box-shadow: 0px 0px 0px 3px rgba(220, 38, 38, 0.2);
341
+ }
342
+
343
+ .form-input-wrapper.success {
344
+ border-color: #008556;
345
+ }
346
+
347
+ .form-input-wrapper.success:hover:not(:has(.form-input:disabled)):not(
348
+ :has(.form-input:read-only)
349
+ ),
350
+ .form-input-wrapper.success:focus-within {
351
+ border-color: #10b981;
352
+ }
353
+
354
+ .form-input-wrapper.success:focus-within {
355
+ box-shadow: 0px 0px 0px 3px rgba(16, 185, 129, 0.15);
356
+ }
357
+
358
+ .form-input-wrapper:has(.form-input-currency) .form-input-icon-container {
359
+ right: 50px;
360
+ }
361
+
362
+ .form-input-wrapper.money-with-icon .form-input-icon-container {
363
+ right: 55px;
364
+ }
365
+
366
+ input::-webkit-outer-spin-button,
367
+ input::-webkit-inner-spin-button {
368
+ -webkit-appearance: none;
369
+ margin: 0;
370
+ }
371
+
372
+ input[type='number'] {
373
+ appearance: textfield;
374
+ -moz-appearance: textfield;
375
+ }
376
+
377
+ @media (prefers-contrast: high) {
378
+ .form-input {
379
+ border-width: 2px;
380
+ }
381
+
382
+ .form-input:focus {
383
+ outline: 2px solid;
384
+ outline-offset: 2px;
385
+ }
386
+ }
387
+
388
+ @media (prefers-reduced-motion: reduce) {
389
+ .form-input {
390
+ transition: none;
391
+ }
392
+ }
393
+ </style>
@@ -0,0 +1,14 @@
1
+ import type { HTMLInputAttributes } from 'svelte/elements';
2
+ type InputType = 'text' | 'password' | 'number' | 'date' | 'money';
3
+ interface InputProps extends Omit<HTMLInputAttributes, 'type' | 'value'> {
4
+ label?: string;
5
+ type?: InputType;
6
+ value?: string | number | null;
7
+ optional?: boolean;
8
+ error?: string | string[];
9
+ description?: string;
10
+ currency?: string;
11
+ }
12
+ declare const Input: import("svelte").Component<InputProps, {}, "value">;
13
+ type Input = ReturnType<typeof Input>;
14
+ export default Input;
@@ -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;