@unicef-polymer/etools-form-builder 1.0.2 → 2.0.0-rc.3

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.
Files changed (55) hide show
  1. package/dist/form-attachments-popup/form-attachments-popup.d.ts +10 -2
  2. package/dist/form-attachments-popup/form-attachments-popup.js +5 -0
  3. package/dist/form-attachments-popup/form-attachments-popup.tpl.d.ts +0 -5
  4. package/dist/form-attachments-popup/form-attachments-popup.tpl.js +0 -5
  5. package/dist/form-fields/abstract-field-base.class.d.ts +28 -0
  6. package/dist/form-fields/{base-field.js → abstract-field-base.class.js} +64 -38
  7. package/dist/form-fields/custom-elements.define.js +17 -5
  8. package/dist/form-fields/field-renderer-component.d.ts +20 -0
  9. package/dist/form-fields/field-renderer-component.js +245 -0
  10. package/dist/form-fields/index.d.ts +9 -5
  11. package/dist/form-fields/index.js +9 -5
  12. package/dist/form-fields/repeatable-fields/repeatable-attachment-field.d.ts +17 -0
  13. package/dist/form-fields/repeatable-fields/repeatable-attachment-field.js +198 -0
  14. package/dist/form-fields/repeatable-fields/repeatable-base-field.d.ts +20 -0
  15. package/dist/form-fields/repeatable-fields/repeatable-base-field.js +123 -0
  16. package/dist/form-fields/repeatable-fields/repeatable-number-field.d.ts +10 -0
  17. package/dist/form-fields/repeatable-fields/repeatable-number-field.js +56 -0
  18. package/dist/form-fields/repeatable-fields/repeatable-scale-field.d.ts +15 -0
  19. package/dist/form-fields/repeatable-fields/repeatable-scale-field.js +104 -0
  20. package/dist/form-fields/repeatable-fields/repeatable-text-field.d.ts +8 -0
  21. package/dist/form-fields/repeatable-fields/repeatable-text-field.js +43 -0
  22. package/dist/form-fields/single-fields/attachment-field.d.ts +16 -0
  23. package/dist/form-fields/single-fields/attachment-field.js +87 -0
  24. package/dist/form-fields/single-fields/base-field.d.ts +11 -0
  25. package/dist/form-fields/single-fields/base-field.js +57 -0
  26. package/dist/form-fields/single-fields/boolean-field.d.ts +8 -0
  27. package/dist/form-fields/single-fields/boolean-field.js +39 -0
  28. package/dist/form-fields/{number-field.d.ts → single-fields/number-field.d.ts} +1 -0
  29. package/dist/form-fields/{number-field.js → single-fields/number-field.js} +15 -2
  30. package/dist/form-fields/{scale-field.d.ts → single-fields/scale-field.d.ts} +4 -2
  31. package/dist/form-fields/{scale-field.js → single-fields/scale-field.js} +14 -2
  32. package/dist/form-fields/{text-field.d.ts → single-fields/text-field.d.ts} +0 -0
  33. package/dist/form-fields/{text-field.js → single-fields/text-field.js} +6 -1
  34. package/dist/form-groups/form-abstract-group.d.ts +12 -12
  35. package/dist/form-groups/form-abstract-group.js +133 -110
  36. package/dist/form-groups/form-card.d.ts +1 -0
  37. package/dist/form-groups/form-card.js +25 -0
  38. package/dist/form-groups/form-collapsed-card.d.ts +3 -1
  39. package/dist/form-groups/form-collapsed-card.js +24 -4
  40. package/dist/index.d.ts +1 -1
  41. package/dist/index.js +6 -1
  42. package/dist/lib/additional-components/confirmation-dialog.d.ts +16 -0
  43. package/dist/lib/additional-components/confirmation-dialog.js +61 -0
  44. package/dist/lib/additional-components/etools-fb-card.js +8 -1
  45. package/dist/lib/styles/attachments.styles.js +5 -2
  46. package/dist/lib/styles/form-builder-card.styles.js +8 -3
  47. package/dist/lib/styles/page-layout-styles.js +1 -1
  48. package/dist/lib/types/form-builder.interfaces.d.ts +2 -2
  49. package/dist/lib/types/form-builder.types.d.ts +8 -2
  50. package/dist/lib/utils/validations.helper.d.ts +3 -3
  51. package/dist/lib/utils/validations.helper.js +7 -7
  52. package/package.json +3 -2
  53. package/dist/form-fields/base-field.d.ts +0 -20
  54. package/dist/form-fields/wide-field.d.ts +0 -11
  55. package/dist/form-fields/wide-field.js +0 -51
