@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,28 +1,29 @@
|
|
|
1
|
-
/* eslint-disable */
|
|
2
1
|
import { css } from 'lit';
|
|
3
2
|
|
|
4
3
|
export default css`
|
|
5
|
-
|
|
4
|
+
/* stylelint-disable no-descending-specificity */
|
|
5
|
+
/* stylelint-disable plugin/no-unsupported-browser-features */
|
|
6
|
+
/* stylelint-disable property-no-vendor-prefix */
|
|
6
7
|
:host {
|
|
7
8
|
display: block;
|
|
8
9
|
}
|
|
9
10
|
|
|
10
11
|
.textarea {
|
|
11
|
-
display: grid;
|
|
12
12
|
align-items: center;
|
|
13
|
-
|
|
14
|
-
|
|
13
|
+
cursor: text;
|
|
14
|
+
display: grid;
|
|
15
15
|
font-family: var(--syn-input-font-family);
|
|
16
16
|
font-weight: var(--syn-input-font-weight);
|
|
17
|
-
line-height: var(--syn-line-height-normal);
|
|
18
17
|
letter-spacing: var(--syn-input-letter-spacing);
|
|
19
|
-
|
|
18
|
+
line-height: var(--syn-line-height-normal);
|
|
19
|
+
position: relative;
|
|
20
20
|
transition:
|
|
21
21
|
var(--syn-transition-fast) color,
|
|
22
22
|
var(--syn-transition-fast) border,
|
|
23
23
|
var(--syn-transition-fast) box-shadow,
|
|
24
24
|
var(--syn-transition-fast) background-color;
|
|
25
|
-
|
|
25
|
+
vertical-align: middle;
|
|
26
|
+
width: 100%;
|
|
26
27
|
}
|
|
27
28
|
|
|
28
29
|
/* Standard textareas */
|
|
@@ -35,6 +36,7 @@ export default css`
|
|
|
35
36
|
background-color: var(--syn-input-background-color-hover);
|
|
36
37
|
border-color: var(--syn-input-border-color-hover);
|
|
37
38
|
}
|
|
39
|
+
|
|
38
40
|
.textarea--standard:hover:not(.textarea--disabled) .textarea__control {
|
|
39
41
|
color: var(--syn-input-color-hover);
|
|
40
42
|
}
|
|
@@ -42,8 +44,8 @@ export default css`
|
|
|
42
44
|
.textarea--standard.textarea--focused:not(.textarea--disabled) {
|
|
43
45
|
background-color: var(--syn-input-background-color-focus);
|
|
44
46
|
border-color: var(--syn-input-border-color-focus);
|
|
45
|
-
color: var(--syn-input-color-focus);
|
|
46
47
|
box-shadow: 0 0 0 var(--syn-focus-ring-width) var(--syn-input-focus-ring-color);
|
|
48
|
+
color: var(--syn-input-color-focus);
|
|
47
49
|
}
|
|
48
50
|
|
|
49
51
|
.textarea--standard.textarea--focused:not(.textarea--disabled) .textarea__control {
|
|
@@ -53,8 +55,8 @@ export default css`
|
|
|
53
55
|
.textarea--standard.textarea--disabled {
|
|
54
56
|
background-color: var(--syn-input-background-color-disabled);
|
|
55
57
|
border-color: var(--syn-input-border-color-disabled);
|
|
56
|
-
opacity: 0.5;
|
|
57
58
|
cursor: not-allowed;
|
|
59
|
+
opacity: var(--syn-input-disabled-opacity); /* #429: Use token for opacity */
|
|
58
60
|
}
|
|
59
61
|
|
|
60
62
|
.textarea__control,
|
|
@@ -63,9 +65,9 @@ export default css`
|
|
|
63
65
|
}
|
|
64
66
|
|
|
65
67
|
.textarea__size-adjuster {
|
|
66
|
-
visibility: hidden;
|
|
67
|
-
pointer-events: none;
|
|
68
68
|
opacity: 0;
|
|
69
|
+
pointer-events: none;
|
|
70
|
+
visibility: hidden;
|
|
69
71
|
}
|
|
70
72
|
|
|
71
73
|
.textarea--standard.textarea--disabled .textarea__control {
|
|
@@ -78,8 +80,8 @@ export default css`
|
|
|
78
80
|
|
|
79
81
|
/* Readonly textareas */
|
|
80
82
|
.textarea--readonly {
|
|
81
|
-
border: none;
|
|
82
83
|
background-color: var(--syn-input-readonly-background-color);
|
|
84
|
+
border: none;
|
|
83
85
|
color: var(--syn-input-color);
|
|
84
86
|
}
|
|
85
87
|
|
|
@@ -95,21 +97,29 @@ export default css`
|
|
|
95
97
|
|
|
96
98
|
.textarea--readonly.textarea--disabled {
|
|
97
99
|
background-color: var(--syn-input-readonly-background-color-disabled);
|
|
98
|
-
opacity: 0.5;
|
|
99
100
|
cursor: not-allowed;
|
|
101
|
+
opacity: var(--syn-input-disabled-opacity);
|
|
100
102
|
}
|
|
101
103
|
|
|
102
104
|
.textarea__control {
|
|
105
|
+
-webkit-appearance: none;
|
|
106
|
+
appearance: none;
|
|
107
|
+
background: none;
|
|
108
|
+
border: none;
|
|
109
|
+
box-shadow: none;
|
|
110
|
+
color: var(--syn-input-color);
|
|
111
|
+
cursor: inherit;
|
|
103
112
|
font-family: inherit;
|
|
104
113
|
font-size: inherit;
|
|
105
114
|
font-weight: inherit;
|
|
106
115
|
line-height: 1.4;
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
116
|
+
|
|
117
|
+
/*
|
|
118
|
+
Unfortunately we need to add a small margin to the textarea control. This is needed for the new sick 2025 theme,
|
|
119
|
+
as because of the big border-radius the resize icon will otherwise overlap with the border
|
|
120
|
+
This added margin needs to be subtracted from the padding of the textarea
|
|
121
|
+
*/
|
|
122
|
+
margin: var(--syn-spacing-3x-small);
|
|
113
123
|
}
|
|
114
124
|
|
|
115
125
|
.textarea__control::-webkit-search-decoration,
|
|
@@ -117,12 +127,13 @@ export default css`
|
|
|
117
127
|
.textarea__control::-webkit-search-results-button,
|
|
118
128
|
.textarea__control::-webkit-search-results-decoration {
|
|
119
129
|
-webkit-appearance: none;
|
|
130
|
+
appearance: none;
|
|
120
131
|
}
|
|
121
132
|
|
|
122
133
|
.textarea__control::placeholder {
|
|
123
134
|
color: var(--syn-input-placeholder-color);
|
|
124
|
-
user-select: none;
|
|
125
135
|
-webkit-user-select: none;
|
|
136
|
+
user-select: none;
|
|
126
137
|
}
|
|
127
138
|
|
|
128
139
|
.textarea__control:focus {
|
|
@@ -132,14 +143,17 @@ export default css`
|
|
|
132
143
|
/*
|
|
133
144
|
* Size modifiers
|
|
134
145
|
*/
|
|
135
|
-
|
|
136
146
|
.textarea--small {
|
|
137
147
|
border-radius: var(--syn-input-border-radius-small);
|
|
138
148
|
font-size: var(--syn-input-font-size-small);
|
|
139
149
|
}
|
|
140
150
|
|
|
141
151
|
.textarea--small .textarea__control {
|
|
142
|
-
|
|
152
|
+
/* TODO: Wait for Design response, how to handle this left / right spacing. Design has "--syn-input-spacing-medium" for all sizes,
|
|
153
|
+
but we have different (coming from shoelace) */
|
|
154
|
+
|
|
155
|
+
/* We need to subtract the added margin of the textarea control from the padding */
|
|
156
|
+
padding: calc(var(--syn-spacing-x-small) - var(--syn-spacing-3x-small)) calc(var(--syn-input-spacing-small) - var(--syn-spacing-3x-small));
|
|
143
157
|
}
|
|
144
158
|
|
|
145
159
|
.textarea--medium {
|
|
@@ -148,7 +162,8 @@ export default css`
|
|
|
148
162
|
}
|
|
149
163
|
|
|
150
164
|
.textarea--medium .textarea__control {
|
|
151
|
-
padding
|
|
165
|
+
/* We need to subtract the added margin of the textarea control from the padding */
|
|
166
|
+
padding: calc(var(--syn-spacing-x-small) - var(--syn-spacing-3x-small)) calc(var(--syn-input-spacing-medium) - var(--syn-spacing-3x-small));
|
|
152
167
|
}
|
|
153
168
|
|
|
154
169
|
.textarea--large {
|
|
@@ -157,13 +172,16 @@ export default css`
|
|
|
157
172
|
}
|
|
158
173
|
|
|
159
174
|
.textarea--large .textarea__control {
|
|
160
|
-
|
|
175
|
+
/* TODO: Wait for Design response, how to handle this left / right spacing. Design has "--syn-input-spacing-medium" for all sizes,
|
|
176
|
+
but we have different (coming from shoelace) */
|
|
177
|
+
|
|
178
|
+
/* We need to subtract the added margin of the textarea control from the padding */
|
|
179
|
+
padding: calc(var(--syn-spacing-x-small) - var(--syn-spacing-3x-small)) calc(var(--syn-input-spacing-large) - var(--syn-spacing-3x-small));
|
|
161
180
|
}
|
|
162
181
|
|
|
163
182
|
/*
|
|
164
183
|
* Resize types
|
|
165
184
|
*/
|
|
166
|
-
|
|
167
185
|
.textarea--resize-none .textarea__control {
|
|
168
186
|
resize: none;
|
|
169
187
|
}
|
|
@@ -174,7 +192,17 @@ export default css`
|
|
|
174
192
|
|
|
175
193
|
.textarea--resize-auto .textarea__control {
|
|
176
194
|
height: auto;
|
|
177
|
-
resize: none;
|
|
178
195
|
overflow-y: hidden;
|
|
196
|
+
resize: none;
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
/* Validation */
|
|
200
|
+
:host([data-user-invalid]) .textarea--standard {
|
|
201
|
+
border-color: var(--syn-input-border-color-focus-error);
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
:host([data-user-invalid]) .textarea--standard.textarea--focused:not(.textarea--disabled) {
|
|
205
|
+
border-color: var(--syn-input-border-color-focus-error);
|
|
206
|
+
box-shadow: 0 0 0 var(--syn-focus-ring-width) var(--syn-input-focus-ring-error);
|
|
179
207
|
}
|
|
180
208
|
`;
|
|
@@ -10,10 +10,8 @@ import { property, query, state } from 'lit/decorators.js';
|
|
|
10
10
|
import { watch } from '../../internal/watch.js';
|
|
11
11
|
import componentStyles from '../../styles/component.styles.js';
|
|
12
12
|
import formControlStyles from '../../styles/form-control.styles.js';
|
|
13
|
-
import formControlCustomStyles from '../../styles/form-control.custom.styles.js';
|
|
14
13
|
import SynergyElement from '../../internal/synergy-element.js';
|
|
15
14
|
import styles from './textarea.styles.js';
|
|
16
|
-
import customStyles from './textarea.custom.styles.js';
|
|
17
15
|
import type { CSSResultGroup } from 'lit';
|
|
18
16
|
import type { SynergyFormControl } from '../../internal/synergy-element.js';
|
|
19
17
|
import { enableDefaultSettings } from '../../utilities/defaultSettings/decorator.js';
|
|
@@ -42,7 +40,7 @@ import { enableDefaultSettings } from '../../utilities/defaultSettings/decorator
|
|
|
42
40
|
*/
|
|
43
41
|
@enableDefaultSettings('SynTextarea')
|
|
44
42
|
export default class SynTextarea extends SynergyElement implements SynergyFormControl {
|
|
45
|
-
static styles: CSSResultGroup = [componentStyles, formControlStyles, styles
|
|
43
|
+
static styles: CSSResultGroup = [componentStyles, formControlStyles, styles];
|
|
46
44
|
|
|
47
45
|
private readonly formControlController = new FormControlController(this, {
|
|
48
46
|
assumeInteractionOn: ['syn-blur', 'syn-input']
|
|
@@ -1,8 +1,7 @@
|
|
|
1
|
-
/* eslint-disable */
|
|
2
1
|
import { css } from 'lit';
|
|
3
2
|
|
|
4
3
|
export default css`
|
|
5
|
-
|
|
4
|
+
/* stylelint-disable property-no-vendor-prefix */
|
|
6
5
|
:host {
|
|
7
6
|
--max-width: 20rem;
|
|
8
7
|
--hide-delay: 0ms;
|
|
@@ -11,6 +10,11 @@ export default css`
|
|
|
11
10
|
display: contents;
|
|
12
11
|
}
|
|
13
12
|
|
|
13
|
+
/** #640: Adjust the zIndex of the arrow to make sure the box-shadow above does not bleed out */
|
|
14
|
+
:host ::part(arrow) {
|
|
15
|
+
z-index: 0 !important;
|
|
16
|
+
}
|
|
17
|
+
|
|
14
18
|
.tooltip {
|
|
15
19
|
--arrow-size: var(--syn-tooltip-arrow-size);
|
|
16
20
|
--arrow-color: var(--syn-tooltip-background-color);
|
|
@@ -37,21 +41,22 @@ export default css`
|
|
|
37
41
|
}
|
|
38
42
|
|
|
39
43
|
.tooltip__body {
|
|
40
|
-
display: block;
|
|
41
|
-
width: max-content;
|
|
42
|
-
max-width: var(--max-width);
|
|
43
|
-
border-radius: var(--syn-tooltip-border-radius);
|
|
44
44
|
background-color: var(--syn-tooltip-background-color);
|
|
45
|
+
border-radius: var(--syn-tooltip-border-radius);
|
|
46
|
+
box-shadow: var(--syn-shadow-large);
|
|
47
|
+
color: var(--syn-tooltip-color);
|
|
48
|
+
display: block;
|
|
45
49
|
font-family: var(--syn-tooltip-font-family);
|
|
46
50
|
font-size: var(--syn-tooltip-font-size);
|
|
47
51
|
font-weight: var(--syn-tooltip-font-weight);
|
|
48
52
|
line-height: var(--syn-tooltip-line-height);
|
|
49
|
-
|
|
50
|
-
white-space: normal;
|
|
51
|
-
color: var(--syn-tooltip-color);
|
|
53
|
+
max-width: var(--max-width);
|
|
52
54
|
padding: var(--syn-tooltip-padding);
|
|
53
55
|
pointer-events: none;
|
|
54
|
-
|
|
56
|
+
text-align: start;
|
|
55
57
|
-webkit-user-select: none;
|
|
58
|
+
user-select: none;
|
|
59
|
+
white-space: normal;
|
|
60
|
+
width: max-content;
|
|
56
61
|
}
|
|
57
62
|
`;
|
|
@@ -4,15 +4,15 @@ import { classMap } from 'lit/directives/class-map.js';
|
|
|
4
4
|
import { getAnimation, setDefaultAnimation } from '../../utilities/animation-registry.js';
|
|
5
5
|
import { html } from 'lit';
|
|
6
6
|
import { LocalizeController } from '../../utilities/localize.js';
|
|
7
|
-
import { property, query } from 'lit/decorators.js';
|
|
7
|
+
import { property, state, query } from 'lit/decorators.js';
|
|
8
8
|
import { waitForEvent } from '../../internal/event.js';
|
|
9
9
|
import { watch } from '../../internal/watch.js';
|
|
10
10
|
import componentStyles from '../../styles/component.styles.js';
|
|
11
11
|
import SynergyElement from '../../internal/synergy-element.js';
|
|
12
12
|
import SynPopup from '../popup/popup.component.js';
|
|
13
13
|
import styles from './tooltip.styles.js';
|
|
14
|
-
import customStyles from './tooltip.custom.styles.js';
|
|
15
14
|
import type { CSSResultGroup } from 'lit';
|
|
15
|
+
import type { VirtualElement } from '../popup/popup.component.js';
|
|
16
16
|
|
|
17
17
|
/**
|
|
18
18
|
* @summary Tooltips display additional information based on a specific action.
|
|
@@ -43,7 +43,7 @@ import type { CSSResultGroup } from 'lit';
|
|
|
43
43
|
* @animation tooltip.hide - The animation to use when hiding the tooltip.
|
|
44
44
|
*/
|
|
45
45
|
export default class SynTooltip extends SynergyElement {
|
|
46
|
-
static styles: CSSResultGroup = [componentStyles, styles
|
|
46
|
+
static styles: CSSResultGroup = [componentStyles, styles];
|
|
47
47
|
static dependencies = { 'syn-popup': SynPopup };
|
|
48
48
|
|
|
49
49
|
private hoverTimeout: number;
|
|
@@ -54,6 +54,13 @@ export default class SynTooltip extends SynergyElement {
|
|
|
54
54
|
@query('.tooltip__body') body: HTMLElement;
|
|
55
55
|
@query('syn-popup') popup: SynPopup;
|
|
56
56
|
|
|
57
|
+
/**
|
|
58
|
+
* The element the tooltip will be anchored to. If the anchor lives outside of the tooltip, you can provide the anchor
|
|
59
|
+
* element `id`, a DOM element reference, or a `VirtualElement`. If the anchor lives inside the tooltip, use the
|
|
60
|
+
* `anchor` slot instead.
|
|
61
|
+
*/
|
|
62
|
+
@state() private anchor: Element | string | VirtualElement | undefined = undefined;
|
|
63
|
+
|
|
57
64
|
/** The tooltip's content. If you need to display HTML, use the `content` slot instead. */
|
|
58
65
|
@property() content = '';
|
|
59
66
|
|
|
@@ -214,7 +221,7 @@ export default class SynTooltip extends SynergyElement {
|
|
|
214
221
|
}
|
|
215
222
|
}
|
|
216
223
|
|
|
217
|
-
@watch(['content', 'distance','placement', 'skidding'])
|
|
224
|
+
@watch(['anchor', 'content', 'distance','placement', 'skidding'])
|
|
218
225
|
async handleOptionsChange() {
|
|
219
226
|
if (this.hasUpdated) {
|
|
220
227
|
await this.updateComplete;
|
|
@@ -258,6 +265,7 @@ export default class SynTooltip extends SynergyElement {
|
|
|
258
265
|
render() {
|
|
259
266
|
return html`
|
|
260
267
|
<syn-popup
|
|
268
|
+
.anchor=${this.anchor}
|
|
261
269
|
part="base"
|
|
262
270
|
exportparts="
|
|
263
271
|
popup:base__popup,
|
|
@@ -275,7 +283,7 @@ export default class SynTooltip extends SynergyElement {
|
|
|
275
283
|
arrow
|
|
276
284
|
hover-bridge
|
|
277
285
|
>
|
|
278
|
-
${'' /*
|
|
286
|
+
${'' /* Always render slotted content in anchor position - it's always visible */}
|
|
279
287
|
<slot slot="anchor" aria-describedby="tooltip"></slot>
|
|
280
288
|
|
|
281
289
|
${'' /* eslint-disable-next-line lit-a11y/accessible-name */}
|
|
@@ -22,16 +22,24 @@ import '@synergy-design-system/components/components/validate/validate.js';
|
|
|
22
22
|
* and showing the validation message in a consistent, user defined way.
|
|
23
23
|
* @documentation https://synergy-design-system.github.io/?path=/docs/components-syn-validate--docs
|
|
24
24
|
* @dependency syn-alert
|
|
25
|
+
* @dependency syn-tooltip
|
|
25
26
|
*
|
|
26
27
|
* @slot - The form field that should be validated.
|
|
27
28
|
* Avoid slotting in more than one element, as subsequent ones will be ignored.
|
|
28
29
|
*
|
|
29
30
|
* @csspart base - The component's base wrapper.
|
|
30
31
|
* @csspart input-wrapper - The container that wraps the form field.
|
|
32
|
+
*
|
|
31
33
|
* @csspart alert - The syn-alert that is shown when the variant is set to "inline".
|
|
32
34
|
* @csspart alert__base - The container that wraps the alert.
|
|
33
35
|
* @csspart alert__message - The container that wraps the alert message.
|
|
34
36
|
* @csspart alert__icon - The container that wraps the alert icon.
|
|
37
|
+
*
|
|
38
|
+
* @csspart tooltip - The syn-tooltip that is shown when the variant is set to "tooltip".
|
|
39
|
+
* @csspart tooltip__base - The container that wraps the tooltip.
|
|
40
|
+
* @csspart tooltip__popup - The container that wraps the tooltip popup.
|
|
41
|
+
* @csspart tooltip__arrow - The container that wraps the tooltip arrow.
|
|
42
|
+
* @csspart tooltip__body - The container that wraps the tooltip body.
|
|
35
43
|
*/
|
|
36
44
|
@Component({
|
|
37
45
|
selector: 'syn-validate',
|
|
@@ -52,6 +60,7 @@ export class SynValidateComponent {
|
|
|
52
60
|
|
|
53
61
|
The following variants are supported:
|
|
54
62
|
- **native** (default): Uses the native browser validation, usually a browser tooltip.
|
|
63
|
+
- **tooltip**: Show the validation message as a tooltip using a `<syn-tooltip>`.
|
|
55
64
|
- **inline**: Show the validation message underneath the element, using a `<syn-alert>`
|
|
56
65
|
*/
|
|
57
66
|
@Input()
|
|
@@ -16,16 +16,24 @@ Component.define('syn-validate');
|
|
|
16
16
|
* and showing the validation message in a consistent, user defined way.
|
|
17
17
|
* @documentation https://synergy-design-system.github.io/?path=/docs/components-syn-validate--docs
|
|
18
18
|
* @dependency syn-alert
|
|
19
|
+
* @dependency syn-tooltip
|
|
19
20
|
*
|
|
20
21
|
* @slot - The form field that should be validated.
|
|
21
22
|
* Avoid slotting in more than one element, as subsequent ones will be ignored.
|
|
22
23
|
*
|
|
23
24
|
* @csspart base - The component's base wrapper.
|
|
24
25
|
* @csspart input-wrapper - The container that wraps the form field.
|
|
26
|
+
*
|
|
25
27
|
* @csspart alert - The syn-alert that is shown when the variant is set to "inline".
|
|
26
28
|
* @csspart alert__base - The container that wraps the alert.
|
|
27
29
|
* @csspart alert__message - The container that wraps the alert message.
|
|
28
30
|
* @csspart alert__icon - The container that wraps the alert icon.
|
|
31
|
+
*
|
|
32
|
+
* @csspart tooltip - The syn-tooltip that is shown when the variant is set to "tooltip".
|
|
33
|
+
* @csspart tooltip__base - The container that wraps the tooltip.
|
|
34
|
+
* @csspart tooltip__popup - The container that wraps the tooltip popup.
|
|
35
|
+
* @csspart tooltip__arrow - The container that wraps the tooltip arrow.
|
|
36
|
+
* @csspart tooltip__body - The container that wraps the tooltip body.
|
|
29
37
|
*/
|
|
30
38
|
export const SynValidate = createComponent({
|
|
31
39
|
displayName: 'SynValidate',
|
|
@@ -1,14 +1,21 @@
|
|
|
1
1
|
import type { CSSResultGroup, PropertyValues } from 'lit';
|
|
2
2
|
import { html } from 'lit';
|
|
3
|
-
import {
|
|
3
|
+
import {
|
|
4
|
+
property,
|
|
5
|
+
query,
|
|
6
|
+
queryAssignedElements,
|
|
7
|
+
state,
|
|
8
|
+
} from 'lit/decorators.js';
|
|
4
9
|
import { ifDefined } from 'lit/directives/if-defined.js';
|
|
5
10
|
import componentStyles from '../../styles/component.styles.js';
|
|
6
11
|
import SynergyElement from '../../internal/synergy-element.js';
|
|
7
12
|
import type SynInput from '../input/input.component.js';
|
|
8
13
|
import { watch } from '../../internal/watch.js';
|
|
9
14
|
import SynAlert from '../alert/alert.component.js';
|
|
15
|
+
import SynTooltip from '../tooltip/tooltip.component.js';
|
|
10
16
|
import {
|
|
11
17
|
alertSizeForInput,
|
|
18
|
+
getActualInputElement,
|
|
12
19
|
getEventNameForElement,
|
|
13
20
|
isBlurEvent,
|
|
14
21
|
isInvalidEvent,
|
|
@@ -18,29 +25,49 @@ import {
|
|
|
18
25
|
import styles from './validate.styles.js';
|
|
19
26
|
import { enableDefaultSettings } from '../../utilities/defaultSettings/decorator.js';
|
|
20
27
|
|
|
28
|
+
/**
|
|
29
|
+
* Utility function that renders the default slot content.
|
|
30
|
+
* This is needed to avoid code duplication when rendering the default slot in both the tooltip and the regular render function.
|
|
31
|
+
*/
|
|
32
|
+
const renderDefaultSlot = () => html`
|
|
33
|
+
<slot
|
|
34
|
+
class="validate__input-wrapper"
|
|
35
|
+
part="input-wrapper"
|
|
36
|
+
></slot>
|
|
37
|
+
`;
|
|
38
|
+
|
|
21
39
|
/**
|
|
22
40
|
* @summary Validate provides form field validation messages in a unified way.
|
|
23
41
|
* It does this by using [the native browser validation](https://developer.mozilla.org/en-US/docs/Learn/Forms/Form_validation)
|
|
24
42
|
* and showing the validation message in a consistent, user defined way.
|
|
25
43
|
* @documentation https://synergy-design-system.github.io/?path=/docs/components-syn-validate--docs
|
|
26
44
|
* @dependency syn-alert
|
|
45
|
+
* @dependency syn-tooltip
|
|
27
46
|
*
|
|
28
47
|
* @slot - The form field that should be validated.
|
|
29
48
|
* Avoid slotting in more than one element, as subsequent ones will be ignored.
|
|
30
49
|
*
|
|
31
50
|
* @csspart base - The component's base wrapper.
|
|
32
51
|
* @csspart input-wrapper - The container that wraps the form field.
|
|
52
|
+
*
|
|
33
53
|
* @csspart alert - The syn-alert that is shown when the variant is set to "inline".
|
|
34
54
|
* @csspart alert__base - The container that wraps the alert.
|
|
35
55
|
* @csspart alert__message - The container that wraps the alert message.
|
|
36
56
|
* @csspart alert__icon - The container that wraps the alert icon.
|
|
37
|
-
|
|
57
|
+
*
|
|
58
|
+
* @csspart tooltip - The syn-tooltip that is shown when the variant is set to "tooltip".
|
|
59
|
+
* @csspart tooltip__base - The container that wraps the tooltip.
|
|
60
|
+
* @csspart tooltip__popup - The container that wraps the tooltip popup.
|
|
61
|
+
* @csspart tooltip__arrow - The container that wraps the tooltip arrow.
|
|
62
|
+
* @csspart tooltip__body - The container that wraps the tooltip body.
|
|
63
|
+
*/
|
|
38
64
|
@enableDefaultSettings('SynValidate')
|
|
39
65
|
export default class SynValidate extends SynergyElement {
|
|
40
66
|
static styles: CSSResultGroup = [componentStyles, styles];
|
|
41
67
|
|
|
42
68
|
static dependencies = {
|
|
43
69
|
'syn-alert': SynAlert,
|
|
70
|
+
'syn-tooltip': SynTooltip,
|
|
44
71
|
};
|
|
45
72
|
|
|
46
73
|
controller = new AbortController();
|
|
@@ -51,6 +78,8 @@ export default class SynValidate extends SynergyElement {
|
|
|
51
78
|
|
|
52
79
|
@queryAssignedElements() private slottedChildren: HTMLElement[];
|
|
53
80
|
|
|
81
|
+
@query('syn-tooltip') private tooltipElement?: SynTooltip;
|
|
82
|
+
|
|
54
83
|
@state() validationMessage = '';
|
|
55
84
|
|
|
56
85
|
@state() eagerFirstMount = true;
|
|
@@ -61,14 +90,17 @@ export default class SynValidate extends SynergyElement {
|
|
|
61
90
|
|
|
62
91
|
@state() alertSize?: SynInput['size'];
|
|
63
92
|
|
|
93
|
+
@state() hasFocus = false;
|
|
94
|
+
|
|
64
95
|
/**
|
|
65
96
|
* The variant that should be used to show validation alerts.
|
|
66
97
|
*
|
|
67
98
|
* The following variants are supported:
|
|
68
99
|
* - **native** (default): Uses the native browser validation, usually a browser tooltip.
|
|
100
|
+
* - **tooltip**: Show the validation message as a tooltip using a `<syn-tooltip>`.
|
|
69
101
|
* - **inline**: Show the validation message underneath the element, using a `<syn-alert>`
|
|
70
102
|
*/
|
|
71
|
-
@property({ reflect: true }) variant: 'native' | 'inline' = 'native';
|
|
103
|
+
@property({ reflect: true }) variant: 'native' | 'tooltip' | 'inline' = 'native';
|
|
72
104
|
|
|
73
105
|
/** Do not show the error icon when using the inline variant validation */
|
|
74
106
|
@property({ attribute: 'hide-icon', reflect: true, type: Boolean }) hideIcon = false;
|
|
@@ -235,6 +267,20 @@ export default class SynValidate extends SynergyElement {
|
|
|
235
267
|
signal: this.controller.signal,
|
|
236
268
|
});
|
|
237
269
|
}
|
|
270
|
+
|
|
271
|
+
// #664: Add focus/blur listeners specifically for tooltip variant
|
|
272
|
+
// This is needed because we want to show the tooltip on focus and hide it on blur, but only when using the tooltip variant.
|
|
273
|
+
// Otherwise, this would interfere with the native validation tooltip, which also relies on focus and blur events.
|
|
274
|
+
const focusEvent = getEventNameForElement(input, 'focus');
|
|
275
|
+
const blurEvent = getEventNameForElement(input, 'blur');
|
|
276
|
+
|
|
277
|
+
input.addEventListener(focusEvent, this.handleInputFocus, {
|
|
278
|
+
signal: this.controller.signal,
|
|
279
|
+
});
|
|
280
|
+
|
|
281
|
+
input.addEventListener(blurEvent, this.handleInputBlur, {
|
|
282
|
+
signal: this.controller.signal,
|
|
283
|
+
});
|
|
238
284
|
}
|
|
239
285
|
|
|
240
286
|
private setValidationMessage(input: HTMLInputElement) {
|
|
@@ -266,6 +312,17 @@ export default class SynValidate extends SynergyElement {
|
|
|
266
312
|
}
|
|
267
313
|
};
|
|
268
314
|
|
|
315
|
+
/**
|
|
316
|
+
* Handle focus/blur events for tooltip variant
|
|
317
|
+
*/
|
|
318
|
+
private handleInputFocus = () => {
|
|
319
|
+
this.hasFocus = true;
|
|
320
|
+
};
|
|
321
|
+
|
|
322
|
+
private handleInputBlur = () => {
|
|
323
|
+
this.hasFocus = false;
|
|
324
|
+
};
|
|
325
|
+
|
|
269
326
|
/**
|
|
270
327
|
* Handle the blur event during validation
|
|
271
328
|
*/
|
|
@@ -439,6 +496,36 @@ export default class SynValidate extends SynergyElement {
|
|
|
439
496
|
this?.sizeObserver?.disconnect();
|
|
440
497
|
}
|
|
441
498
|
|
|
499
|
+
updated(changedProperties: PropertyValues) {
|
|
500
|
+
super.updated(changedProperties);
|
|
501
|
+
|
|
502
|
+
// #664: Make sure to update the syn-tooltip if the validation state changes when using the tooltip variant
|
|
503
|
+
if (this.variant !== 'tooltip') {
|
|
504
|
+
return;
|
|
505
|
+
}
|
|
506
|
+
|
|
507
|
+
const tooltip = this.tooltipElement;
|
|
508
|
+
|
|
509
|
+
if (!tooltip) {
|
|
510
|
+
return;
|
|
511
|
+
}
|
|
512
|
+
|
|
513
|
+
// When we have a valid tooltip,
|
|
514
|
+
// we need to update the content and show or hide it based on the validation state and focus state.
|
|
515
|
+
// We have to do this manually, as there is a problem when updating open and content at the same time.
|
|
516
|
+
// The order is critical: fill before showing, don´t update the content during hide.
|
|
517
|
+
const shouldShowTooltip = !this.isValid && this.validationMessage && this.hasFocus;
|
|
518
|
+
|
|
519
|
+
if (shouldShowTooltip) {
|
|
520
|
+
tooltip.content = this.validationMessage;
|
|
521
|
+
// eslint-disable-next-line @typescript-eslint/no-floating-promises
|
|
522
|
+
tooltip.show();
|
|
523
|
+
} else {
|
|
524
|
+
// eslint-disable-next-line @typescript-eslint/no-floating-promises
|
|
525
|
+
tooltip.hide();
|
|
526
|
+
}
|
|
527
|
+
}
|
|
528
|
+
|
|
442
529
|
private renderInlineValidation() {
|
|
443
530
|
if (this.variant !== 'inline' || !this.validationMessage) {
|
|
444
531
|
return '';
|
|
@@ -462,16 +549,27 @@ export default class SynValidate extends SynergyElement {
|
|
|
462
549
|
}
|
|
463
550
|
|
|
464
551
|
render() {
|
|
552
|
+
// #664: When using the tooltip variant, we need to wrap the default slot in a tooltip when the input is invalid and has a validation message.
|
|
553
|
+
const slotContent = this.variant === 'tooltip'
|
|
554
|
+
? html`
|
|
555
|
+
<syn-tooltip
|
|
556
|
+
.anchor=${getActualInputElement(this.getInput()) as Element ?? undefined}
|
|
557
|
+
exportparts="base:tooltip__base,base__popup:tooltip__popup,base__arrow:tooltip__arrow,body:tooltip__body"
|
|
558
|
+
.open=${this.eager ? !this.isValid && this.validationMessage.length > 0 : false}
|
|
559
|
+
part="tooltip"
|
|
560
|
+
placement="bottom"
|
|
561
|
+
trigger="manual"
|
|
562
|
+
>
|
|
563
|
+
${renderDefaultSlot()}
|
|
564
|
+
</syn-tooltip>
|
|
565
|
+
` : renderDefaultSlot();
|
|
566
|
+
|
|
465
567
|
return html`
|
|
466
568
|
<div
|
|
467
569
|
class="validate"
|
|
468
570
|
part="base"
|
|
469
571
|
>
|
|
470
|
-
|
|
471
|
-
class="validate__input-wrapper"
|
|
472
|
-
part="input-wrapper"
|
|
473
|
-
></slot>
|
|
474
|
-
|
|
572
|
+
${slotContent}
|
|
475
573
|
${this.renderInlineValidation()}
|
|
476
574
|
</div>
|
|
477
575
|
`;
|
|
@@ -11,16 +11,24 @@
|
|
|
11
11
|
* and showing the validation message in a consistent, user defined way.
|
|
12
12
|
* @documentation https://synergy-design-system.github.io/?path=/docs/components-syn-validate--docs
|
|
13
13
|
* @dependency syn-alert
|
|
14
|
+
* @dependency syn-tooltip
|
|
14
15
|
*
|
|
15
16
|
* @slot - The form field that should be validated.
|
|
16
17
|
* Avoid slotting in more than one element, as subsequent ones will be ignored.
|
|
17
18
|
*
|
|
18
19
|
* @csspart base - The component's base wrapper.
|
|
19
20
|
* @csspart input-wrapper - The container that wraps the form field.
|
|
21
|
+
*
|
|
20
22
|
* @csspart alert - The syn-alert that is shown when the variant is set to "inline".
|
|
21
23
|
* @csspart alert__base - The container that wraps the alert.
|
|
22
24
|
* @csspart alert__message - The container that wraps the alert message.
|
|
23
25
|
* @csspart alert__icon - The container that wraps the alert icon.
|
|
26
|
+
*
|
|
27
|
+
* @csspart tooltip - The syn-tooltip that is shown when the variant is set to "tooltip".
|
|
28
|
+
* @csspart tooltip__base - The container that wraps the tooltip.
|
|
29
|
+
* @csspart tooltip__popup - The container that wraps the tooltip popup.
|
|
30
|
+
* @csspart tooltip__arrow - The container that wraps the tooltip arrow.
|
|
31
|
+
* @csspart tooltip__body - The container that wraps the tooltip body.
|
|
24
32
|
*/
|
|
25
33
|
import { computed, ref } from 'vue';
|
|
26
34
|
import '@synergy-design-system/components/components/validate/validate.js';
|
|
@@ -41,6 +49,7 @@ const props = defineProps<{
|
|
|
41
49
|
|
|
42
50
|
The following variants are supported:
|
|
43
51
|
- **native** (default): Uses the native browser validation, usually a browser tooltip.
|
|
52
|
+
- **tooltip**: Show the validation message as a tooltip using a `<syn-tooltip>`.
|
|
44
53
|
- **inline**: Show the validation message underneath the element, using a `<syn-alert>`
|
|
45
54
|
*/
|
|
46
55
|
variant?: SynValidate['variant'];
|