@progressive-development/pd-forms 0.0.4 → 0.0.6
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/index.js +21 -0
- package/package.json +3 -2
- package/src/shared-input-styles.js +227 -0
- package/src/squi-base-ui-input.js +68 -0
- package/src/squi-base-ui.js +14 -0
- package/src/squi-button-group.js +52 -0
- package/src/squi-button.js +187 -0
- package/src/squi-checkbox.js +290 -0
- package/src/squi-form-container.js +51 -0
- package/src/squi-form-row.js +103 -0
- package/src/squi-input-area.js +185 -0
- package/src/squi-input.js +206 -0
- package/src/squi-radio-group.js +111 -0
- package/src/squi-select.js +308 -0
- package/src/components/test-el.js +0 -32
- package/test-el.js +0 -34
|
@@ -0,0 +1,206 @@
|
|
|
1
|
+
import { html, css } from 'lit';
|
|
2
|
+
import { classMap } from 'lit/directives/class-map';
|
|
3
|
+
import { SharedInputStyles } from './shared-input-styles.js';
|
|
4
|
+
|
|
5
|
+
import { SquiBaseUIInput, INPUT_TYPE_TEXT } from './squi-base-ui-input.js';
|
|
6
|
+
|
|
7
|
+
import '@progressive-development/pd-icon/pd-icon.js';
|
|
8
|
+
|
|
9
|
+
// https://github.com/Victor-Bernabe/lit-input
|
|
10
|
+
// https://levelup.gitconnected.com/build-a-material-like-input-web-component-using-litelement-20e9e0d203b6
|
|
11
|
+
/**
|
|
12
|
+
* Web component to input text implemented with LitElement.
|
|
13
|
+
*
|
|
14
|
+
* ### Styling
|
|
15
|
+
*
|
|
16
|
+
* All custom properties should start with `--squi-input`.
|
|
17
|
+
*
|
|
18
|
+
* Font and icon size will scale automatically with `squi-input`'s height.
|
|
19
|
+
*
|
|
20
|
+
* Custom property | Description | Default
|
|
21
|
+
* ----------------|-------------|--------
|
|
22
|
+
* `--squi-input-width` | Width | `250px`
|
|
23
|
+
* `--my-input-height` | Height | `30px`
|
|
24
|
+
* `--squi-input-border` | Border | `1px solid black`
|
|
25
|
+
* `--squi-input-border-focus` | Border when focused | `1px solid #4d90fe`
|
|
26
|
+
* `--squi-input-background-color` | Background color | `white`
|
|
27
|
+
* `--squi-input-font-size` | Font size | `calc(var(--my-input-height) / 1.8)`
|
|
28
|
+
* `--squi-input-text-color` | Text color | `inherit`
|
|
29
|
+
* `--squi-input-placeholder-color` | Placeholder text color | `#a0a0a0`
|
|
30
|
+
* `--squi-input-icon-fill-color` | Icon fill color | `currentcolor`
|
|
31
|
+
* `--squi-input-icon-stroke-color` | Icon stroke color | `none`
|
|
32
|
+
*
|
|
33
|
+
* ### Icon and text alignment
|
|
34
|
+
*
|
|
35
|
+
* The icon inside `squi-input` is hidden by default. To show it, set the attribute `icon-right` or `icon-left`.
|
|
36
|
+
*
|
|
37
|
+
* <squi-input icon-left></squi-input>
|
|
38
|
+
* <squi-input icon-right></squi-input>
|
|
39
|
+
*
|
|
40
|
+
* <squi-input icon-left .icon="${'hardware:headset'}"></squi-input>
|
|
41
|
+
*
|
|
42
|
+
* Text can be left or right aligned. Default is left alignment.
|
|
43
|
+
*
|
|
44
|
+
* <squi-input text-right></squi-input>
|
|
45
|
+
* <squi-input text-left></squi-input>
|
|
46
|
+
*/
|
|
47
|
+
export class SquiInput extends SquiBaseUIInput {
|
|
48
|
+
/**
|
|
49
|
+
* Fired when `squi-input` has focus and the user press `Enter` key.
|
|
50
|
+
* @event enter-pressed
|
|
51
|
+
*/
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* Fired when `squi-input` has focus and the user press any key except `Enter`.
|
|
55
|
+
* @event key-pressed
|
|
56
|
+
*/
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* Fire when the `squi-input` loses focus.
|
|
60
|
+
* @event focus-lost
|
|
61
|
+
*/
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* Fire when the icon inside `squi-input` is clicked.
|
|
65
|
+
* @event icon-clicked
|
|
66
|
+
*/
|
|
67
|
+
|
|
68
|
+
static get styles() {
|
|
69
|
+
return [
|
|
70
|
+
SharedInputStyles,
|
|
71
|
+
css`
|
|
72
|
+
* {
|
|
73
|
+
box-sizing: border-box;
|
|
74
|
+
}
|
|
75
|
+
`,
|
|
76
|
+
];
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
static get properties() {
|
|
80
|
+
return {
|
|
81
|
+
key: { type: String }, // Test, wird für das setzten der Error Msg benötigt
|
|
82
|
+
|
|
83
|
+
/** Placeholder for `squi-input` initial text. */
|
|
84
|
+
placeHolder: { type: String },
|
|
85
|
+
/**
|
|
86
|
+
* Icon to be shown inside `squi-input`.
|
|
87
|
+
*/
|
|
88
|
+
icon: { type: String },
|
|
89
|
+
secret: { type: Boolean }, // True for type password
|
|
90
|
+
minlength: { type: String },
|
|
91
|
+
maxlength: { type: String }, // max length for field
|
|
92
|
+
};
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
constructor() {
|
|
96
|
+
super();
|
|
97
|
+
this._inputType = INPUT_TYPE_TEXT;
|
|
98
|
+
this.placeHolder = '';
|
|
99
|
+
this.icon = 'toggleCollapse';
|
|
100
|
+
this.secret = false;
|
|
101
|
+
this.key = '';
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
render() {
|
|
105
|
+
return html`
|
|
106
|
+
<label for="${this.id}Input">${this.label}</label>
|
|
107
|
+
<div class="input ${classMap({ error: this.errorMsg.length > 0 })}">
|
|
108
|
+
<squi-icon
|
|
109
|
+
icon="toggleCollapse"
|
|
110
|
+
@click="${this._onIconClick}"
|
|
111
|
+
></squi-icon>
|
|
112
|
+
<input
|
|
113
|
+
id="${this.id}Input"
|
|
114
|
+
class="input-style ${this.gradient ? 'gradient' : ''}"
|
|
115
|
+
type="${this.secret ? 'password' : 'text'}"
|
|
116
|
+
placeholder="${this.disabled ? '---' : this.placeHolder}"
|
|
117
|
+
.value="${this.value}"
|
|
118
|
+
?readonly="${this.readonly}"
|
|
119
|
+
minlength="${this.minlength}"
|
|
120
|
+
maxlength="${this.maxlength}"
|
|
121
|
+
?disabled="${this.disabled}"
|
|
122
|
+
@keyup="${this._onKeyUp}"
|
|
123
|
+
@blur="${this._onBlur}"
|
|
124
|
+
/>
|
|
125
|
+
<!-- Sollte erst Clientseitig im Input validiert werden. Meldung verschwindet erst beim Submit nicht mehr zeitgemäß-->
|
|
126
|
+
${this.errorMsg.length > 0
|
|
127
|
+
? html`<span class="error-msg">${this.errorMsg}</span>`
|
|
128
|
+
: ''}
|
|
129
|
+
</div>
|
|
130
|
+
`;
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
firstUpdated() {
|
|
134
|
+
// Save input reference for performance (bind html element to class property)
|
|
135
|
+
this._input = this.shadowRoot.querySelector('input');
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
_onKeyUp(event) {
|
|
139
|
+
// set value (tbd überdenken)
|
|
140
|
+
this.value = this._input.value;
|
|
141
|
+
|
|
142
|
+
// If Enter key pressed, fire 'enter-pressed'
|
|
143
|
+
if (Number(event.keyCode) === 13) {
|
|
144
|
+
this.dispatchEvent(
|
|
145
|
+
new CustomEvent('enter-pressed', {
|
|
146
|
+
detail: {
|
|
147
|
+
value: this._input.value,
|
|
148
|
+
},
|
|
149
|
+
composed: true,
|
|
150
|
+
bubbles: true,
|
|
151
|
+
})
|
|
152
|
+
);
|
|
153
|
+
event.preventDefault();
|
|
154
|
+
} else {
|
|
155
|
+
// If any other key, fire 'key-pressed'
|
|
156
|
+
|
|
157
|
+
// Interessante Stelle, die error msg wird von außen gesetzt
|
|
158
|
+
// wenn die error msg hier gesetzt wird, danach nicht mehr für änderungen von außen für den gleichen typ gültig
|
|
159
|
+
// da der wert außen nicht verändert wurde, und daher nicht neu gesetzt wird...
|
|
160
|
+
// => Die eigentliche NAchricht ist nochgesetzt...
|
|
161
|
+
// Hack bevor das Thema richtig nachgezogen wird (recherche), es wird nicht für felder von bestimmten typ durchgeführt
|
|
162
|
+
// d.h. für zip und mail nicht
|
|
163
|
+
/*
|
|
164
|
+
if (this.key != 'mail' && this.key != 'zip' && this.key != 'phone') {
|
|
165
|
+
this.errorMsg = '';
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
Aufrund der gennanten Problematik auskommentiert, ein evenlistener sorgt nun dafür
|
|
169
|
+
*/
|
|
170
|
+
this.dispatchEvent(
|
|
171
|
+
new CustomEvent('key-pressed', {
|
|
172
|
+
detail: {
|
|
173
|
+
value: this._input.value,
|
|
174
|
+
name: this.valueName,
|
|
175
|
+
},
|
|
176
|
+
composed: true,
|
|
177
|
+
bubbles: true,
|
|
178
|
+
})
|
|
179
|
+
);
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
_onBlur() {
|
|
184
|
+
this.dispatchEvent(
|
|
185
|
+
new CustomEvent('focus-lost', {
|
|
186
|
+
detail: {
|
|
187
|
+
value: this._input.value,
|
|
188
|
+
},
|
|
189
|
+
composed: true,
|
|
190
|
+
bubbles: true,
|
|
191
|
+
})
|
|
192
|
+
);
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
_onIconClick() {
|
|
196
|
+
this.dispatchEvent(
|
|
197
|
+
new CustomEvent('icon-clicked', {
|
|
198
|
+
detail: {
|
|
199
|
+
value: this._input.value,
|
|
200
|
+
},
|
|
201
|
+
composed: true,
|
|
202
|
+
bubbles: true,
|
|
203
|
+
})
|
|
204
|
+
);
|
|
205
|
+
}
|
|
206
|
+
}
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license
|
|
3
|
+
* Copyright (c) 2019 The Polymer Project Authors. All rights reserved.
|
|
4
|
+
* This code may only be used under the BSD style license found at
|
|
5
|
+
* http://polymer.github.io/LICENSE.txt
|
|
6
|
+
* The complete set of authors may be found at
|
|
7
|
+
* http://polymer.github.io/AUTHORS.txt
|
|
8
|
+
* The complete set of contributors may be found at
|
|
9
|
+
* http://polymer.github.io/CONTRIBUTORS.txt
|
|
10
|
+
* Code distributed by Google as part of the polymer project is also
|
|
11
|
+
* subject to an additional IP rights grant found at
|
|
12
|
+
* http://polymer.github.io/PATENTS.txt
|
|
13
|
+
*/
|
|
14
|
+
|
|
15
|
+
import {LitElement, html, css} from 'lit';
|
|
16
|
+
import { classMap } from 'lit/directives/class-map';
|
|
17
|
+
import { SharedInputStyles } from './shared-input-styles.js';
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* An example element.
|
|
21
|
+
*
|
|
22
|
+
* @slot - This element has a slot
|
|
23
|
+
* @csspart button - The button
|
|
24
|
+
*/
|
|
25
|
+
export class SquiRadioGroup extends LitElement {
|
|
26
|
+
|
|
27
|
+
static get styles() {
|
|
28
|
+
return [
|
|
29
|
+
SharedInputStyles,
|
|
30
|
+
css`
|
|
31
|
+
:host {
|
|
32
|
+
/* define direction of checkboxes*/
|
|
33
|
+
--my-direction: var(--group-direction, row);
|
|
34
|
+
|
|
35
|
+
/* ToDo: Auf die schnelle, anders lösen (vertikal / horizontal als eigenschaft mit entsprechenden klassen)*/
|
|
36
|
+
--my-gap: var(--group-gap, 5px);
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
.group-style {
|
|
40
|
+
display: flex;
|
|
41
|
+
gap: var(--my-gap);
|
|
42
|
+
flex-direction: var(--my-direction);
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
`];
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
static get properties() {
|
|
49
|
+
return {
|
|
50
|
+
label: {type: String},
|
|
51
|
+
valueName: { type: String },
|
|
52
|
+
errorMsg: {type: String} // errorMsg (could set fronm outside for busines validation, internal validation=> todo)
|
|
53
|
+
};
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
constructor() {
|
|
57
|
+
super();
|
|
58
|
+
this.label = '';
|
|
59
|
+
this.valueName = '';
|
|
60
|
+
this.errorMsg = '';
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
get value() {
|
|
64
|
+
const elColl = this.getElementsByTagName('squi-checkbox');
|
|
65
|
+
let returnVal;
|
|
66
|
+
Object.keys(elColl).forEach(keyValue => {
|
|
67
|
+
if (elColl[keyValue].value === 'true') {
|
|
68
|
+
returnVal = elColl[keyValue];
|
|
69
|
+
}
|
|
70
|
+
});
|
|
71
|
+
return returnVal ? returnVal.valueName : undefined;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
firstUpdated() {
|
|
75
|
+
|
|
76
|
+
// add event listener
|
|
77
|
+
this.addEventListener('checkbox-changed', (e) => {
|
|
78
|
+
const elCollection = this.getElementsByTagName('squi-checkbox');
|
|
79
|
+
Object.keys(elCollection).forEach(keyValue => {
|
|
80
|
+
if (elCollection[keyValue] !== e.target) {
|
|
81
|
+
elCollection[keyValue].value = false;
|
|
82
|
+
}
|
|
83
|
+
elCollection[keyValue].readonly = (elCollection[keyValue].value === 'true');
|
|
84
|
+
// do with event handler, change from outside...
|
|
85
|
+
// this.errorMsg = '';
|
|
86
|
+
});
|
|
87
|
+
});
|
|
88
|
+
|
|
89
|
+
// set default
|
|
90
|
+
const elColl = this.getElementsByTagName('squi-checkbox');
|
|
91
|
+
Object.keys(elColl).forEach(keyValue => {
|
|
92
|
+
elColl[keyValue].readonly = elColl[keyValue].value === 'true';
|
|
93
|
+
});
|
|
94
|
+
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
render() {
|
|
98
|
+
return html`
|
|
99
|
+
<label>${this.label}</label>
|
|
100
|
+
<div class="group-style input ${classMap({'error': this.errorMsg.length > 0})}">
|
|
101
|
+
<slot></slot>
|
|
102
|
+
</div>
|
|
103
|
+
${this.errorMsg.length > 0 ? html`
|
|
104
|
+
<div class="error-box error">
|
|
105
|
+
<span class="error-msg">${this.errorMsg}</span>
|
|
106
|
+
</div>
|
|
107
|
+
` : ''}
|
|
108
|
+
`;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
}
|
|
@@ -0,0 +1,308 @@
|
|
|
1
|
+
import { html, css } from 'lit';
|
|
2
|
+
import { classMap } from 'lit/directives/class-map';
|
|
3
|
+
import { SharedInputStyles } from './shared-input-styles.js';
|
|
4
|
+
|
|
5
|
+
import { SquiBaseUIInput, INPUT_TYPE_SELECT } from './squi-base-ui-input.js';
|
|
6
|
+
|
|
7
|
+
import '@progressive-development/pd-icon/pd-icon.js';
|
|
8
|
+
|
|
9
|
+
// https://github.com/Victor-Bernabe/lit-input
|
|
10
|
+
// https://levelup.gitconnected.com/build-a-material-like-input-web-component-using-litelement-20e9e0d203b6
|
|
11
|
+
/**
|
|
12
|
+
* Web component to input text implemented with LitElement.
|
|
13
|
+
*
|
|
14
|
+
* ### Styling
|
|
15
|
+
*
|
|
16
|
+
* All custom properties should start with `--squi-input`.
|
|
17
|
+
*
|
|
18
|
+
* Font and icon size will scale automatically with `squi-input`'s height.
|
|
19
|
+
*
|
|
20
|
+
* Custom property | Description | Default
|
|
21
|
+
* ----------------|-------------|--------
|
|
22
|
+
* `--squi-input-width` | Width | `250px`
|
|
23
|
+
* `--my-input-height` | Height | `30px`
|
|
24
|
+
* `--squi-input-border` | Border | `1px solid black`
|
|
25
|
+
* `--squi-input-border-focus` | Border when focused | `1px solid #4d90fe`
|
|
26
|
+
* `--squi-input-background-color` | Background color | `white`
|
|
27
|
+
* `--squi-input-font-size` | Font size | `calc(var(--my-input-height) / 1.8)`
|
|
28
|
+
* `--squi-input-text-color` | Text color | `inherit`
|
|
29
|
+
* `--squi-input-placeholder-color` | Placeholder text color | `#a0a0a0`
|
|
30
|
+
* `--squi-input-icon-fill-color` | Icon fill color | `currentcolor`
|
|
31
|
+
* `--squi-input-icon-stroke-color` | Icon stroke color | `none`
|
|
32
|
+
*
|
|
33
|
+
* ### Icon and text alignment
|
|
34
|
+
*
|
|
35
|
+
* The icon inside `squi-input` is hidden by default. To show it, set the attribute `icon-right` or `icon-left`.
|
|
36
|
+
*
|
|
37
|
+
* <squi-input icon-left></squi-input>
|
|
38
|
+
* <squi-input icon-right></squi-input>
|
|
39
|
+
*
|
|
40
|
+
* <squi-input icon-left .icon="${'hardware:headset'}"></squi-input>
|
|
41
|
+
*
|
|
42
|
+
* Text can be left or right aligned. Default is left alignment.
|
|
43
|
+
*
|
|
44
|
+
* <squi-input text-right></squi-input>
|
|
45
|
+
* <squi-input text-left></squi-input>
|
|
46
|
+
*/
|
|
47
|
+
export class SquiSelect extends SquiBaseUIInput {
|
|
48
|
+
/**
|
|
49
|
+
* Fired when `squi-input` has focus and the user press `Enter` key.
|
|
50
|
+
* @event enter-pressed
|
|
51
|
+
*/
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* Fired when `squi-input` has focus and the user press any key except `Enter`.
|
|
55
|
+
* @event key-pressed
|
|
56
|
+
*/
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* Fired when value is changed
|
|
60
|
+
* @event change-value
|
|
61
|
+
*/
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* Fire when the `squi-input` loses focus.
|
|
65
|
+
* @event focus-lost
|
|
66
|
+
*/
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
* Fire when the icon inside `squi-input` is clicked.
|
|
70
|
+
* @event icon-clicked
|
|
71
|
+
*/
|
|
72
|
+
|
|
73
|
+
static get styles() {
|
|
74
|
+
return [
|
|
75
|
+
SharedInputStyles,
|
|
76
|
+
css`
|
|
77
|
+
/* Select style */
|
|
78
|
+
/* https://css-tricks.com/styling-a-select-like-its-2019/
|
|
79
|
+
class applies to select element itself, not a wrapper element */
|
|
80
|
+
.select-css {
|
|
81
|
+
display: block;
|
|
82
|
+
|
|
83
|
+
-moz-appearance: none;
|
|
84
|
+
-webkit-appearance: none;
|
|
85
|
+
appearance: none;
|
|
86
|
+
|
|
87
|
+
/* Define color */
|
|
88
|
+
background-image: url('data:image/svg+xml;charset=US-ASCII,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%22292.4%22%20height%3D%22292.4%22%3E%3Cpath%20fill%3D%22%23007CB2%22%20d%3D%22M287%2069.4a17.6%2017.6%200%200%200-13-5.4H18.4c-5%200-9.3%201.8-12.9%205.4A17.6%2017.6%200%200%200%200%2082.2c0%205%201.8%209.3%205.4%2012.9l128%20127.9c3.6%203.6%207.8%205.4%2012.8%205.4s9.2-1.8%2012.8-5.4L287%2095c3.5-3.5%205.4-7.8%205.4-12.8%200-5-1.9-9.2-5.5-12.8z%22%2F%3E%3C%2Fsvg%3E');
|
|
89
|
+
background-repeat: no-repeat, repeat;
|
|
90
|
+
/* arrow icon position (1em from the right, 50% vertical) , then gradient position*/
|
|
91
|
+
background-position: right 0.5em top 50%, 0 0;
|
|
92
|
+
/* icon size, then gradient */
|
|
93
|
+
background-size: 0.65em auto, 100%;
|
|
94
|
+
|
|
95
|
+
max-width: 100%; /* useful when width is set to anything other than 100% */
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
.gradient {
|
|
99
|
+
/* Define color */
|
|
100
|
+
background-image: url('data:image/svg+xml;charset=US-ASCII,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%22292.4%22%20height%3D%22292.4%22%3E%3Cpath%20fill%3D%22%23007CB2%22%20d%3D%22M287%2069.4a17.6%2017.6%200%200%200-13-5.4H18.4c-5%200-9.3%201.8-12.9%205.4A17.6%2017.6%200%200%200%200%2082.2c0%205%201.8%209.3%205.4%2012.9l128%20127.9c3.6%203.6%207.8%205.4%2012.8%205.4s9.2-1.8%2012.8-5.4L287%2095c3.5-3.5%205.4-7.8%205.4-12.8%200-5-1.9-9.2-5.5-12.8z%22%2F%3E%3C%2Fsvg%3E'),
|
|
101
|
+
linear-gradient(
|
|
102
|
+
to bottom,
|
|
103
|
+
var(--my-background-gradient-color),
|
|
104
|
+
var(--my-background-color)
|
|
105
|
+
);
|
|
106
|
+
background-color: var(--my-background-color);
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
/* Hide arrow icon in IE browsers */
|
|
110
|
+
.select-css::-ms-expand {
|
|
111
|
+
display: none;
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
/* Focus style */
|
|
115
|
+
.select-css:focus {
|
|
116
|
+
border-color: var(--my-border-color-focus);
|
|
117
|
+
/* It'd be nice to use -webkit-focus-ring-color here but it doesn't work on box-shadow */
|
|
118
|
+
box-shadow: 0 0 1px 3px rgba(59, 153, 252, 0.7);
|
|
119
|
+
box-shadow: 0 0 0 3px -moz-mac-focusring;
|
|
120
|
+
color: #222;
|
|
121
|
+
outline: none;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
.error .select-css {
|
|
125
|
+
background-image: url('data:image/svg+xml;charset=US-ASCII,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%22292.4%22%20height%3D%22292.4%22%3E%3Cpath%20fill%3D%22graytext%22%20d%3D%22M287%2069.4a17.6%2017.6%200%200%200-13-5.4H18.4c-5%200-9.3%201.8-12.9%205.4A17.6%2017.6%200%200%200%200%2082.2c0%205%201.8%209.3%205.4%2012.9l128%20127.9c3.6%203.6%207.8%205.4%2012.8%205.4s9.2-1.8%2012.8-5.4L287%2095c3.5-3.5%205.4-7.8%205.4-12.8%200-5-1.9-9.2-5.5-12.8z%22%2F%3E%3C%2Fsvg%3E');
|
|
126
|
+
/* repeat instructions because of setted background in shared-styles */
|
|
127
|
+
background-repeat: no-repeat, repeat;
|
|
128
|
+
/* arrow icon position (1em from the right, 50% vertical) , then gradient position*/
|
|
129
|
+
background-position: right 0.5em top 50%, 0 0;
|
|
130
|
+
/* icon size, then gradient */
|
|
131
|
+
background-size: 0.65em auto, 100%;
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
.error .gradient {
|
|
135
|
+
background-image: url('data:image/svg+xml;charset=US-ASCII,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%22292.4%22%20height%3D%22292.4%22%3E%3Cpath%20fill%3D%22graytext%22%20d%3D%22M287%2069.4a17.6%2017.6%200%200%200-13-5.4H18.4c-5%200-9.3%201.8-12.9%205.4A17.6%2017.6%200%200%200%200%2082.2c0%205%201.8%209.3%205.4%2012.9l128%20127.9c3.6%203.6%207.8%205.4%2012.8%205.4s9.2-1.8%2012.8-5.4L287%2095c3.5-3.5%205.4-7.8%205.4-12.8%200-5-1.9-9.2-5.5-12.8z%22%2F%3E%3C%2Fsvg%3E'),
|
|
136
|
+
linear-gradient(
|
|
137
|
+
to bottom,
|
|
138
|
+
var(--my-background-gradient-color) 10%,
|
|
139
|
+
#f5979b 100%
|
|
140
|
+
);
|
|
141
|
+
/* repeat instructions because of setted background in shared-styles */
|
|
142
|
+
background-repeat: no-repeat, repeat;
|
|
143
|
+
/* arrow icon position (1em from the right, 50% vertical) , then gradient position*/
|
|
144
|
+
background-position: right 0.5em top 50%, 0 0;
|
|
145
|
+
/* icon size, then gradient */
|
|
146
|
+
background-size: 0.65em auto, 100%;
|
|
147
|
+
background-color: var(--my-error-background-color);
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
/* Set options to normal weight */
|
|
151
|
+
.select-css option {
|
|
152
|
+
font-weight: normal;
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
/* Disabled styles */
|
|
156
|
+
.select-css:disabled,
|
|
157
|
+
.select-css[aria-disabled='true'] {
|
|
158
|
+
background-image: url('data:image/svg+xml;charset=US-ASCII,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%22292.4%22%20height%3D%22292.4%22%3E%3Cpath%20fill%3D%22graytext%22%20d%3D%22M287%2069.4a17.6%2017.6%200%200%200-13-5.4H18.4c-5%200-9.3%201.8-12.9%205.4A17.6%2017.6%200%200%200%200%2082.2c0%205%201.8%209.3%205.4%2012.9l128%20127.9c3.6%203.6%207.8%205.4%2012.8%205.4s9.2-1.8%2012.8-5.4L287%2095c3.5-3.5%205.4-7.8%205.4-12.8%200-5-1.9-9.2-5.5-12.8z%22%2F%3E%3C%2Fsvg%3E');
|
|
159
|
+
/* repeat instructions because of setted background in shared-styles */
|
|
160
|
+
background-repeat: no-repeat, repeat;
|
|
161
|
+
/* arrow icon position (1em from the right, 50% vertical) , then gradient position*/
|
|
162
|
+
background-position: right 0.5em top 50%, 0 0;
|
|
163
|
+
/* icon size, then gradient */
|
|
164
|
+
background-size: 0.65em auto, 100%;
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
.gradient:disabled,
|
|
168
|
+
.gradient[aria-disabled='true'] {
|
|
169
|
+
background-image: url('data:image/svg+xml;charset=US-ASCII,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%22292.4%22%20height%3D%22292.4%22%3E%3Cpath%20fill%3D%22graytext%22%20d%3D%22M287%2069.4a17.6%2017.6%200%200%200-13-5.4H18.4c-5%200-9.3%201.8-12.9%205.4A17.6%2017.6%200%200%200%200%2082.2c0%205%201.8%209.3%205.4%2012.9l128%20127.9c3.6%203.6%207.8%205.4%2012.8%205.4s9.2-1.8%2012.8-5.4L287%2095c3.5-3.5%205.4-7.8%205.4-12.8%200-5-1.9-9.2-5.5-12.8z%22%2F%3E%3C%2Fsvg%3E'),
|
|
170
|
+
linear-gradient(to bottom, #ebebeb 0%, #999 100%);
|
|
171
|
+
/* repeat instructions because of setted background in shared-styles */
|
|
172
|
+
background-repeat: no-repeat, repeat;
|
|
173
|
+
/* arrow icon position (1em from the right, 50% vertical) , then gradient position*/
|
|
174
|
+
background-position: right 0.5em top 50%, 0 0;
|
|
175
|
+
/* icon size, then gradient */
|
|
176
|
+
background-size: 0.65em auto, 100%;
|
|
177
|
+
}
|
|
178
|
+
`,
|
|
179
|
+
];
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
static get properties() {
|
|
183
|
+
return {
|
|
184
|
+
icon: { type: String },
|
|
185
|
+
values: { type: Array },
|
|
186
|
+
};
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
constructor() {
|
|
190
|
+
super();
|
|
191
|
+
this._inputType = INPUT_TYPE_SELECT;
|
|
192
|
+
this.icon = 'toggleCollapse';
|
|
193
|
+
this.values = [];
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
render() {
|
|
197
|
+
return html`
|
|
198
|
+
<label for="${this.id}Select">${this.label}</label>
|
|
199
|
+
<div class="input ${classMap({ error: this.errorMsg.length > 0 })}">
|
|
200
|
+
<squi-icon
|
|
201
|
+
icon="toggleCollapse"
|
|
202
|
+
@click="${this._onIconClick}"
|
|
203
|
+
></squi-icon>
|
|
204
|
+
<select
|
|
205
|
+
id="${this.id}Input"
|
|
206
|
+
class="select-css input-style ${this.gradient ? 'gradient' : ''}"
|
|
207
|
+
?disabled="${this.disabled}"
|
|
208
|
+
@change="${this._onChange}"
|
|
209
|
+
@keyup="${this._onKeyUp}"
|
|
210
|
+
@blur="${this._onBlur}"
|
|
211
|
+
>
|
|
212
|
+
${this.values.map(
|
|
213
|
+
val => html`
|
|
214
|
+
<option
|
|
215
|
+
value="${val.value}"
|
|
216
|
+
?selected=${
|
|
217
|
+
// eslint-disable-next-line eqeqeq
|
|
218
|
+
this.value == val.value
|
|
219
|
+
}
|
|
220
|
+
>
|
|
221
|
+
${val.name}
|
|
222
|
+
</option>
|
|
223
|
+
`
|
|
224
|
+
)}
|
|
225
|
+
</select>
|
|
226
|
+
<!-- Sollte erst Clientseitig im Input validiert werden. Meldung verschwindet erst beim Submit nicht mehr zeitgemäß-->
|
|
227
|
+
${this.errorMsg.length > 0
|
|
228
|
+
? html`<span class="error-msg">${this.errorMsg}</span>`
|
|
229
|
+
: ''}
|
|
230
|
+
</div>
|
|
231
|
+
`;
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
firstUpdated() {
|
|
235
|
+
// Save input reference for performance (bind html element to class property)
|
|
236
|
+
this._input = this.shadowRoot.querySelector('select');
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
_onKeyUp(event) {
|
|
240
|
+
// set value (tbd überdenken)
|
|
241
|
+
this.value = this._input.value;
|
|
242
|
+
|
|
243
|
+
// If Enter key pressed, fire 'enter-pressed'
|
|
244
|
+
// eslint-disable-next-line eqeqeq
|
|
245
|
+
if (event.keyCode == 13) {
|
|
246
|
+
this.dispatchEvent(
|
|
247
|
+
new CustomEvent('enter-pressed', {
|
|
248
|
+
detail: {
|
|
249
|
+
value: this._input.value,
|
|
250
|
+
},
|
|
251
|
+
composed: true,
|
|
252
|
+
bubbles: true,
|
|
253
|
+
})
|
|
254
|
+
);
|
|
255
|
+
event.preventDefault();
|
|
256
|
+
} else {
|
|
257
|
+
// If any other key, fire 'key-pressed'
|
|
258
|
+
this.dispatchEvent(
|
|
259
|
+
new CustomEvent('key-pressed', {
|
|
260
|
+
detail: {
|
|
261
|
+
value: this._input.value,
|
|
262
|
+
},
|
|
263
|
+
composed: true,
|
|
264
|
+
bubbles: true,
|
|
265
|
+
})
|
|
266
|
+
);
|
|
267
|
+
}
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
_onChange() {
|
|
271
|
+
this.value = this._input.value;
|
|
272
|
+
// this.errorMsg = ''; do not change public attribute inside component => progress, handle with event handler at the moment
|
|
273
|
+
this.dispatchEvent(
|
|
274
|
+
new CustomEvent('change-value', {
|
|
275
|
+
detail: {
|
|
276
|
+
value: this._input.value,
|
|
277
|
+
name: this.valueName,
|
|
278
|
+
},
|
|
279
|
+
composed: true,
|
|
280
|
+
bubbles: true,
|
|
281
|
+
})
|
|
282
|
+
);
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
_onBlur() {
|
|
286
|
+
this.dispatchEvent(
|
|
287
|
+
new CustomEvent('focus-lost', {
|
|
288
|
+
detail: {
|
|
289
|
+
value: this._input.value,
|
|
290
|
+
},
|
|
291
|
+
composed: true,
|
|
292
|
+
bubbles: true,
|
|
293
|
+
})
|
|
294
|
+
);
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
_onIconClick() {
|
|
298
|
+
this.dispatchEvent(
|
|
299
|
+
new CustomEvent('icon-clicked', {
|
|
300
|
+
detail: {
|
|
301
|
+
value: this._input.value,
|
|
302
|
+
},
|
|
303
|
+
composed: true,
|
|
304
|
+
bubbles: true,
|
|
305
|
+
})
|
|
306
|
+
);
|
|
307
|
+
}
|
|
308
|
+
}
|
|
@@ -1,32 +0,0 @@
|
|
|
1
|
-
import { html, css, LitElement } from 'lit';
|
|
2
|
-
|
|
3
|
-
export class TestEl extends LitElement {
|
|
4
|
-
static get styles() {
|
|
5
|
-
return css`
|
|
6
|
-
:host {
|
|
7
|
-
display: block;
|
|
8
|
-
padding: 25px;
|
|
9
|
-
color: var(--pd-forms-text-color, #000);
|
|
10
|
-
}
|
|
11
|
-
`;
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
static get properties() {
|
|
15
|
-
return {
|
|
16
|
-
title: { type: String },
|
|
17
|
-
counter: { type: Number },
|
|
18
|
-
};
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
constructor() {
|
|
22
|
-
super();
|
|
23
|
-
this.title = 'Hey there';
|
|
24
|
-
this.counter = 5;
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
render() {
|
|
28
|
-
return html`
|
|
29
|
-
<h2>Das ist wirklich gut</h2>
|
|
30
|
-
`;
|
|
31
|
-
}
|
|
32
|
-
}
|
package/test-el.js
DELETED
|
@@ -1,34 +0,0 @@
|
|
|
1
|
-
import { html, css, LitElement } from 'lit';
|
|
2
|
-
|
|
3
|
-
export class TestEl extends LitElement {
|
|
4
|
-
static get styles() {
|
|
5
|
-
return css`
|
|
6
|
-
:host {
|
|
7
|
-
display: block;
|
|
8
|
-
padding: 25px;
|
|
9
|
-
color: var(--pd-forms-text-color, #000);
|
|
10
|
-
}
|
|
11
|
-
`;
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
static get properties() {
|
|
15
|
-
return {
|
|
16
|
-
title: { type: String },
|
|
17
|
-
counter: { type: Number },
|
|
18
|
-
};
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
constructor() {
|
|
22
|
-
super();
|
|
23
|
-
this.title = 'Hey there';
|
|
24
|
-
this.counter = 5;
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
render() {
|
|
28
|
-
return html`
|
|
29
|
-
<h2>Das ist wirklich gut</h2>
|
|
30
|
-
`;
|
|
31
|
-
}
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
window.customElements.define('test-el', TestEl);
|