@progressive-development/pd-forms 0.0.5 → 0.0.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,290 @@
1
+ import { html, css } from "lit";
2
+ import { classMap } from 'lit/directives/class-map.js';
3
+
4
+ // import {GestureEventListeners} from '@polymer/polymer/lib/mixins/gesture-event-listeners.js';
5
+
6
+ import '@progressive-development/pd-icon';
7
+ import { SquiBaseUIInput, INPUT_TYPE_CHECK } from "./squi-base-ui-input.js";
8
+
9
+
10
+ // import { installMediaQueryWatcher } from 'pwa-helpers/media-query.js';
11
+
12
+ export class SquiCheckbox extends SquiBaseUIInput {
13
+ static get properties() {
14
+ return {
15
+ hasInner: { type: Boolean },
16
+ // _panX: {type: Number},
17
+ // _panEnd: {type: Boolean},
18
+ isSwitch: { type: Boolean }
19
+ };
20
+ }
21
+
22
+ constructor() {
23
+ super();
24
+ this._inputType = INPUT_TYPE_CHECK;
25
+ // this._panEnd = false;
26
+ // this._panX = 0;
27
+ }
28
+
29
+ static get styles() {
30
+ return [
31
+ // SharedInputStyles,
32
+ css`
33
+ :host {
34
+
35
+ --my-icon-fill: var(--app-primary-color, #177E89);
36
+ --my-icon-active-fill: var(--app-primary-color, #177E89);
37
+ --my-icon-bg-color: var(--app-primary-color, #fefefe) ;
38
+ --my-icon-bg-active-color: var(--app-primary-color, #fefefe);
39
+
40
+ --my-bg-color: var(--squi-bg-color, #177E89);
41
+ --my-txt-color: var(--squi-bg-color, black);
42
+
43
+ --my-font: var(--squi-font-2, Montserrat);
44
+
45
+ /* ref copy from shared styles...*/
46
+ --my-error-color: var(--squi-error-color, #d6242d);
47
+ --my-error-background-color: var(--squi-error-background-color, #f6d4d4a1);
48
+ --my-border-radius: var(--squi-border-radius, 0rem);
49
+
50
+
51
+
52
+ /* TODO vars used in squi-icon */
53
+ --squi-checkbox-checked-color: var(--my-primary);
54
+ --squi-checkbox-unchecked-color: var(--my-ligth);
55
+ --squi-checkbox-bg: var(--my-dark);
56
+ --squi-checkbox-unchecked-bg: var(--my-dark);
57
+ --squi-checkbox-label-color: var(--my-primary);
58
+
59
+ --squi-checkbox-label-disabled-color: var(--app-copy-color, #303030);
60
+
61
+ /* Checkbox squi-icon */
62
+ --squi-icon-fill: var(--my-icon-bg-color);
63
+ --squi-icon-bg: var(--my-icon-fill);
64
+ --squi-icon-fill-active: var(--my-icon-bg-active-color);
65
+ --squi-icon-bg-active: var(--my-icon-active-fill);
66
+
67
+ display: inline-block;
68
+ font-size: .8rem;
69
+ }
70
+ /* Switch squi-icon */
71
+ :host([isSwitch]) {
72
+ --squi-icon-fill: var(--my-icon-fill);
73
+ --squi-icon-bg: var(--my-icon-bg-color);
74
+ --squi-icon-fill-active: var(--my-icon-active-fill);
75
+ --squi-icon-bg-active: var(--my-icon-bg-active-color);
76
+ }
77
+ div {
78
+ display: flex;
79
+ align-items: center;
80
+ cursor: pointer;
81
+ }
82
+ div.disabled {
83
+ opacity: 0.5;
84
+ cursor: auto;
85
+ }
86
+ div.readonly {
87
+ cursor: auto;
88
+ }
89
+ .checkbox {
90
+ display: flex;
91
+ border-radius: 4px;
92
+ line-height: 0;
93
+ align-items: center;
94
+ justify-content: center;
95
+ }
96
+ .checkbox squi-icon {
97
+ margin: .25rem;
98
+ }
99
+ .label {
100
+ margin-left: .5rem;
101
+ color: var(--my-txt-color);
102
+ font-family: var(--my-font);
103
+ }
104
+ .disabled .label {
105
+ color: var(--squi-checkbox-label-disabled-color, #6e6c6c);
106
+ }
107
+ .readonly .label {
108
+ color: var(--app-copy-color, var(--squi-checkbox-label-color, #303030));
109
+ }
110
+ /* Switch styles */
111
+ .switch {
112
+ height: var(--my-input-height); /* noch ohne effekt?*/
113
+ position: relative;
114
+ outline: 0;
115
+ -webkit-user-select: none;
116
+ -moz-user-select: none;
117
+ -ms-user-select: none;
118
+ user-select: none;
119
+ }
120
+ .switch-paddle {
121
+ display: inline-block;
122
+ vertical-align: baseline;
123
+ margin: 0;
124
+ position: relative;
125
+ min-width: 4rem;
126
+ max-width: 4rem;
127
+ height: 2rem;
128
+ border-radius: 0;
129
+ background: var(--my-bg-color);
130
+ font-weight: inherit;
131
+ color: inherit;
132
+ cursor: pointer;
133
+ }
134
+ .disabled .switch-paddle {
135
+ cursor: auto;
136
+ }
137
+ .readonly .switch-paddle {
138
+ cursor: auto;
139
+ max-width: 2rem;
140
+ min-width: 2rem;
141
+ background: none;
142
+
143
+ --squi-icon-bg: transparent;
144
+ --squi-icon-fill: var(--card-dark-red);
145
+ --squi-icon-fill-hover: var(--squi-icon-fill);
146
+ --squi-icon-fill-active: var(--card-medium-green);
147
+ }
148
+ .readonly .isChecked.switch-paddle squi-icon {
149
+ transform: translate3d(0, 0, 0);
150
+ left: 0.25rem;
151
+ }
152
+ .switch-paddle squi-icon {
153
+ position: absolute;
154
+ top: 0.25rem;
155
+ left: 0.25rem;
156
+ display: block;
157
+ width: 1.5rem;
158
+ height: 1.5rem;
159
+ -webkit-transform: translate3d(0, 0, 0);
160
+ transform: translate3d(0, 0, 0);
161
+ border-radius: 3px;
162
+ -webkit-transition: all 0.25s ease-out;
163
+ transition: all 0.25s ease-out;
164
+ content: '';
165
+ }
166
+ .isChecked.switch-paddle squi-icon {
167
+ left: 2.25rem;
168
+ }
169
+
170
+ /* Copy from SharedINputStyles, not used for select => ref, or exclude error styles and reuse oder something... */
171
+ .error-box {
172
+ display: block;
173
+ color: var(--my-error-color);
174
+ background: var(--my-error-background-color);
175
+ border: 1px solid var(--my-error-color);
176
+ border-radius: var(--my-border-radius);
177
+ }
178
+
179
+ /* Error Msg Div for input, select, area */
180
+ .error-msg {
181
+ padding:0.25rem;
182
+ white-space: nowrap;
183
+ font-size: .8rem;
184
+ max-width: var(--squi-input-width, 250px);
185
+ }
186
+
187
+ @media (min-width: 580px) {
188
+ :host {
189
+ font-size: 1rem;
190
+ }
191
+ }
192
+ `];
193
+ }
194
+
195
+ firstUpdated() {
196
+ this.hasInner = !!this.innerHTML.trim().length;
197
+ // installMediaQueryWatcher(`(min-width: 780px)`, (matches) => matches ? this : this._updateScale(1.5));
198
+ // const paddle = el.shadowRoot.querySelectorAll('.switch-paddle');
199
+ // this.isSwitch ? Gestures.addListener(this, 'track', this.handleTrack.bind(this)) : '';
200
+ }
201
+
202
+ render() {
203
+ const checked = (this.value === 'true');
204
+
205
+ // eslint-disable-next-line lit-a11y/click-events-have-key-events
206
+ return html`<div @click="${this.onClick}" class="${classMap({'disabled': this.disabled, 'switch': this.isSwitch, 'readonly': this.readonly})}">
207
+ <a href="#" @click="${this.linkClick}" @keypress="${this.onKeyPress}"
208
+ class="${classMap({'switch-paddle': this.isSwitch, 'checkbox': !this.isSwitch, 'isChecked': checked, 'isUnchecked': !checked})}">
209
+ <squi-icon icon="checkBox" class="${classMap({'switch': this.isSwitch, 'checkBox': !this.isSwitch})}" ?activeIcon="${checked}"></squi-icon>
210
+ </a>
211
+ ${this.hasInner
212
+ ? html`<span class="label">
213
+ <slot></slot>
214
+ </span>`
215
+ : ""}
216
+ </div>
217
+ ${this.errorMsg.length > 0 ? html`
218
+ <div class="error-box error">
219
+ <span class="error-msg">${this.errorMsg}</span>
220
+ </div>
221
+ ` : ''}
222
+ `;
223
+ }
224
+
225
+ /*
226
+ update(changedProperties) {
227
+ //let { deltaX = 0, isFinal = false } = this._panX;
228
+ let isFinal = this._panEnd;
229
+ let deltaX = this._panX || 0;
230
+ //console.log(this._panData);
231
+
232
+ // Guard against an infinite loop by looking for index.
233
+ if (isFinal) {
234
+ console.log('deltaX', deltaX);
235
+ // TODO 250 half screen size?
236
+ if ( deltaX > 100) {
237
+ this.onClick(true);
238
+ } else if(deltaX < -100){
239
+ this.onClick(false);
240
+ }
241
+ this._panEnd = false;
242
+ }
243
+ // We don't want the latent deltaX when releasing a pan.
244
+ deltaX = (isFinal ? 0 : deltaX);
245
+
246
+ super.update(changedProperties);
247
+ }
248
+
249
+ handleTrack(e) {
250
+ switch(e.detail.state) {
251
+ case 'start':
252
+ //this.message = 'Tracking started!';
253
+ break;
254
+ case 'track':
255
+ //this.message = 'Tracking in progress... ' + e.detail.x + ', ' + e.detail.y;
256
+ break;
257
+ case 'end':
258
+ this._panX = e.detail.dx;
259
+ this._panEnd = true;
260
+ break;
261
+ }
262
+ }
263
+ */
264
+ onClick() {
265
+ if (this.disabled || this.readonly) {
266
+ return;
267
+ }
268
+ const checked = (this.value === 'true');
269
+ this.value = checked ? 'false' : 'true';
270
+ this.dispatchEvent(
271
+ new CustomEvent("checkbox-changed", {
272
+ bubbles: true,
273
+ composed: true,
274
+ detail: {check: !checked, name: this.valueName},
275
+ })
276
+ );
277
+ }
278
+
279
+ onKeyPress(e) {
280
+ e.preventDefault();
281
+ if (e.keyCode === 32 || e.code === "Space") {
282
+ this.onClick();
283
+ }
284
+ }
285
+
286
+ // eslint-disable-next-line class-methods-use-this
287
+ linkClick(e) {
288
+ e.preventDefault();
289
+ }
290
+ }
@@ -0,0 +1,51 @@
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
+
17
+ /**
18
+ * An example element.
19
+ *
20
+ * @slot - This element has a slot
21
+ * @csspart button - The button
22
+ */
23
+ export class SquiFormContainer extends LitElement {
24
+
25
+ static get styles() {
26
+ return css`
27
+ :host {
28
+ display: flex;
29
+ flex-direction: column;
30
+ align-items: left;
31
+ gap: 20px;
32
+ }
33
+
34
+ `;
35
+ }
36
+
37
+ static get properties() {
38
+ return {
39
+ // not needed at the moment
40
+ };
41
+ }
42
+
43
+ render() {
44
+ return html`
45
+ <form>
46
+ <slot></slot>
47
+ </form>
48
+ `;
49
+ }
50
+
51
+ }
@@ -0,0 +1,103 @@
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
+
17
+ /**
18
+ * An example element.
19
+ *
20
+ * @slot - This element has a slot
21
+ * @csspart button - The button
22
+ */
23
+ export class SquiFormRow extends LitElement {
24
+
25
+ static get styles() {
26
+ return css`
27
+ :host {
28
+
29
+ /* Define size for row, depends on media queries */
30
+ --my-row-width: 800px;
31
+ --my-gap: 20px;
32
+ display: flex;
33
+ flex: 1 1 100%;
34
+ /*margin: 0 0 .5rem 0;*/
35
+ box-sizing: border-box;
36
+ min-width: var(--my-row-width);
37
+ max-width: 100%;
38
+ gap: var(--my-gap);
39
+ align-items: flex-start;
40
+
41
+ padding-top: var(--row-padding-top, 0px);
42
+ }
43
+
44
+ ::slotted(.quarter1) {
45
+ --squi-input-width: calc(var(--my-row-width) * 0.25 - (var(--my-gap) * 0.75));
46
+
47
+ }
48
+
49
+ ::slotted(.quarter2) {
50
+ --squi-input-width: calc((var(--my-row-width) * 0.5) - (var(--my-gap) / 2));
51
+
52
+ }
53
+
54
+ ::slotted(.quarter3) {
55
+ --squi-input-width: calc(var(--my-row-width) * 0.75 - (var(--my-gap) * 0.25));
56
+ }
57
+ /* Area is longer? Scrollbar? */
58
+ ::slotted(.quarter3-area) {
59
+ --squi-input-width: calc((var(--my-row-width) - 22px) * 0.75 - (var(--my-gap) * 0.25));
60
+ }
61
+
62
+ ::slotted(.quarter4) {
63
+ --squi-input-width: var(--my-row-width);
64
+ }
65
+ /* Area is longer? Scrollbar? */
66
+ ::slotted(.quarter4-area) {
67
+ --squi-input-width: calc(var(--my-row-width) - 22px);
68
+ }
69
+
70
+ @media (max-width: 930px) {
71
+ :host {
72
+ --my-row-width: 600px;
73
+ }
74
+ }
75
+ @media (max-width: 650px) {
76
+ :host {
77
+ --my-row-width: 400px;
78
+ --my-gap: 10px;
79
+ }
80
+ }
81
+ @media (max-width: 450px) {
82
+ :host {
83
+ --my-row-width: 300px;
84
+ --my-gap: 8px;
85
+ }
86
+ }
87
+
88
+ `;
89
+ }
90
+
91
+ static get properties() {
92
+ return {
93
+ // not needed at the moment
94
+ };
95
+ }
96
+
97
+ render() {
98
+ return html`
99
+ <slot></slot>
100
+ `;
101
+ }
102
+
103
+ }
@@ -0,0 +1,185 @@
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_AREA } from './squi-base-ui-input.js';
6
+
7
+
8
+ import '@progressive-development/pd-icon/pd-icon.js';
9
+
10
+ // https://github.com/Victor-Bernabe/lit-input
11
+ // https://levelup.gitconnected.com/build-a-material-like-input-web-component-using-litelement-20e9e0d203b6
12
+ /**
13
+ * Web component to input text implemented with LitElement.
14
+ *
15
+ * ### Styling
16
+ *
17
+ * All custom properties should start with `--squi-input`.
18
+ *
19
+ * Font and icon size will scale automatically with `squi-input`'s height.
20
+ *
21
+ * Custom property | Description | Default
22
+ * ----------------|-------------|--------
23
+ * `--squi-input-width` | Width | `250px`
24
+ * `--my-input-height` | Height | `30px`
25
+ * `--squi-input-border` | Border | `1px solid black`
26
+ * `--squi-input-border-focus` | Border when focused | `1px solid #4d90fe`
27
+ * `--squi-input-background-color` | Background color | `white`
28
+ * `--squi-input-font-size` | Font size | `calc(var(--my-input-height) / 1.8)`
29
+ * `--squi-input-text-color` | Text color | `inherit`
30
+ * `--squi-input-placeholder-color` | Placeholder text color | `#a0a0a0`
31
+ * `--squi-input-icon-fill-color` | Icon fill color | `currentcolor`
32
+ * `--squi-input-icon-stroke-color` | Icon stroke color | `none`
33
+ *
34
+ * ### Icon and text alignment
35
+ *
36
+ * The icon inside `squi-input` is hidden by default. To show it, set the attribute `icon-right` or `icon-left`.
37
+ *
38
+ * <squi-input icon-left></squi-input>
39
+ * <squi-input icon-right></squi-input>
40
+ *
41
+ * <squi-input icon-left .icon="${'hardware:headset'}"></squi-input>
42
+ *
43
+ * Text can be left or right aligned. Default is left alignment.
44
+ *
45
+ * <squi-input text-right></squi-input>
46
+ * <squi-input text-left></squi-input>
47
+ */
48
+ export class SquiInputArea extends SquiBaseUIInput {
49
+
50
+ /**
51
+ * Fired when `squi-input-area` has focus and the user press `Enter` key.
52
+ * @event enter-pressed
53
+ */
54
+
55
+ /**
56
+ * Fired when `squi-input-area` has focus and the user press any key except `Enter`.
57
+ * @event key-pressed
58
+ */
59
+
60
+ /**
61
+ * Fire when the `squi-input-area` loses focus.
62
+ * @event focus-lost
63
+ */
64
+
65
+ /**
66
+ * Fire when the icon inside `squi-input-area` is clicked.
67
+ * @event icon-clicked
68
+ */
69
+
70
+ static get styles() {
71
+ return [
72
+ SharedInputStyles,
73
+ css`
74
+ /* 10 py scroll border rigth? => overwrite*/
75
+ .input-style {
76
+ width: var(--squi-input-width, 240px);
77
+ }
78
+
79
+ `];
80
+ }
81
+
82
+ static get properties() {
83
+ return {
84
+ /** Placeholder for `squi-input` initial text. */
85
+ placeHolder: { type: String },
86
+ /**
87
+ * Icon to be shown inside `squi-input`.
88
+ */
89
+ icon: { type: String },
90
+ name: { type: String },
91
+ rows: { type: Number },
92
+ cols: { type: Number },
93
+ minlength: { type: String },
94
+ maxlength: { type: String } // max length for field
95
+ };
96
+ }
97
+
98
+ constructor() {
99
+ super();
100
+ this._inputType = INPUT_TYPE_AREA;
101
+ this.placeHolder = '';
102
+ this.icon = 'toggleCollapse';
103
+
104
+ this.maxlength = 500;
105
+ this.name = '';
106
+ this.rows = 2;
107
+ this.value = '';
108
+ }
109
+
110
+ render() {
111
+ return html`
112
+ <label for="${this.id}InputArea">${this.label}</label>
113
+ <div class="input ${classMap({'error': this.errorMsg.length > 0})}">
114
+ <squi-icon icon="toggleCollapse"
115
+ @click="${this._onIconClick}"></squi-icon>
116
+ <textarea
117
+ id="${this.id}InputArea"
118
+ class="input-style ${this.gradient ? 'gradient' : ''}"
119
+ rows="${this.rows}"
120
+ cols="${this.cols}"
121
+ placeholder="${this.placeHolder}"
122
+ ?disabled="${this.disabled}"
123
+ ?readonly="${this.readonly}"
124
+ @keyup="${this._onKeyUp}"
125
+ @blur="${this._onBlur}">${this.value}</textarea>
126
+ <!-- Sollte erst Clientseitig im Input validiert werden. Meldung verschwindet erst beim Submit nicht mehr zeitgemäß-->
127
+ ${this.errorMsg.length > 0 ? html`<span class="error-msg">${this.errorMsg}</span>` : ''}
128
+ </div>
129
+ `;
130
+ }
131
+
132
+ firstUpdated() {
133
+ // Save input reference for performance (bind html element to class property)
134
+ this._input = this.shadowRoot.querySelector('textarea');
135
+ }
136
+
137
+ _onKeyUp(event) {
138
+
139
+ // set value (tbd überdenken)
140
+ this.value = this._input.value;
141
+
142
+ // If Enter key pressed, fire 'enter-pressed'
143
+ if(event.keyCode === 13) {
144
+ this.dispatchEvent(new CustomEvent('enter-pressed', {
145
+ detail: {
146
+ value: this._input.value
147
+ },
148
+ composed: true,
149
+ bubbles: true
150
+ }));
151
+ event.preventDefault();
152
+ } else {
153
+ // If any other key, fire 'key-pressed'
154
+ // this.errorMsg = ''; change with handler now...
155
+ this.dispatchEvent(new CustomEvent('key-pressed', {
156
+ detail: {
157
+ value: this._input.value,
158
+ name: this.valueName
159
+ },
160
+ composed: true,
161
+ bubbles: true
162
+ }));
163
+ }
164
+ }
165
+
166
+ _onBlur() {
167
+ this.dispatchEvent(new CustomEvent('focus-lost', {
168
+ detail: {
169
+ value: this._input.value
170
+ },
171
+ composed: true,
172
+ bubbles: true
173
+ }));
174
+ }
175
+
176
+ _onIconClick() {
177
+ this.dispatchEvent(new CustomEvent('icon-clicked', {
178
+ detail: {
179
+ value: this._input.value
180
+ },
181
+ composed: true,
182
+ bubbles: true
183
+ }));
184
+ }
185
+ }