@synergy-design-system/mcp 2.6.1 → 2.8.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/CHANGELOG.md +33 -0
- package/dist/utilities/storybook/scraper.js +14 -3
- package/metadata/checksum.txt +1 -1
- package/metadata/packages/components/components/syn-alert/component.styles.ts +126 -26
- package/metadata/packages/components/components/syn-alert/component.ts +1 -2
- package/metadata/packages/components/components/syn-checkbox/component.angular.ts +13 -0
- package/metadata/packages/components/components/syn-checkbox/component.styles.ts +99 -39
- package/metadata/packages/components/components/syn-checkbox/component.ts +13 -10
- package/metadata/packages/components/components/syn-checkbox/component.vue +5 -0
- package/metadata/packages/components/components/syn-combobox/component.angular.ts +13 -0
- package/metadata/packages/components/components/syn-combobox/component.styles.ts +216 -193
- package/metadata/packages/components/components/syn-combobox/component.ts +68 -39
- package/metadata/packages/components/components/syn-combobox/component.vue +5 -0
- package/metadata/packages/components/components/syn-file/component.angular.ts +13 -0
- package/metadata/packages/components/components/syn-file/component.styles.ts +20 -3
- package/metadata/packages/components/components/syn-file/component.ts +19 -5
- package/metadata/packages/components/components/syn-file/component.vue +5 -0
- package/metadata/packages/components/components/syn-input/component.ts +1 -2
- package/metadata/packages/components/components/syn-popup/component.styles.ts +24 -17
- package/metadata/packages/components/components/syn-popup/component.ts +1 -2
- package/metadata/packages/components/components/syn-radio/component.angular.ts +13 -0
- package/metadata/packages/components/components/syn-radio/component.styles.ts +91 -29
- package/metadata/packages/components/components/syn-radio/component.ts +19 -10
- package/metadata/packages/components/components/syn-radio/component.vue +5 -0
- package/metadata/packages/components/components/syn-radio-group/component.styles.ts +30 -9
- package/metadata/packages/components/components/syn-radio-group/component.ts +61 -32
- package/metadata/packages/components/components/syn-range/component.angular.ts +13 -0
- package/metadata/packages/components/components/syn-range/component.styles.ts +27 -3
- package/metadata/packages/components/components/syn-range/component.ts +17 -5
- package/metadata/packages/components/components/syn-range/component.vue +5 -0
- package/metadata/packages/components/components/syn-select/component.angular.ts +13 -0
- package/metadata/packages/components/components/syn-select/component.styles.ts +222 -151
- package/metadata/packages/components/components/syn-select/component.ts +30 -15
- package/metadata/packages/components/components/syn-select/component.vue +5 -0
- package/metadata/packages/components/components/syn-switch/component.angular.ts +13 -0
- package/metadata/packages/components/components/syn-switch/component.styles.ts +145 -63
- package/metadata/packages/components/components/syn-switch/component.ts +16 -4
- package/metadata/packages/components/components/syn-switch/component.vue +5 -0
- package/metadata/packages/components/components/syn-textarea/component.styles.ts +55 -27
- package/metadata/packages/components/components/syn-textarea/component.ts +1 -3
- package/metadata/packages/components/components/syn-tooltip/component.styles.ts +15 -10
- package/metadata/packages/components/components/syn-tooltip/component.ts +13 -5
- package/metadata/packages/components/components/syn-validate/component.angular.ts +9 -0
- package/metadata/packages/components/components/syn-validate/component.react.ts +8 -0
- package/metadata/packages/components/components/syn-validate/component.ts +106 -8
- package/metadata/packages/components/components/syn-validate/component.vue +9 -0
- package/metadata/packages/components/static/CHANGELOG.md +43 -0
- package/metadata/packages/tokens/CHANGELOG.md +33 -0
- package/metadata/packages/tokens/dark.css +7 -1
- package/metadata/packages/tokens/index.js +31 -1
- package/metadata/packages/tokens/light.css +7 -1
- package/metadata/packages/tokens/sick2018_dark.css +7 -1
- package/metadata/packages/tokens/sick2018_light.css +7 -1
- package/metadata/packages/tokens/sick2025_dark.css +7 -1
- package/metadata/packages/tokens/sick2025_light.css +7 -1
- package/metadata/static/components/syn-checkbox/docs.md +36 -0
- package/metadata/static/components/syn-combobox/docs.md +138 -0
- package/metadata/static/components/syn-file/docs.md +24 -0
- package/metadata/static/components/syn-input/docs.md +1 -1
- package/metadata/static/components/syn-radio/docs.md +21 -0
- package/metadata/static/components/syn-radio-group/docs.md +46 -0
- package/metadata/static/components/syn-range/docs.md +19 -0
- package/metadata/static/components/syn-select/docs.md +81 -0
- package/metadata/static/components/syn-switch/docs.md +22 -0
- package/metadata/static/components/syn-textarea/docs.md +1 -1
- package/metadata/static/components/syn-tooltip/docs.md +73 -0
- package/metadata/static/components/syn-validate/docs.md +33 -6
- package/package.json +4 -4
- package/metadata/packages/components/components/syn-alert/component.custom.styles.ts +0 -136
- package/metadata/packages/components/components/syn-checkbox/component.custom.styles.ts +0 -86
- package/metadata/packages/components/components/syn-combobox/component.custom.styles.ts +0 -122
- package/metadata/packages/components/components/syn-popup/component.custom.styles.ts +0 -18
- package/metadata/packages/components/components/syn-radio/component.custom.styles.ts +0 -86
- package/metadata/packages/components/components/syn-radio-group/component.custom.styles.ts +0 -25
- package/metadata/packages/components/components/syn-select/component.custom.styles.ts +0 -175
- package/metadata/packages/components/components/syn-switch/component.custom.styles.ts +0 -141
- package/metadata/packages/components/components/syn-textarea/component.custom.styles.ts +0 -48
- package/metadata/packages/components/components/syn-tooltip/component.custom.styles.ts +0 -13
|
@@ -1,104 +1,125 @@
|
|
|
1
|
-
/* eslint-disable */
|
|
2
1
|
import { css } from 'lit';
|
|
3
2
|
|
|
4
3
|
export default css`
|
|
5
|
-
|
|
4
|
+
/* stylelint-disable no-descending-specificity */
|
|
6
5
|
:host {
|
|
7
6
|
display: block;
|
|
8
7
|
}
|
|
9
8
|
|
|
10
9
|
:host(:focus-visible) {
|
|
11
|
-
outline:
|
|
10
|
+
outline: 0;
|
|
12
11
|
}
|
|
13
12
|
|
|
14
13
|
.radio {
|
|
14
|
+
align-items: flex-start;
|
|
15
|
+
color: var(--syn-input-label-color);
|
|
16
|
+
cursor: pointer;
|
|
15
17
|
display: inline-flex;
|
|
16
|
-
align-items: top;
|
|
17
18
|
font-family: var(--syn-input-font-family);
|
|
18
19
|
font-size: var(--syn-input-font-size-medium);
|
|
19
20
|
font-weight: var(--syn-input-font-weight);
|
|
20
|
-
color: var(--syn-input-label-color);
|
|
21
21
|
vertical-align: middle;
|
|
22
|
-
cursor: pointer;
|
|
23
22
|
}
|
|
24
23
|
|
|
25
24
|
.radio--small {
|
|
26
25
|
--toggle-size: var(--syn-toggle-size-small);
|
|
26
|
+
|
|
27
27
|
font-size: var(--syn-input-font-size-small);
|
|
28
28
|
}
|
|
29
29
|
|
|
30
30
|
.radio--medium {
|
|
31
31
|
--toggle-size: var(--syn-toggle-size-medium);
|
|
32
|
+
|
|
32
33
|
font-size: var(--syn-input-font-size-medium);
|
|
33
34
|
}
|
|
34
35
|
|
|
35
36
|
.radio--large {
|
|
36
37
|
--toggle-size: var(--syn-toggle-size-large);
|
|
38
|
+
|
|
37
39
|
font-size: var(--syn-input-font-size-large);
|
|
38
40
|
}
|
|
39
41
|
|
|
40
42
|
.radio__checked-icon {
|
|
41
43
|
display: inline-flex;
|
|
42
|
-
width: var(--toggle-size);
|
|
43
44
|
height: var(--toggle-size);
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* #920: The new icons are instances in figma.
|
|
48
|
+
* The width of the system icon is 12px x 12px, so there is no inner padding.
|
|
49
|
+
* To accommodate for this, we need to set the width and height of the icon to 50% to get the same result as before.
|
|
50
|
+
*/
|
|
51
|
+
scale: 0.5;
|
|
52
|
+
width: var(--toggle-size);
|
|
53
|
+
|
|
44
54
|
}
|
|
45
55
|
|
|
46
56
|
.radio__control {
|
|
47
|
-
flex: 0 0 auto;
|
|
48
|
-
position: relative;
|
|
49
|
-
display: inline-flex;
|
|
50
57
|
align-items: center;
|
|
51
|
-
|
|
52
|
-
width: var(--toggle-size);
|
|
53
|
-
height: var(--toggle-size);
|
|
58
|
+
background-color: var(--syn-input-background-color);
|
|
54
59
|
border: solid var(--syn-input-border-width) var(--syn-input-border-color);
|
|
55
60
|
border-radius: 50%;
|
|
56
|
-
background-color: var(--syn-input-background-color);
|
|
57
61
|
color: transparent;
|
|
62
|
+
display: inline-flex;
|
|
63
|
+
flex: 0 0 auto;
|
|
64
|
+
height: var(--toggle-size);
|
|
65
|
+
justify-content: center;
|
|
66
|
+
position: relative;
|
|
58
67
|
transition:
|
|
59
68
|
var(--syn-transition-fast) border-color,
|
|
60
69
|
var(--syn-transition-fast) background-color,
|
|
61
70
|
var(--syn-transition-fast) color,
|
|
62
71
|
var(--syn-transition-fast) box-shadow;
|
|
72
|
+
width: var(--toggle-size);
|
|
63
73
|
}
|
|
64
74
|
|
|
65
75
|
.radio__input {
|
|
66
|
-
|
|
76
|
+
margin: 0;
|
|
67
77
|
opacity: 0;
|
|
68
78
|
padding: 0;
|
|
69
|
-
margin: 0;
|
|
70
79
|
pointer-events: none;
|
|
80
|
+
position: absolute;
|
|
71
81
|
}
|
|
72
82
|
|
|
73
83
|
/* Hover */
|
|
74
|
-
.radio:not(.radio--checked):not(.radio--disabled)
|
|
84
|
+
.radio:not(.radio--checked):not(.radio--disabled):not(.radio--readonly):hover .radio__control {
|
|
75
85
|
border-color: var(--syn-input-border-color-hover);
|
|
76
|
-
background-color: var(--syn-input-background-color-hover);
|
|
77
86
|
}
|
|
78
87
|
|
|
79
88
|
/* Checked */
|
|
80
89
|
.radio--checked .radio__control {
|
|
90
|
+
background-color: var(--syn-interactive-emphasis-color);
|
|
91
|
+
border-color: var(--syn-interactive-emphasis-color);
|
|
81
92
|
color: var(--syn-color-neutral-0);
|
|
82
|
-
border-color: var(--syn-color-primary-600);
|
|
83
|
-
background-color: var(--syn-color-primary-600);
|
|
84
93
|
}
|
|
85
94
|
|
|
86
95
|
/* Checked + hover */
|
|
87
|
-
.radio.radio--checked:not(.radio--disabled)
|
|
88
|
-
|
|
89
|
-
|
|
96
|
+
.radio.radio--checked:not(.radio--disabled):not(.radio--readonly):hover .radio__control {
|
|
97
|
+
background-color: var(--syn-interactive-emphasis-color-hover);
|
|
98
|
+
border-color: var(--syn-interactive-emphasis-color-hover);
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
/* Checked + active */
|
|
102
|
+
.radio.radio--checked:not(.radio--disabled):not(.radio--readonly):active .radio__control {
|
|
103
|
+
background-color: var(--syn-interactive-emphasis-color-active);
|
|
104
|
+
border-color: var(--syn-interactive-emphasis-color-active);
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
/* Not-Checked + active */
|
|
108
|
+
.radio:not(.radio--checked):not(.radio--disabled):not(.radio--readonly):active .radio__control {
|
|
109
|
+
border-color: var(--syn-input-border-color-active);
|
|
90
110
|
}
|
|
91
111
|
|
|
92
112
|
/* Checked + focus */
|
|
93
113
|
:host(:focus-visible) .radio__control {
|
|
94
114
|
outline: var(--syn-focus-ring);
|
|
95
|
-
outline-offset: var(--syn-focus-ring-
|
|
115
|
+
outline-offset: var(--syn-focus-ring-width);
|
|
96
116
|
}
|
|
97
117
|
|
|
98
|
-
/* Disabled */
|
|
99
118
|
.radio--disabled {
|
|
100
|
-
opacity: 0.5;
|
|
101
119
|
cursor: not-allowed;
|
|
120
|
+
|
|
121
|
+
/** #429: Use token for opacity */
|
|
122
|
+
opacity: var(--syn-input-disabled-opacity);
|
|
102
123
|
}
|
|
103
124
|
|
|
104
125
|
/* When the control isn't checked, hide the circle for Windows High Contrast mode a11y */
|
|
@@ -106,12 +127,53 @@ export default css`
|
|
|
106
127
|
opacity: 0;
|
|
107
128
|
}
|
|
108
129
|
|
|
130
|
+
/* Fix#456: Multi line radio fixes */
|
|
109
131
|
.radio__label {
|
|
110
|
-
|
|
132
|
+
align-self: center;
|
|
111
133
|
color: var(--syn-input-label-color);
|
|
134
|
+
display: inline-block;
|
|
112
135
|
line-height: var(--toggle-size);
|
|
113
|
-
margin-inline-start:
|
|
136
|
+
margin-inline-start: var(--syn-spacing-x-small);
|
|
137
|
+
margin-top: -1px;
|
|
114
138
|
user-select: none;
|
|
115
|
-
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
.radio--small .radio__label {
|
|
142
|
+
font: var(--syn-body-small-regular);
|
|
143
|
+
margin-inline-start: var(--syn-spacing-x-small);
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
.radio--medium .radio__label {
|
|
147
|
+
font: var(--syn-body-medium-regular);
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
.radio--large .radio__label {
|
|
151
|
+
font: var(--syn-body-large-regular);
|
|
152
|
+
margin-inline-start: var(--syn-spacing-x-small);
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
/* /Fix#456 */
|
|
156
|
+
|
|
157
|
+
/**
|
|
158
|
+
* #1174: Readonly state
|
|
159
|
+
*/
|
|
160
|
+
.radio.radio--readonly {
|
|
161
|
+
cursor: default;
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
.radio.radio--readonly .radio__label {
|
|
165
|
+
user-select: auto;
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
.radio.radio--readonly .radio__control {
|
|
169
|
+
background: var(--syn-input-readonly-background-color);
|
|
170
|
+
border-color: var(--syn-input-readonly-background-color);
|
|
171
|
+
color: var(--syn-readonly-indicator-color);
|
|
172
|
+
cursor: default;
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
:host(:focus) .radio--readonly .radio__control {
|
|
176
|
+
outline: var(--syn-focus-ring);
|
|
177
|
+
outline-offset: var(--syn-focus-ring-width);
|
|
116
178
|
}
|
|
117
179
|
`;
|
|
@@ -1,14 +1,12 @@
|
|
|
1
|
-
/* eslint-disable */
|
|
2
1
|
import { classMap } from 'lit/directives/class-map.js';
|
|
3
2
|
import { html } from 'lit';
|
|
3
|
+
import type { CSSResultGroup } from 'lit';
|
|
4
4
|
import { property, state } from 'lit/decorators.js';
|
|
5
5
|
import { watch } from '../../internal/watch.js';
|
|
6
6
|
import componentStyles from '../../styles/component.styles.js';
|
|
7
7
|
import SynergyElement from '../../internal/synergy-element.js';
|
|
8
8
|
import SynIcon from '../icon/icon.component.js';
|
|
9
9
|
import styles from './radio.styles.js';
|
|
10
|
-
import customStyles from './radio.custom.styles.js';
|
|
11
|
-
import type { CSSResultGroup } from 'lit';
|
|
12
10
|
import { enableDefaultSettings } from '../../utilities/defaultSettings/decorator.js';
|
|
13
11
|
|
|
14
12
|
/**
|
|
@@ -32,10 +30,12 @@ import { enableDefaultSettings } from '../../utilities/defaultSettings/decorator
|
|
|
32
30
|
*/
|
|
33
31
|
@enableDefaultSettings('SynRadio')
|
|
34
32
|
export default class SynRadio extends SynergyElement {
|
|
35
|
-
static styles: CSSResultGroup = [componentStyles, styles
|
|
33
|
+
static styles: CSSResultGroup = [componentStyles, styles];
|
|
34
|
+
|
|
36
35
|
static dependencies = { 'syn-icon': SynIcon };
|
|
37
36
|
|
|
38
37
|
@state() checked = false;
|
|
38
|
+
|
|
39
39
|
@state() protected hasFocus = false;
|
|
40
40
|
|
|
41
41
|
/** The radio's value. When selected, the radio group will receive this value. */
|
|
@@ -48,7 +48,10 @@ export default class SynRadio extends SynergyElement {
|
|
|
48
48
|
@property({ reflect: true }) size: 'small' | 'medium' | 'large' = 'medium';
|
|
49
49
|
|
|
50
50
|
/** Disables the radio. */
|
|
51
|
-
@property({
|
|
51
|
+
@property({ reflect: true, type: Boolean }) disabled = false;
|
|
52
|
+
|
|
53
|
+
/** Sets the radio to a readonly state. */
|
|
54
|
+
@property({ reflect: true, type: Boolean }) readonly = false;
|
|
52
55
|
|
|
53
56
|
constructor() {
|
|
54
57
|
super();
|
|
@@ -68,6 +71,11 @@ export default class SynRadio extends SynergyElement {
|
|
|
68
71
|
};
|
|
69
72
|
|
|
70
73
|
private handleClick = () => {
|
|
74
|
+
if (this.readonly) {
|
|
75
|
+
this.focus();
|
|
76
|
+
return;
|
|
77
|
+
}
|
|
78
|
+
|
|
71
79
|
if (!this.disabled) {
|
|
72
80
|
this.checked = true;
|
|
73
81
|
}
|
|
@@ -81,7 +89,7 @@ export default class SynRadio extends SynergyElement {
|
|
|
81
89
|
private setInitialAttributes() {
|
|
82
90
|
this.setAttribute('role', 'radio');
|
|
83
91
|
this.setAttribute('tabindex', '-1');
|
|
84
|
-
this.setAttribute('aria-disabled', this.disabled ? 'true' : 'false');
|
|
92
|
+
this.setAttribute('aria-disabled', (this.disabled || this.readonly) ? 'true' : 'false');
|
|
85
93
|
}
|
|
86
94
|
|
|
87
95
|
@watch('checked')
|
|
@@ -90,9 +98,9 @@ export default class SynRadio extends SynergyElement {
|
|
|
90
98
|
this.setAttribute('tabindex', this.checked ? '0' : '-1');
|
|
91
99
|
}
|
|
92
100
|
|
|
93
|
-
@watch('disabled', { waitUntilFirstUpdate: true })
|
|
101
|
+
@watch(['disabled', 'readonly'], { waitUntilFirstUpdate: true })
|
|
94
102
|
handleDisabledChange() {
|
|
95
|
-
this.setAttribute('aria-disabled', this.disabled ? 'true' : 'false');
|
|
103
|
+
this.setAttribute('aria-disabled', (this.disabled || this.readonly) ? 'true' : 'false');
|
|
96
104
|
}
|
|
97
105
|
|
|
98
106
|
render() {
|
|
@@ -104,9 +112,10 @@ export default class SynRadio extends SynergyElement {
|
|
|
104
112
|
'radio--checked': this.checked,
|
|
105
113
|
'radio--disabled': this.disabled,
|
|
106
114
|
'radio--focused': this.hasFocus,
|
|
107
|
-
'radio--
|
|
115
|
+
'radio--large': this.size === 'large',
|
|
108
116
|
'radio--medium': this.size === 'medium',
|
|
109
|
-
'radio--
|
|
117
|
+
'radio--readonly': this.readonly,
|
|
118
|
+
'radio--small': this.size === 'small',
|
|
110
119
|
})}
|
|
111
120
|
>
|
|
112
121
|
<span part="${`control${this.checked ? ' control--checked' : ''}`}" class="radio__control">
|
|
@@ -57,6 +57,11 @@ attribute can typically be omitted.
|
|
|
57
57
|
* Disables the radio.
|
|
58
58
|
*/
|
|
59
59
|
disabled?: SynRadio['disabled'];
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* Sets the radio to a readonly state.
|
|
63
|
+
*/
|
|
64
|
+
readonly?: SynRadio['readonly'];
|
|
60
65
|
}>();
|
|
61
66
|
|
|
62
67
|
// Make sure prop binding only forwards the props that are actually there.
|
|
@@ -1,17 +1,27 @@
|
|
|
1
|
-
/* eslint-disable */
|
|
2
1
|
import { css } from 'lit';
|
|
3
2
|
|
|
4
3
|
export default css`
|
|
5
|
-
/* stylelint-disable */
|
|
6
4
|
:host {
|
|
7
5
|
display: block;
|
|
8
6
|
}
|
|
9
7
|
|
|
8
|
+
:host([data-user-invalid]) {
|
|
9
|
+
--syn-input-border-color: var(--syn-input-border-color-focus-error);
|
|
10
|
+
--syn-input-border-color-hover: var(--syn-input-border-color-focus-error);
|
|
11
|
+
--syn-color-primary-600: var(--syn-input-border-color-focus-error);
|
|
12
|
+
--syn-color-primary-900: var(--syn-color-error-900);
|
|
13
|
+
--syn-color-primary-950: var(--syn-color-error-950);
|
|
14
|
+
--syn-color-neutral-1000: var(--syn-input-border-color-focus-error);
|
|
15
|
+
--syn-interactive-emphasis-color: var(--syn-input-border-color-focus-error);
|
|
16
|
+
--syn-interactive-emphasis-color-hover: var(--syn-input-border-color-focus-error);
|
|
17
|
+
--syn-interactive-emphasis-color-active: var(--syn-input-border-color-focus-error);
|
|
18
|
+
}
|
|
19
|
+
|
|
10
20
|
.form-control {
|
|
11
|
-
position: relative;
|
|
12
21
|
border: none;
|
|
13
|
-
padding: 0;
|
|
14
22
|
margin: 0;
|
|
23
|
+
padding: 0;
|
|
24
|
+
position: relative;
|
|
15
25
|
}
|
|
16
26
|
|
|
17
27
|
.form-control__label {
|
|
@@ -24,14 +34,25 @@ export default css`
|
|
|
24
34
|
}
|
|
25
35
|
|
|
26
36
|
.visually-hidden {
|
|
27
|
-
|
|
28
|
-
|
|
37
|
+
border: 0;
|
|
38
|
+
/* stylelint-disable-next-line property-no-deprecated */
|
|
39
|
+
clip: rect(0, 0, 0, 0);
|
|
29
40
|
height: 1px;
|
|
30
|
-
padding: 0;
|
|
31
41
|
margin: -1px;
|
|
32
42
|
overflow: hidden;
|
|
33
|
-
|
|
43
|
+
padding: 0;
|
|
44
|
+
position: absolute;
|
|
34
45
|
white-space: nowrap;
|
|
35
|
-
|
|
46
|
+
width: 1px;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
.form-control-input {
|
|
50
|
+
display: flex;
|
|
51
|
+
flex-direction: column;
|
|
52
|
+
gap: var(--syn-spacing-x-small);
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
.form-control--has-help-text.form-control--radio-group .form-control__help-text {
|
|
56
|
+
margin-top: var(--syn-spacing-x-small);
|
|
36
57
|
}
|
|
37
58
|
`;
|
|
@@ -1,23 +1,22 @@
|
|
|
1
|
-
/* eslint-disable */
|
|
1
|
+
/* eslint-disable @typescript-eslint/no-floating-promises */
|
|
2
|
+
/* eslint-disable no-param-reassign */
|
|
2
3
|
import { classMap } from 'lit/directives/class-map.js';
|
|
4
|
+
import { html } from 'lit';
|
|
5
|
+
import { property, query, state } from 'lit/decorators.js';
|
|
6
|
+
import type { CSSResultGroup } from 'lit';
|
|
3
7
|
import {
|
|
4
|
-
customErrorValidityState,
|
|
5
8
|
FormControlController,
|
|
9
|
+
customErrorValidityState,
|
|
6
10
|
validValidityState,
|
|
7
|
-
valueMissingValidityState
|
|
11
|
+
valueMissingValidityState,
|
|
8
12
|
} from '../../internal/form.js';
|
|
9
13
|
import { HasSlotController } from '../../internal/slot.js';
|
|
10
|
-
import { html } from 'lit';
|
|
11
|
-
import { property, query, state } from 'lit/decorators.js';
|
|
12
14
|
import { watch } from '../../internal/watch.js';
|
|
13
15
|
import componentStyles from '../../styles/component.styles.js';
|
|
14
16
|
import formControlStyles from '../../styles/form-control.styles.js';
|
|
15
|
-
import formControlCustomStyles from '../../styles/form-control.custom.styles.js';
|
|
16
17
|
import SynergyElement from '../../internal/synergy-element.js';
|
|
17
18
|
import SynButtonGroup from '../button-group/button-group.component.js';
|
|
18
19
|
import styles from './radio-group.styles.js';
|
|
19
|
-
import customStyles from './radio-group.custom.styles.js';
|
|
20
|
-
import type { CSSResultGroup } from 'lit';
|
|
21
20
|
import type { SynergyFormControl } from '../../internal/synergy-element.js';
|
|
22
21
|
import type SynRadio from '../radio/radio.js';
|
|
23
22
|
import type SynRadioButton from '../radio-button/radio-button.js';
|
|
@@ -49,19 +48,26 @@ import { enableDefaultSettings } from '../../utilities/defaultSettings/decorator
|
|
|
49
48
|
*/
|
|
50
49
|
@enableDefaultSettings('SynRadioGroup')
|
|
51
50
|
export default class SynRadioGroup extends SynergyElement implements SynergyFormControl {
|
|
52
|
-
static styles: CSSResultGroup = [componentStyles, formControlStyles, styles
|
|
51
|
+
static styles: CSSResultGroup = [componentStyles, formControlStyles, styles];
|
|
52
|
+
|
|
53
53
|
static dependencies = { 'syn-button-group': SynButtonGroup };
|
|
54
54
|
|
|
55
55
|
protected readonly formControlController = new FormControlController(this);
|
|
56
|
+
|
|
56
57
|
private readonly hasSlotController = new HasSlotController(this, 'help-text', 'label');
|
|
58
|
+
|
|
57
59
|
private customValidityMessage = '';
|
|
60
|
+
|
|
58
61
|
private validationTimeout: number;
|
|
59
62
|
|
|
60
63
|
@query('slot:not([name])') defaultSlot: HTMLSlotElement;
|
|
64
|
+
|
|
61
65
|
@query('.radio-group__validation-input') validationInput: HTMLInputElement;
|
|
62
66
|
|
|
63
67
|
@state() private hasButtonGroup = false;
|
|
68
|
+
|
|
64
69
|
@state() private errorMessage = '';
|
|
70
|
+
|
|
65
71
|
@state() defaultValue: string | number = '';
|
|
66
72
|
|
|
67
73
|
/**
|
|
@@ -90,7 +96,7 @@ export default class SynRadioGroup extends SynergyElement implements SynergyForm
|
|
|
90
96
|
@property({ reflect: true }) form = '';
|
|
91
97
|
|
|
92
98
|
/** Ensures a child radio is checked before allowing the containing form to submit. */
|
|
93
|
-
@property({
|
|
99
|
+
@property({ reflect: true, type: Boolean }) required = false;
|
|
94
100
|
|
|
95
101
|
/** Gets the validity state object */
|
|
96
102
|
get validity() {
|
|
@@ -99,7 +105,9 @@ export default class SynRadioGroup extends SynergyElement implements SynergyForm
|
|
|
99
105
|
|
|
100
106
|
if (hasCustomValidityMessage) {
|
|
101
107
|
return customErrorValidityState;
|
|
102
|
-
}
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
if (isRequiredAndEmpty) {
|
|
103
111
|
return valueMissingValidityState;
|
|
104
112
|
}
|
|
105
113
|
|
|
@@ -113,7 +121,9 @@ export default class SynRadioGroup extends SynergyElement implements SynergyForm
|
|
|
113
121
|
|
|
114
122
|
if (hasCustomValidityMessage) {
|
|
115
123
|
return this.customValidityMessage;
|
|
116
|
-
}
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
if (isRequiredAndEmpty) {
|
|
117
127
|
return this.validationInput.validationMessage;
|
|
118
128
|
}
|
|
119
129
|
|
|
@@ -138,12 +148,15 @@ export default class SynRadioGroup extends SynergyElement implements SynergyForm
|
|
|
138
148
|
const radios = this.getAllRadios();
|
|
139
149
|
const oldValue = this.value;
|
|
140
150
|
|
|
141
|
-
if
|
|
151
|
+
// #1174: If we have a radio, also do nothing if the radio is readonly
|
|
152
|
+
if (!target || target.disabled || (target as SynRadio).readonly) {
|
|
142
153
|
return;
|
|
143
154
|
}
|
|
144
155
|
|
|
145
156
|
this.value = target.value;
|
|
146
|
-
radios.forEach(radio =>
|
|
157
|
+
radios.forEach(radio => {
|
|
158
|
+
radio.checked = radio === target;
|
|
159
|
+
});
|
|
147
160
|
|
|
148
161
|
if (this.value !== oldValue) {
|
|
149
162
|
this.emit('syn-change');
|
|
@@ -156,21 +169,26 @@ export default class SynRadioGroup extends SynergyElement implements SynergyForm
|
|
|
156
169
|
return;
|
|
157
170
|
}
|
|
158
171
|
|
|
159
|
-
|
|
160
|
-
const
|
|
172
|
+
// #1174: Filter out elements that are either disabled or readonly
|
|
173
|
+
const availableRadios = this.getAllRadios().filter(radio => (!radio.disabled && !(radio as SynRadio).readonly));
|
|
174
|
+
const checkedRadio = availableRadios.find(radio => radio.checked) ?? availableRadios[0];
|
|
175
|
+
|
|
176
|
+
// eslint-disable-next-line no-nested-ternary
|
|
161
177
|
const incr = event.key === ' ' ? 0 : ['ArrowUp', 'ArrowLeft'].includes(event.key) ? -1 : 1;
|
|
162
178
|
const oldValue = this.value;
|
|
163
|
-
let index =
|
|
179
|
+
let index = availableRadios.indexOf(checkedRadio) + incr;
|
|
164
180
|
|
|
165
181
|
if (index < 0) {
|
|
166
|
-
index =
|
|
182
|
+
index = availableRadios.length - 1;
|
|
167
183
|
}
|
|
168
184
|
|
|
169
|
-
if (index >
|
|
185
|
+
if (index > availableRadios.length - 1) {
|
|
170
186
|
index = 0;
|
|
171
187
|
}
|
|
172
188
|
|
|
173
|
-
this.getAllRadios()
|
|
189
|
+
const allRadios = this.getAllRadios();
|
|
190
|
+
|
|
191
|
+
allRadios.forEach(radio => {
|
|
174
192
|
radio.checked = false;
|
|
175
193
|
|
|
176
194
|
if (!this.hasButtonGroup) {
|
|
@@ -178,14 +196,19 @@ export default class SynRadioGroup extends SynergyElement implements SynergyForm
|
|
|
178
196
|
}
|
|
179
197
|
});
|
|
180
198
|
|
|
181
|
-
|
|
182
|
-
|
|
199
|
+
// #1175: If all radios are readonly, skip and focus the first one and do not change the value
|
|
200
|
+
if (!availableRadios[index]) {
|
|
201
|
+
return;
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
this.value = availableRadios[index].value;
|
|
205
|
+
availableRadios[index].checked = true;
|
|
183
206
|
|
|
184
207
|
if (!this.hasButtonGroup) {
|
|
185
|
-
|
|
186
|
-
|
|
208
|
+
availableRadios[index].setAttribute('tabindex', '0');
|
|
209
|
+
availableRadios[index].focus();
|
|
187
210
|
} else {
|
|
188
|
-
|
|
211
|
+
availableRadios[index].shadowRoot!.querySelector('button')!.focus();
|
|
189
212
|
}
|
|
190
213
|
|
|
191
214
|
if (this.value !== oldValue) {
|
|
@@ -214,7 +237,7 @@ export default class SynRadioGroup extends SynergyElement implements SynergyForm
|
|
|
214
237
|
await radio.updateComplete;
|
|
215
238
|
radio.checked = radio.value === this.value;
|
|
216
239
|
radio.size = this.size;
|
|
217
|
-
})
|
|
240
|
+
}),
|
|
218
241
|
);
|
|
219
242
|
|
|
220
243
|
this.hasButtonGroup = radios.some(radio => radio.tagName.toLowerCase() === 'syn-radio-button');
|
|
@@ -262,7 +285,9 @@ export default class SynRadioGroup extends SynergyElement implements SynergyForm
|
|
|
262
285
|
|
|
263
286
|
private updateCheckedRadio() {
|
|
264
287
|
const radios = this.getAllRadios();
|
|
265
|
-
radios.forEach(radio =>
|
|
288
|
+
radios.forEach(radio => {
|
|
289
|
+
radio.checked = radio.value === this.value;
|
|
290
|
+
});
|
|
266
291
|
this.formControlController.setValidity(this.validity.valid);
|
|
267
292
|
}
|
|
268
293
|
|
|
@@ -309,7 +334,9 @@ export default class SynRadioGroup extends SynergyElement implements SynergyForm
|
|
|
309
334
|
// Show the browser's constraint validation message
|
|
310
335
|
this.validationInput.hidden = false;
|
|
311
336
|
this.validationInput.reportValidity();
|
|
312
|
-
this.validationTimeout = setTimeout(() =>
|
|
337
|
+
this.validationTimeout = setTimeout(() => {
|
|
338
|
+
this.validationInput.hidden = true;
|
|
339
|
+
}, 10000) as unknown as number;
|
|
313
340
|
}
|
|
314
341
|
|
|
315
342
|
return isValid;
|
|
@@ -338,6 +365,7 @@ export default class SynRadioGroup extends SynergyElement implements SynergyForm
|
|
|
338
365
|
}
|
|
339
366
|
|
|
340
367
|
render() {
|
|
368
|
+
/* eslint-disable @typescript-eslint/unbound-method */
|
|
341
369
|
const hasLabelSlot = this.hasSlotController.test('label');
|
|
342
370
|
const hasHelpTextSlot = this.hasSlotController.test('help-text');
|
|
343
371
|
const hasLabel = this.label ? true : !!hasLabelSlot;
|
|
@@ -351,12 +379,12 @@ export default class SynRadioGroup extends SynergyElement implements SynergyForm
|
|
|
351
379
|
part="form-control"
|
|
352
380
|
class=${classMap({
|
|
353
381
|
'form-control': true,
|
|
354
|
-
'form-control--
|
|
355
|
-
'form-control--
|
|
382
|
+
'form-control--has-help-text': hasHelpText,
|
|
383
|
+
'form-control--has-label': hasLabel,
|
|
356
384
|
'form-control--large': this.size === 'large',
|
|
385
|
+
'form-control--medium': this.size === 'medium',
|
|
357
386
|
'form-control--radio-group': true,
|
|
358
|
-
'form-control--
|
|
359
|
-
'form-control--has-help-text': hasHelpText
|
|
387
|
+
'form-control--small': this.size === 'small',
|
|
360
388
|
})}
|
|
361
389
|
role="radiogroup"
|
|
362
390
|
aria-labelledby="label"
|
|
@@ -407,5 +435,6 @@ export default class SynRadioGroup extends SynergyElement implements SynergyForm
|
|
|
407
435
|
</div>
|
|
408
436
|
</fieldset>
|
|
409
437
|
`;
|
|
438
|
+
/* eslint-enable @typescript-eslint/unbound-method */
|
|
410
439
|
}
|
|
411
440
|
}
|
|
@@ -177,6 +177,19 @@ export class SynRangeComponent {
|
|
|
177
177
|
return this.nativeElement.disabled;
|
|
178
178
|
}
|
|
179
179
|
|
|
180
|
+
/**
|
|
181
|
+
* Sets the range to a readonly state.
|
|
182
|
+
*/
|
|
183
|
+
@Input()
|
|
184
|
+
set readonly(v: '' | SynRange['readonly']) {
|
|
185
|
+
this._ngZone.runOutsideAngular(
|
|
186
|
+
() => (this.nativeElement.readonly = v === '' || v),
|
|
187
|
+
);
|
|
188
|
+
}
|
|
189
|
+
get readonly(): SynRange['readonly'] {
|
|
190
|
+
return this.nativeElement.readonly;
|
|
191
|
+
}
|
|
192
|
+
|
|
180
193
|
/**
|
|
181
194
|
* The minimum acceptable value of the range.
|
|
182
195
|
*/
|
|
@@ -213,20 +213,26 @@ export default css`
|
|
|
213
213
|
cursor: not-allowed;
|
|
214
214
|
}
|
|
215
215
|
|
|
216
|
+
:host([readonly]) .track__wrapper,
|
|
217
|
+
:host([readonly]) .thumb,
|
|
218
|
+
:host([readonly]) .thumb.grabbed {
|
|
219
|
+
cursor: default;
|
|
220
|
+
}
|
|
221
|
+
|
|
216
222
|
/*
|
|
217
223
|
* Guard against mobile devices not removing the transform
|
|
218
224
|
* @see https://developer.mozilla.org/en-US/docs/Web/CSS/@media/any-hover
|
|
219
225
|
*/
|
|
220
226
|
@media (any-hover: hover) {
|
|
221
|
-
:host(:not([disabled])) .thumb:hover {
|
|
227
|
+
:host(:not([disabled]):not([readonly])) .thumb:hover {
|
|
222
228
|
transform: scale(var(--thumb-hit-area-size));
|
|
223
229
|
}
|
|
224
230
|
|
|
225
|
-
:host(:not([disabled])) .thumb:not(.grabbed):hover {
|
|
231
|
+
:host(:not([disabled]):not([readonly])) .thumb:not(.grabbed):hover {
|
|
226
232
|
background: var(--syn-interactive-emphasis-color-hover);
|
|
227
233
|
}
|
|
228
234
|
|
|
229
|
-
:host(:not([disabled])) .thumb:hover::after {
|
|
235
|
+
:host(:not([disabled]):not([readonly])) .thumb:hover::after {
|
|
230
236
|
/* Unset the area of the thumb click and drag area space, so it does not scale with the hover */
|
|
231
237
|
inset: unset;
|
|
232
238
|
}
|
|
@@ -282,4 +288,22 @@ export default css`
|
|
|
282
288
|
:host([data-user-invalid]) .thumb {
|
|
283
289
|
background-color: var(--syn-range-error-color);
|
|
284
290
|
}
|
|
291
|
+
|
|
292
|
+
/**
|
|
293
|
+
* #1176: Readonly state
|
|
294
|
+
*/
|
|
295
|
+
:host([readonly]) {
|
|
296
|
+
--track-color-active: var(--syn-readonly-indicator-color);
|
|
297
|
+
--track-color-inactive: var(--syn-readonly-background-color);
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
:host([readonly]) .thumb {
|
|
301
|
+
background-color: var(--syn-readonly-indicator-color);
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
:host([readonly]) .thumb:focus {
|
|
305
|
+
background-color: var(--syn-readonly-indicator-color);
|
|
306
|
+
outline: var(--syn-focus-ring);
|
|
307
|
+
outline-offset: 0;
|
|
308
|
+
}
|
|
285
309
|
`;
|