@softwareone/spi-sv5-library 1.12.5 → 1.13.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.
@@ -0,0 +1,176 @@
1
+ <script lang="ts">
2
+ import Label from '../Label/Label.svelte';
3
+ import type { LabelProps } from '../Label/labelState.svelte.js';
4
+ import type { OptionValueType, RadioOption } from './radioGroupState.svelte.js';
5
+
6
+ interface RadioGroupProps extends LabelProps {
7
+ options: string[] | RadioOption[];
8
+ name: string;
9
+ value?: OptionValueType;
10
+ disabled?: boolean;
11
+ row?: boolean;
12
+ description?: string;
13
+ onchange?: (value: OptionValueType) => void;
14
+ }
15
+
16
+ let {
17
+ label,
18
+ name,
19
+ required,
20
+ optional,
21
+ infoTooltip,
22
+ options,
23
+ value = $bindable(),
24
+ disabled = false,
25
+ row = false,
26
+ description,
27
+ onchange
28
+ }: RadioGroupProps = $props();
29
+
30
+ const isStringArray = (items: string[] | RadioOption[]): items is string[] =>
31
+ typeof items[0] === 'string';
32
+
33
+ const normalizedOptions = $derived<RadioOption[]>(
34
+ isStringArray(options)
35
+ ? options.map((option) => ({ label: option, value: option }))
36
+ : options
37
+ );
38
+ </script>
39
+
40
+ <div class="form-container">
41
+ <Label {label} {required} {optional} {infoTooltip} />
42
+ {#if description}
43
+ <p class="message-description">{description}</p>
44
+ {/if}
45
+ <div class={['radio-group', row && 'row']} role="radiogroup">
46
+ {#each normalizedOptions as option, index (option.value)}
47
+ <label class={['radio-option', disabled && 'disabled']}>
48
+ <input
49
+ id="{name}-{index}"
50
+ type="radio"
51
+ bind:group={value}
52
+ value={option.value}
53
+ {name}
54
+ {disabled}
55
+ onchange={() => onchange?.(option.value)}
56
+ class="radio-input"
57
+ />
58
+ <span
59
+ class={[
60
+ 'radio-indicator',
61
+ value === option.value && 'checked',
62
+ disabled && 'disabled'
63
+ ]}
64
+ ></span>
65
+ <span class="radio-label">{option.label}</span>
66
+ </label>
67
+ {/each}
68
+ </div>
69
+ </div>
70
+
71
+ <style>
72
+ .form-container {
73
+ --primary-color: #472aff;
74
+ --primary-focus: rgba(149, 155, 255, 0.3);
75
+ --gray-4: #6b7180;
76
+ --gray-2: #e0e5e8;
77
+ --white: #fff;
78
+
79
+ display: flex;
80
+ flex-direction: column;
81
+ gap: 8px;
82
+ font-size: 14px;
83
+ line-height: 20px;
84
+ }
85
+
86
+ .message-description {
87
+ font-size: 12px;
88
+ color: var(--gray-4);
89
+ }
90
+
91
+ .radio-group {
92
+ display: flex;
93
+ flex-direction: column;
94
+ gap: 8px;
95
+ }
96
+
97
+ .radio-group.row {
98
+ flex-direction: row;
99
+ flex-wrap: wrap;
100
+ gap: 8px 24px;
101
+ }
102
+
103
+ .radio-option {
104
+ display: flex;
105
+ align-items: center;
106
+ gap: 8px;
107
+ cursor: pointer;
108
+ user-select: none;
109
+ }
110
+
111
+ .radio-option.disabled {
112
+ cursor: not-allowed;
113
+ color: var(--gray-4);
114
+ }
115
+
116
+ .radio-input {
117
+ position: absolute;
118
+ opacity: 0;
119
+ width: 0;
120
+ height: 0;
121
+ }
122
+
123
+ .radio-indicator {
124
+ display: flex;
125
+ align-items: center;
126
+ justify-content: center;
127
+ width: 18px;
128
+ height: 18px;
129
+ min-width: 18px;
130
+ border-radius: 50%;
131
+ border: 2px solid var(--gray-4);
132
+ background: var(--white);
133
+ transition: all 0.2s ease-in-out;
134
+ }
135
+
136
+ .radio-indicator::after {
137
+ content: '';
138
+ width: 8px;
139
+ height: 8px;
140
+ border-radius: 50%;
141
+ background: transparent;
142
+ transition: background 0.2s ease-in-out;
143
+ }
144
+
145
+ .radio-option:not(.disabled):hover .radio-indicator {
146
+ border-color: var(--primary-color);
147
+ }
148
+
149
+ .radio-input:focus-visible + .radio-indicator {
150
+ box-shadow: 0px 0px 0px 3px var(--primary-focus);
151
+ border-color: var(--primary-color);
152
+ }
153
+
154
+ .radio-indicator.checked {
155
+ border-color: var(--primary-color);
156
+ }
157
+
158
+ .radio-indicator.checked::after {
159
+ background: var(--primary-color);
160
+ }
161
+
162
+ .radio-indicator.disabled {
163
+ border-color: var(--gray-4);
164
+ background: var(--gray-2);
165
+ cursor: not-allowed;
166
+ }
167
+
168
+ .radio-indicator.disabled.checked::after {
169
+ background: var(--gray-4);
170
+ }
171
+
172
+ .radio-label {
173
+ font-size: 14px;
174
+ line-height: 20px;
175
+ }
176
+ </style>
@@ -0,0 +1,14 @@
1
+ import type { LabelProps } from '../Label/labelState.svelte.js';
2
+ import type { OptionValueType, RadioOption } from './radioGroupState.svelte.js';
3
+ interface RadioGroupProps extends LabelProps {
4
+ options: string[] | RadioOption[];
5
+ name: string;
6
+ value?: OptionValueType;
7
+ disabled?: boolean;
8
+ row?: boolean;
9
+ description?: string;
10
+ onchange?: (value: OptionValueType) => void;
11
+ }
12
+ declare const RadioGroup: import("svelte").Component<RadioGroupProps, {}, "value">;
13
+ type RadioGroup = ReturnType<typeof RadioGroup>;
14
+ export default RadioGroup;
@@ -0,0 +1,5 @@
1
+ export interface RadioOption {
2
+ value: OptionValueType;
3
+ label: string;
4
+ }
5
+ export type OptionValueType = string | boolean | number;
@@ -0,0 +1 @@
1
+ export {};
@@ -19,6 +19,7 @@
19
19
  disableValidationColor?: boolean;
20
20
  value?: string | string[] | null;
21
21
  error?: string | string[];
22
+ description?: string;
22
23
  positionStrategy?: 'absolute' | 'fixed';
23
24
  customSelection?: Snippet<[option: SelectOption]>;
24
25
  customOption?: Snippet<[option: SelectOption]>;
@@ -42,6 +43,7 @@
42
43
  disableValidationColor = false,
43
44
  value = $bindable(),
44
45
  error,
46
+ description,
45
47
  positionStrategy = 'absolute',
46
48
  customSelection,
47
49
  customOption,
@@ -304,8 +306,13 @@
304
306
  </section>
305
307
  {/if}
306
308
  </div>
309
+ {#if description}
310
+ <p class="message-description">
311
+ {description}
312
+ </p>
313
+ {/if}
307
314
  {#if isInvalid}
308
- <p class="form-message-error">
315
+ <p class="message-error">
309
316
  {Array.isArray(error) ? error[0] : error}
310
317
  </p>
311
318
  {/if}
@@ -380,7 +387,12 @@
380
387
  cursor: default;
381
388
  }
382
389
 
383
- > .form-message-error {
390
+ > .message-description {
391
+ font-size: 12px;
392
+ color: var(--gray-4);
393
+ }
394
+
395
+ > .message-error {
384
396
  font-size: 12px;
385
397
  color: var(--error);
386
398
  }
@@ -13,6 +13,7 @@ interface SelectProps extends LabelProps {
13
13
  disableValidationColor?: boolean;
14
14
  value?: string | string[] | null;
15
15
  error?: string | string[];
16
+ description?: string;
16
17
  positionStrategy?: 'absolute' | 'fixed';
17
18
  customSelection?: Snippet<[option: SelectOption]>;
18
19
  customOption?: Snippet<[option: SelectOption]>;
package/dist/index.d.ts CHANGED
@@ -30,18 +30,19 @@ import Switcher from './Switcher/Switcher.svelte';
30
30
  import Tabs from './Tabs/Tabs.svelte';
31
31
  import TextArea from './Controls/TextArea/TextArea.svelte';
32
32
  import Toaster from './Toast/Toast.svelte';
33
+ import RadioGroup from './Controls/RadioGroup/RadioGroup.svelte';
33
34
  import Toggle from './Controls/Toggle/Toggle.svelte';
34
35
  import Tooltip from './Tooltip/Tooltip.svelte';
35
36
  import Waffle from './Waffle/Waffle.svelte';
36
37
  import AttachFile from './Controls/AttachFile/AttachFile.svelte';
37
- import { createTabComponent } from './Tabs/tabsState.svelte.js';
38
38
  import { addBreadcrumbsNameMap } from './Breadcrumbs/breadcrumbsState.svelte.js';
39
39
  import { ChipType } from './Chips/chipsState.svelte.js';
40
40
  import { ColumnType, ImageType } from './HighlightPanel/highlightPanelState.svelte.js';
41
41
  import { setProgressWizardStepsContext, getProgressWizardContext } from './ProgressWizard/context.js';
42
42
  import { setStepValidity } from './ProgressWizard/progressWizardState.svelte.js';
43
- import { addToast } from './Toast/toastState.svelte';
44
- import { getSubMenuItemsFromMenu } from './Menu/MenuState.svelte';
43
+ import { addToast } from './Toast/toastState.svelte.js';
44
+ import { getSubMenuItemsFromMenu } from './Menu/MenuState.svelte.js';
45
+ import { createTabComponent } from './Tabs/tabsState.svelte.js';
45
46
  import type { AnnouncementItem } from './Announcement/AnnouncementState.svelte.js';
46
47
  import type { BreadcrumbsNameMap } from './Breadcrumbs/breadcrumbsState.svelte.js';
47
48
  import type { HighlightPanelColumn } from './HighlightPanel/highlightPanelState.svelte.js';
@@ -49,10 +50,11 @@ import type { HomeItem } from './Menu/MenuState.svelte.js';
49
50
  import type { MainMenu, MenuItem, SubMenuItem } from './Menu/MenuState.svelte.js';
50
51
  import type { ModalProps } from './Modal/modalState.svelte.js';
51
52
  import type { ProgressWizardStep } from './ProgressWizard/progressWizardState.svelte.js';
53
+ import type { RadioOption } from './Controls/RadioGroup/radioGroupState.svelte.js';
52
54
  import type { SwitcherOption } from './Switcher/switcherState.svelte.js';
53
55
  import type { SelectOption } from './Controls/Select/selectState.svelte.js';
54
56
  import type { Tab } from './Tabs/tabsState.svelte.js';
55
- import type { Toast } from './Toast/toastState.svelte';
57
+ import type { Toast } from './Toast/toastState.svelte.js';
56
58
  import type { WaffleItem } from './Waffle/waffleState.svelte.js';
57
59
  import type { NotificationProps } from './Notification/notificationState.svelte.js';
58
- export { Accordion, AttachFile, Avatar, Breadcrumbs, Button, Card, Chips, DeleteConfirmationModal, ErrorPage, Footer, Header, HeaderAccount, HeaderLoader, HeaderLogo, HighlightPanel, Home, Input, Label, Link, Menu, Modal, Notification, Processing, ProgressPage, ProgressWizard, Search, Select, Sidebar, Spinner, Switcher, Tabs, TextArea, Toaster, Toggle, Tooltip, Waffle, addBreadcrumbsNameMap, addToast, getProgressWizardContext, setProgressWizardStepsContext, setStepValidity, getSubMenuItemsFromMenu, createTabComponent, ChipType, ColumnType, ImageType, type AnnouncementItem, type BreadcrumbsNameMap, type HighlightPanelColumn, type HomeItem, type MainMenu, type MenuItem, type ModalProps, type ProgressWizardStep, type SelectOption, type SwitcherOption, type Tab, type Toast, type WaffleItem, type SubMenuItem, type NotificationProps };
60
+ export { Accordion, AttachFile, Avatar, Breadcrumbs, Button, Card, Chips, DeleteConfirmationModal, ErrorPage, Footer, Header, HeaderAccount, HeaderLoader, HeaderLogo, HighlightPanel, Home, Input, Label, Link, Menu, Modal, Notification, Processing, ProgressPage, ProgressWizard, RadioGroup, Search, Select, Sidebar, Spinner, Switcher, Tabs, TextArea, Toaster, Toggle, Tooltip, Waffle, addBreadcrumbsNameMap, addToast, getProgressWizardContext, setProgressWizardStepsContext, setStepValidity, getSubMenuItemsFromMenu, createTabComponent, ChipType, ColumnType, ImageType, type AnnouncementItem, type BreadcrumbsNameMap, type HighlightPanelColumn, type HomeItem, type MainMenu, type MenuItem, type ModalProps, type ProgressWizardStep, type RadioOption, type SelectOption, type SubMenuItem, type SwitcherOption, type Tab, type Toast, type WaffleItem, type NotificationProps };
package/dist/index.js CHANGED
@@ -31,22 +31,23 @@ import Switcher from './Switcher/Switcher.svelte';
31
31
  import Tabs from './Tabs/Tabs.svelte';
32
32
  import TextArea from './Controls/TextArea/TextArea.svelte';
33
33
  import Toaster from './Toast/Toast.svelte';
34
+ import RadioGroup from './Controls/RadioGroup/RadioGroup.svelte';
34
35
  import Toggle from './Controls/Toggle/Toggle.svelte';
35
36
  import Tooltip from './Tooltip/Tooltip.svelte';
36
37
  import Waffle from './Waffle/Waffle.svelte';
37
38
  import AttachFile from './Controls/AttachFile/AttachFile.svelte';
38
- import { createTabComponent } from './Tabs/tabsState.svelte.js';
39
39
  // State, enums, and helpers
40
40
  import { addBreadcrumbsNameMap } from './Breadcrumbs/breadcrumbsState.svelte.js';
41
41
  import { ChipType } from './Chips/chipsState.svelte.js';
42
42
  import { ColumnType, ImageType } from './HighlightPanel/highlightPanelState.svelte.js';
43
43
  import { setProgressWizardStepsContext, getProgressWizardContext } from './ProgressWizard/context.js';
44
44
  import { setStepValidity } from './ProgressWizard/progressWizardState.svelte.js';
45
- import { addToast } from './Toast/toastState.svelte';
46
- import { getSubMenuItemsFromMenu } from './Menu/MenuState.svelte';
45
+ import { addToast } from './Toast/toastState.svelte.js';
46
+ import { getSubMenuItemsFromMenu } from './Menu/MenuState.svelte.js';
47
+ import { createTabComponent } from './Tabs/tabsState.svelte.js';
47
48
  export {
48
49
  // Components
49
- Accordion, AttachFile, Avatar, Breadcrumbs, Button, Card, Chips, DeleteConfirmationModal, ErrorPage, Footer, Header, HeaderAccount, HeaderLoader, HeaderLogo, HighlightPanel, Home, Input, Label, Link, Menu, Modal, Notification, Processing, ProgressPage, ProgressWizard, Search, Select, Sidebar, Spinner, Switcher, Tabs, TextArea, Toaster, Toggle, Tooltip, Waffle,
50
+ Accordion, AttachFile, Avatar, Breadcrumbs, Button, Card, Chips, DeleteConfirmationModal, ErrorPage, Footer, Header, HeaderAccount, HeaderLoader, HeaderLogo, HighlightPanel, Home, Input, Label, Link, Menu, Modal, Notification, Processing, ProgressPage, ProgressWizard, RadioGroup, Search, Select, Sidebar, Spinner, Switcher, Tabs, TextArea, Toaster, Toggle, Tooltip, Waffle,
50
51
  // Functions and helpers
51
52
  addBreadcrumbsNameMap, addToast, getProgressWizardContext, setProgressWizardStepsContext, setStepValidity, getSubMenuItemsFromMenu, createTabComponent,
52
53
  // Enums
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@softwareone/spi-sv5-library",
3
- "version": "1.12.5",
3
+ "version": "1.13.0",
4
4
  "description": "Svelte components",
5
5
  "keywords": [
6
6
  "svelte",