@@ -0,0 +1,198 @@
1
+ import '@unicef-polymer/etools-upload/etools-upload';
2
+ import { RepeatableBaseField } from './repeatable-base-field';
3
+ import { AttachmentsHelper } from '../../form-attachments-popup';
4
+ import { html, css } from 'lit-element';
5
+ import { fireEvent } from '../../lib/utils/fire-custom-event';
6
+ import { SharedStyles } from '../../lib/styles/shared-styles';
7
+ import { AttachmentsStyles } from '../../lib/styles/attachments.styles';
8
+ export class RepeatableAttachmentField extends RepeatableBaseField {
9
+ constructor() {
10
+ super(...arguments);
11
+ this.computedPath = [];
12
+ }
13
+ get uploadUrl() {
14
+ return AttachmentsHelper.uploadUrl;
15
+ }
16
+ get jwtLocalStorageKey() {
17
+ return AttachmentsHelper.jwtLocalStorageKey;
18
+ }
19
+ render() {
20
+ var _a;
21
+ const values = this.getValues();
22
+ return html `
23
+ <div class="finding-container">
24
+ <div class="question layout start"><slot>${this.questionTemplate()}</slot></div>
25
+ <div class="question-control layout vertical center-justified start">
26
+ ${values.map((value, index) => value
27
+ ? html `
28
+ <div class="layout horizontal file-container">
29
+ <!-- File name component -->
30
+ <div class="filename-container file-selector__filename">
31
+ <iron-icon class="file-icon" icon="attachment"></iron-icon>
32
+ <span class="filename" title="${value.filename}">${value.filename}</span>
33
+ </div>
34
+
35
+ <!-- Download Button -->
36
+ <paper-button
37
+ ?hidden="${!value.url}"
38
+ class="download-button file-selector__download"
39
+ @tap="${() => this.downloadFile(value)}"
40
+ >
41
+ <iron-icon icon="cloud-download" class="dw-icon"></iron-icon>
42
+ Download
43
+ </paper-button>
44
+
45
+ <!-- Delete Button -->
46
+ <paper-button
47
+ class="delete-button file-selector__delete"
48
+ ?hidden="${this.isReadonly}"
49
+ @tap="${() => this.removeControl(index)}"
50
+ >
51
+ Delete
52
+ </paper-button>
53
+ </div>
54
+ `
55
+ : '')}
56
+ <!-- Upload button -->
57
+ <etools-upload-multi
58
+ class="with-padding"
59
+ activate-offline
60
+ ?hidden="${this.isReadonly}"
61
+ @upload-finished="${({ detail }) => this.attachmentsUploaded(detail)}"
62
+ .endpointInfo="${{ endpoint: this.uploadUrl, extraInfo: { composedPath: this.computedPath } }}"
63
+ .jwtLocalStorageKey="${this.jwtLocalStorageKey}"
64
+ >
65
+ </etools-upload-multi>
66
+ <div ?hidden="${!this.isReadonly || ((_a = this.value) === null || _a === void 0 ? void 0 : _a.length)}">—</div>
67
+ </div>
68
+ </div>
69
+ `;
70
+ }
71
+ controlTemplate() {
72
+ return html ``;
73
+ }
74
+ customValidation() {
75
+ return null;
76
+ }
77
+ attachmentsUploaded({ success, error }) {
78
+ success === null || success === void 0 ? void 0 : success.forEach((file, index) => {
79
+ var _a, _b;
80
+ const newIndex = ((_b = Number((_a = this.editedValues) === null || _a === void 0 ? void 0 : _a.length)) !== null && _b !== void 0 ? _b : 0) + index;
81
+ if (this.isUploadedAttachment(file)) {
82
+ this.valueChanged({
83
+ url: file.file_link,
84
+ attachment: file.id,
85
+ filename: file.filename,
86
+ file_type: null
87
+ }, newIndex);
88
+ }
89
+ else if (this.isOfflineSavedAttachment(file)) {
90
+ this.valueChanged({
91
+ attachment: file.id,
92
+ filename: file.filename,
93
+ composedPath: [],
94
+ file_type: null
95
+ }, newIndex);
96
+ }
97
+ else {
98
+ console.warn('Missing fields in parsed attachment');
99
+ }
100
+ });
101
+ if (error && error.length) {
102
+ console.error(error);
103
+ fireEvent(this, 'toast', { text: 'Can not upload attachments. Please try again later' });
104
+ }
105
+ }
106
+ downloadFile(attachment) {
107
+ if (!(attachment === null || attachment === void 0 ? void 0 : attachment.url)) {
108
+ return;
109
+ }
110
+ const link = document.createElement('a');
111
+ link.target = '_blank';
112
+ link.href = attachment.url;
113
+ link.click();
114
+ window.URL.revokeObjectURL(attachment.url);
115
+ }
116
+ isUploadedAttachment(attachment) {
117
+ return (attachment.hasOwnProperty('filename') &&
118
+ attachment.hasOwnProperty('id') &&
119
+ attachment.hasOwnProperty('file_link') &&
120
+ !attachment.hasOwnProperty('unsynced'));
121
+ }
122
+ isOfflineSavedAttachment(attachment) {
123
+ return (attachment.hasOwnProperty('filename') && attachment.hasOwnProperty('id') && attachment.hasOwnProperty('unsynced'));
124
+ }
125
+ static get styles() {
126
+ // language=CSS
127
+ return [
128
+ ...RepeatableBaseField.styles,
129
+ SharedStyles,
130
+ AttachmentsStyles,
131
+ css `
132
+ .file-selector__type-dropdown {
133
+ flex-basis: 25%;
134
+ padding-left: 8px;
135
+ padding-right: 8px;
136
+ }
137
+
138
+ .file-selector__filename {
139
+ flex-basis: 35%;
140
+ }
141
+
142
+ .file-selector__download {
143
+ flex-basis: 10%;
144
+ }
145
+
146
+ .file-selector__delete {
147
+ flex-basis: 10%;
148
+ }
149
+
150
+ .file-selector-container.with-type-dropdown {
151
+ flex-wrap: nowrap;
152
+ }
153
+
154
+ .popup-container {
155
+ padding: 12px 12px 0;
156
+ }
157
+
158
+ .file-container {
159
+ padding: 8px 0;
160
+ }
161
+
162
+ @media (max-width: 380px) {
163
+ .file-selector-container.with-type-dropdown {
164
+ justify-content: center;
165
+ }
166
+
167
+ .file-selector-container.with-type-dropdown etools-dropdown.type-dropdown {
168
+ flex-basis: 90%;
169
+ }
170
+
171
+ .file-selector__filename {
172
+ flex-basis: 90%;
173
+ }
174
+
175
+ .file-selector__download {
176
+ flex-basis: 5%;
177
+ }
178
+
179
+ .file-selector__delete {
180
+ flex-basis: 5%;
181
+ }
182
+ }
183
+
184
+ @media (max-width: 600px) {
185
+ etools-dropdown {
186
+ padding: 0;
187
+ }
188
+
189
+ .file-selector-container.with-type-dropdown {
190
+ border-bottom: 1px solid lightgrey;
191
+ flex-wrap: wrap;
192
+ padding-bottom: 10px;
193
+ }
194
+ }
195
+ `
196
+ ];
197
+ }
198
+ }
@@ -0,0 +1,20 @@
1
+ import { CSSResultArray, TemplateResult } from 'lit-element';
2
+ import { AbstractFieldBaseClass } from '../abstract-field-base.class';
3
+ export declare abstract class RepeatableBaseField<T> extends AbstractFieldBaseClass<T[]> {
4
+ set errorMessage(messages: (string | null)[]);
5
+ get errorMessage(): (string | null)[];
6
+ protected _errorMessage: (string | null)[];
7
+ protected editedValues: (T | null)[] | null;
8
+ protected render(): TemplateResult;
9
+ protected questionTemplate(): TemplateResult;
10
+ protected valueChanged(newValue: T, index: number): void;
11
+ protected setValue(value: (T | null)[]): void;
12
+ protected validateField(value: T[]): void;
13
+ protected validateField(value: T, index: number): void;
14
+ protected addNewField(): void;
15
+ protected removeControl(index: number): void;
16
+ protected getValues(): (T | null)[];
17
+ private isArrayData;
18
+ protected abstract controlTemplate(value: T | null, index: number): TemplateResult;
19
+ static get styles(): CSSResultArray;
20
+ }
@@ -0,0 +1,123 @@
1
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
2
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
3
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
4
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
5
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
6
+ };
7
+ import { css, html, property } from 'lit-element';
8
+ import { AbstractFieldBaseClass } from '../abstract-field-base.class';
9
+ import { fireEvent } from '../../lib/utils/fire-custom-event';
10
+ export class RepeatableBaseField extends AbstractFieldBaseClass {
11
+ constructor() {
12
+ super(...arguments);
13
+ this._errorMessage = [];
14
+ this.editedValues = null;
15
+ }
16
+ set errorMessage(messages) {
17
+ this._errorMessage = messages || [];
18
+ }
19
+ get errorMessage() {
20
+ return this.isReadonly ? [] : this._errorMessage;
21
+ }
22
+ render() {
23
+ const values = this.getValues();
24
+ return html `
25
+ <div class="finding-container">
26
+ <div class="question layout start"><slot>${this.questionTemplate()}</slot></div>
27
+ <div class="question-control layout vertical center-justified start">
28
+ ${values.map((value, index) => html `<div class="layout horizontal center full-width">
29
+ ${this.controlTemplate(value, index)}
30
+ <iron-icon
31
+ icon="close"
32
+ ?hidden="${this.isReadonly || values.length < 2}"
33
+ @click="${() => this.removeControl(index)}"
34
+ ></iron-icon>
35
+ </div>`)}
36
+ <paper-button class="add-button" ?hidden="${this.isReadonly}" @click="${() => this.addNewField()}">
37
+ Add
38
+ </paper-button>
39
+ </div>
40
+ </div>
41
+ `;
42
+ }
43
+ questionTemplate() {
44
+ return html `<span class="question-text">${this.questionText}</span>`;
45
+ }
46
+ valueChanged(newValue, index) {
47
+ if (!this.isReadonly) {
48
+ this.validateField(newValue, index);
49
+ }
50
+ else {
51
+ this._errorMessage = [];
52
+ }
53
+ if (this.editedValues && newValue !== this.editedValues[index]) {
54
+ this.editedValues[index] = newValue;
55
+ this.setValue(this.editedValues);
56
+ }
57
+ }
58
+ setValue(value) {
59
+ this.editedValues = value;
60
+ this.value = value.filter((value) => Boolean(value));
61
+ fireEvent(this, 'value-changed', { value: this.value });
62
+ }
63
+ validateField(value, index) {
64
+ if (this.isArrayData(value)) {
65
+ return value.forEach((item, index) => this.validateField(item, index));
66
+ }
67
+ let errorMessage;
68
+ if (this.required && !value && value !== null && typeof value !== 'number') {
69
+ errorMessage = 'This field is required!';
70
+ }
71
+ else {
72
+ errorMessage = this.metaValidation(value);
73
+ }
74
+ const oldError = (this._errorMessage || [])[index] || null;
75
+ if (oldError !== errorMessage) {
76
+ const errors = this.editedValues.map((_, index) => (this._errorMessage && this._errorMessage[index]) || null);
77
+ errors.splice(index, 1, errorMessage);
78
+ const newErrors = errors.some((error) => error !== null) ? errors : null;
79
+ fireEvent(this, 'error-changed', { error: newErrors });
80
+ this._errorMessage = errors;
81
+ this.requestUpdate();
82
+ }
83
+ }
84
+ addNewField() {
85
+ this.editedValues = [...this.editedValues, null];
86
+ }
87
+ removeControl(index) {
88
+ this.editedValues.splice(index, 1);
89
+ this.value = this.editedValues.filter((value) => Boolean(value));
90
+ fireEvent(this, 'value-changed', { value: this.value });
91
+ this.requestUpdate();
92
+ }
93
+ getValues() {
94
+ if (this.isReadonly) {
95
+ this.editedValues = Array.isArray(this.value) && this.value.length ? this.value : [null];
96
+ }
97
+ else if (!this.editedValues) {
98
+ this.editedValues = Array.isArray(this.value) && this.value.length ? this.value : [null];
99
+ }
100
+ return this.editedValues || [null];
101
+ }
102
+ isArrayData(value) {
103
+ return Array.isArray(value);
104
+ }
105
+ static get styles() {
106
+ // language=CSS
107
+ return [
108
+ ...AbstractFieldBaseClass.styles,
109
+ css `
110
+ :host(:not([is-readonly])) .question-control,
111
+ :host(:not([is-readonly])) .question {
112
+ padding-bottom: 10px;
113
+ }
114
+ `
115
+ ];
116
+ }
117
+ }
118
+ __decorate([
119
+ property()
120
+ ], RepeatableBaseField.prototype, "_errorMessage", void 0);
121
+ __decorate([
122
+ property()
123
+ ], RepeatableBaseField.prototype, "editedValues", void 0);
@@ -0,0 +1,10 @@
1
+ import { CSSResultArray, TemplateResult } from 'lit-element';
2
+ import '@polymer/paper-input/paper-input';
3
+ import { RepeatableBaseField } from './repeatable-base-field';
4
+ export declare class RepeatableNumberField extends RepeatableBaseField<number> {
5
+ isInteger: boolean;
6
+ protected controlTemplate(value: number | null, index: number): TemplateResult;
7
+ protected valueChanged(newValue: number, index: number): void;
8
+ protected customValidation(value: number): string | null;
9
+ static get styles(): CSSResultArray;
10
+ }
@@ -0,0 +1,56 @@
1
+ import { css, html } from 'lit-element';
2
+ import '@polymer/paper-input/paper-input';
3
+ import { InputStyles } from '../../lib/styles/input-styles';
4
+ import { RepeatableBaseField } from './repeatable-base-field';
5
+ import { AbstractFieldBaseClass } from '../abstract-field-base.class';
6
+ export class RepeatableNumberField extends RepeatableBaseField {
7
+ constructor() {
8
+ super(...arguments);
9
+ this.isInteger = false;
10
+ }
11
+ controlTemplate(value, index) {
12
+ return html `
13
+ ${InputStyles}
14
+ <paper-input
15
+ class="without-border no-padding-left form-control"
16
+ no-label-float
17
+ placeholder="${this.isReadonly ? '—' : this.placeholder}"
18
+ .value="${value}"
19
+ @value-changed="${({ detail }) => this.valueChanged(detail.value, index)}"
20
+ placeholder="&#8212;"
21
+ ?invalid="${this.errorMessage[index]}"
22
+ error-message="${this.errorMessage[index]}"
23
+ ?disabled="${this.isReadonly}"
24
+ >
25
+ </paper-input>
26
+ `;
27
+ }
28
+ valueChanged(newValue, index) {
29
+ const formatted = Number(newValue);
30
+ const isNumber = !isNaN(formatted) && `${newValue}` !== '' && `${newValue}` !== 'null';
31
+ super.valueChanged(isNumber ? formatted : newValue, index);
32
+ }
33
+ customValidation(value) {
34
+ if (!value) {
35
+ return null;
36
+ }
37
+ if (isNaN(value)) {
38
+ return 'Must be a number';
39
+ }
40
+ const integerValidation = !this.isInteger || value - Math.floor(value) === 0;
41
+ return integerValidation ? null : 'Must be an integer';
42
+ }
43
+ static get styles() {
44
+ // language=CSS
45
+ return [
46
+ ...AbstractFieldBaseClass.styles,
47
+ css `
48
+ @media (max-width: 380px) {
49
+ .no-padding-left {
50
+ padding-left: 0;
51
+ }
52
+ }
53
+ `
54
+ ];
55
+ }
56
+ }
@@ -0,0 +1,15 @@
1
+ import { TemplateResult, CSSResultArray } from 'lit-element';
2
+ import '@polymer/paper-radio-group/paper-radio-group';
3
+ import '@polymer/paper-radio-button/paper-radio-button';
4
+ import { PaperRadioButtonElement } from '@polymer/paper-radio-button/paper-radio-button';
5
+ import { RepeatableBaseField } from './repeatable-base-field';
6
+ import { FieldOption } from '..';
7
+ export declare class RepeatableScaleField extends RepeatableBaseField<string | number | null> {
8
+ options: (FieldOption | string | number)[];
9
+ protected controlTemplate(value: string | null, index: number): TemplateResult;
10
+ protected onSelect(item: PaperRadioButtonElement, index: number): void;
11
+ protected getLabel(option: FieldOption | string | number): unknown;
12
+ protected getValue(option: FieldOption | string | number): unknown;
13
+ protected customValidation(): string | null;
14
+ static get styles(): CSSResultArray;
15
+ }
@@ -0,0 +1,104 @@
1
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
2
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
3
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
4
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
5
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
6
+ };
7
+ import { html, property, css } from 'lit-element';
8
+ import { repeat } from 'lit-html/directives/repeat';
9
+ import '@polymer/paper-radio-group/paper-radio-group';
10
+ import '@polymer/paper-radio-button/paper-radio-button';
11
+ import { InputStyles } from '../../lib/styles/input-styles';
12
+ import { RepeatableBaseField } from './repeatable-base-field';
13
+ import { AbstractFieldBaseClass } from '../abstract-field-base.class';
14
+ export class RepeatableScaleField extends RepeatableBaseField {
15
+ constructor() {
16
+ super(...arguments);
17
+ this.options = [];
18
+ }
19
+ controlTemplate(value, index) {
20
+ return html `
21
+ ${InputStyles}
22
+ <div class="container">
23
+ <paper-radio-group
24
+ class="radio-group"
25
+ selected="${value}"
26
+ @iron-select="${({ detail }) => this.onSelect(detail.item, index)}"
27
+ >
28
+ ${repeat(this.options, (option) => html `
29
+ <paper-radio-button class="radio-button" name="${this.getValue(option)}">
30
+ ${this.getLabel(option)}
31
+ </paper-radio-button>
32
+ `)}
33
+ </paper-radio-group>
34
+
35
+ <paper-button
36
+ ?hidden="${this.isReadonly}"
37
+ @click="${() => this.valueChanged(null, index)}"
38
+ class="clear-button"
39
+ >
40
+ <iron-icon icon="clear"></iron-icon>Clear
41
+ </paper-button>
42
+ </div>
43
+ `;
44
+ }
45
+ onSelect(item, index) {
46
+ const newValue = item.get('name');
47
+ this.valueChanged(newValue, index);
48
+ }
49
+ getLabel(option) {
50
+ return typeof option === 'object' ? option.label : option;
51
+ }
52
+ getValue(option) {
53
+ return typeof option === 'object' ? option.value : option;
54
+ }
55
+ customValidation() {
56
+ return null;
57
+ }
58
+ static get styles() {
59
+ // language=CSS
60
+ return [
61
+ ...AbstractFieldBaseClass.styles,
62
+ css `
63
+ .container {
64
+ position: relative;
65
+ min-height: 48px;
66
+ display: flex;
67
+ align-items: center;
68
+ flex-direction: row;
69
+ }
70
+
71
+ .radio-group {
72
+ display: flex;
73
+ flex-direction: row;
74
+ flex-wrap: wrap;
75
+ }
76
+
77
+ :host([is-readonly]) paper-radio-group {
78
+ pointer-events: none;
79
+ opacity: 0.55;
80
+ }
81
+
82
+ @media (max-width: 1080px) {
83
+ .container {
84
+ flex-direction: column;
85
+ align-items: flex-start;
86
+ }
87
+ .radio-group {
88
+ flex-direction: column;
89
+ }
90
+ .radio-button {
91
+ padding-left: 3px;
92
+ }
93
+ .clear-button {
94
+ margin: 0;
95
+ padding-left: 0;
96
+ }
97
+ }
98
+ `
99
+ ];
100
+ }
101
+ }
102
+ __decorate([
103
+ property({ type: Array })
104
+ ], RepeatableScaleField.prototype, "options", void 0);
@@ -0,0 +1,8 @@
1
+ import { CSSResultArray, TemplateResult } from 'lit-element';
2
+ import '@polymer/paper-input/paper-textarea';
3
+ import { RepeatableBaseField } from './repeatable-base-field';
4
+ export declare class RepeatableTextField extends RepeatableBaseField<string> {
5
+ protected controlTemplate(value: string | null, index: number): TemplateResult;
6
+ protected customValidation(): string | null;
7
+ static get styles(): CSSResultArray;
8
+ }
@@ -0,0 +1,43 @@
1
+ import { css, html } from 'lit-element';
2
+ import '@polymer/paper-input/paper-textarea';
3
+ import { InputStyles } from '../../lib/styles/input-styles';
4
+ import { RepeatableBaseField } from './repeatable-base-field';
5
+ import { AbstractFieldBaseClass } from '../abstract-field-base.class';
6
+ export class RepeatableTextField extends RepeatableBaseField {
7
+ controlTemplate(value, index) {
8
+ return html `
9
+ ${InputStyles}
10
+ <paper-textarea
11
+ id="textarea"
12
+ class="no-padding-left form-control"
13
+ no-label-float
14
+ placeholder="${this.isReadonly ? '—' : this.placeholder}"
15
+ .value="${value}"
16
+ @value-changed="${({ detail }) => this.valueChanged(detail.value, index)}"
17
+ ?disabled="${this.isReadonly}"
18
+ ?invalid="${this.errorMessage[index]}"
19
+ error-message="${this.errorMessage[index]}"
20
+ >
21
+ </paper-textarea>
22
+ `;
23
+ }
24
+ customValidation() {
25
+ return null;
26
+ }
27
+ static get styles() {
28
+ // language=CSS
29
+ return [
30
+ ...AbstractFieldBaseClass.styles,
31
+ css `
32
+ :host(.wide) paper-textarea {
33
+ padding-left: 0;
34
+ }
35
+ @media (max-width: 380px) {
36
+ .no-padding-left {
37
+ padding-left: 0;
38
+ }
39
+ }
40
+ `
41
+ ];
42
+ }
43
+ }
@@ -0,0 +1,16 @@
1
+ import '@unicef-polymer/etools-upload/etools-upload';
2
+ import { BaseField } from './base-field';
3
+ import { SingleUploadFinishedDetails, StoredAttachment } from '../../form-attachments-popup';
4
+ import { TemplateResult, CSSResultArray } from 'lit-element';
5
+ export declare class AttachmentField extends BaseField<StoredAttachment | null> {
6
+ get uploadUrl(): string;
7
+ get jwtLocalStorageKey(): string;
8
+ computedPath: string[];
9
+ protected controlTemplate(): TemplateResult;
10
+ protected customValidation(): string | null;
11
+ protected attachmentsUploaded({ success, error }: SingleUploadFinishedDetails): void;
12
+ protected downloadFile(attachment: StoredAttachment | null): void;
13
+ private isUploadedAttachment;
14
+ private isOfflineSavedAttachment;
15
+ static get styles(): CSSResultArray;
16
+ }