@unicef-polymer/etools-form-builder 3.1.1 → 3.1.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 (40) hide show
  1. package/LICENSE +674 -674
  2. package/README.md +1 -1
  3. package/dist/form-attachments-popup/form-attachments-popup.js +135 -135
  4. package/dist/form-fields/abstract-field-base.class.d.ts +1 -0
  5. package/dist/form-fields/abstract-field-base.class.js +104 -101
  6. package/dist/form-fields/field-renderer-component.d.ts +1 -1
  7. package/dist/form-fields/field-renderer-component.js +168 -166
  8. package/dist/form-fields/repeatable-fields/repeatable-attachment-field.js +111 -111
  9. package/dist/form-fields/repeatable-fields/repeatable-base-field.js +22 -22
  10. package/dist/form-fields/repeatable-fields/repeatable-number-field.js +19 -19
  11. package/dist/form-fields/repeatable-fields/repeatable-scale-field.js +57 -57
  12. package/dist/form-fields/repeatable-fields/repeatable-text-field.js +19 -19
  13. package/dist/form-fields/single-fields/attachment-field.js +13 -13
  14. package/dist/form-fields/single-fields/boolean-field.js +16 -16
  15. package/dist/form-fields/single-fields/number-field.js +20 -20
  16. package/dist/form-fields/single-fields/scale-field.js +58 -58
  17. package/dist/form-fields/single-fields/text-field.d.ts +4 -1
  18. package/dist/form-fields/single-fields/text-field.js +54 -26
  19. package/dist/form-groups/form-abstract-group.js +129 -129
  20. package/dist/form-groups/form-card.js +30 -30
  21. package/dist/form-groups/form-collapsed-card.js +34 -34
  22. package/dist/lib/additional-components/confirmation-dialog.js +20 -20
  23. package/dist/lib/additional-components/etools-fb-card.js +144 -144
  24. package/dist/lib/styles/attachments.styles.js +61 -61
  25. package/dist/lib/styles/card-styles.js +147 -147
  26. package/dist/lib/styles/dialog.styles.js +83 -83
  27. package/dist/lib/styles/elevation-styles.js +46 -46
  28. package/dist/lib/styles/flex-layout-classes.js +316 -316
  29. package/dist/lib/styles/form-builder-card.styles.js +53 -53
  30. package/dist/lib/styles/page-layout-styles.js +198 -198
  31. package/dist/lib/styles/shared-styles.js +61 -61
  32. package/dist/rich-editor/rich-action.d.ts +19 -0
  33. package/dist/rich-editor/rich-action.js +105 -0
  34. package/dist/rich-editor/rich-text.d.ts +12 -0
  35. package/dist/rich-editor/rich-text.js +125 -0
  36. package/dist/rich-editor/rich-toolbar.d.ts +14 -0
  37. package/dist/rich-editor/rich-toolbar.js +194 -0
  38. package/dist/rich-editor/rich-viewer.d.ts +11 -0
  39. package/dist/rich-editor/rich-viewer.js +78 -0
  40. package/package.json +51 -52
@@ -19,23 +19,23 @@ export class RepeatableBaseField extends AbstractFieldBaseClass {
19
19
  }
20
20
  render() {
21
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) => html `<div class="layout horizontal center full-width">
27
- ${this.controlTemplate(value, index)}
28
- <etools-icon-button
29
- name="close"
30
- ?hidden="${this.isReadonly || values.length < 2}"
31
- @click="${() => this.removeControl(index)}"
32
- ></etools-icon-button>
33
- </div>`)}
34
- <etools-button variant="primary" class="add-button" ?hidden="${this.isReadonly}" @click="${this.addNewField}">
35
- ${getTranslation(this.language, 'ADD')}
36
- </etools-button>
37
- </div>
38
- </div>
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) => html `<div class="layout horizontal center full-width">
27
+ ${this.controlTemplate(value, index)}
28
+ <etools-icon-button
29
+ name="close"
30
+ ?hidden="${this.isReadonly || values.length < 2}"
31
+ @click="${() => this.removeControl(index)}"
32
+ ></etools-icon-button>
33
+ </div>`)}
34
+ <etools-button variant="primary" class="add-button" ?hidden="${this.isReadonly}" @click="${this.addNewField}">
35
+ ${getTranslation(this.language, 'ADD')}
36
+ </etools-button>
37
+ </div>
38
+ </div>
39
39
  `;
40
40
  }
41
41
  questionTemplate() {
@@ -104,11 +104,11 @@ export class RepeatableBaseField extends AbstractFieldBaseClass {
104
104
  // language=CSS
105
105
  return [
106
106
  ...AbstractFieldBaseClass.styles,
107
- css `
108
- :host(:not([is-readonly])) .question-control,
109
- :host(:not([is-readonly])) .question {
110
- padding-bottom: 10px;
111
- }
107
+ css `
108
+ :host(:not([is-readonly])) .question-control,
109
+ :host(:not([is-readonly])) .question {
110
+ padding-bottom: 10px;
111
+ }
112
112
  `
113
113
  ];
114
114
  }
@@ -11,19 +11,19 @@ let RepeatableNumberField = class RepeatableNumberField extends RepeatableBaseFi
11
11
  this.isInteger = false;
12
12
  }
13
13
  controlTemplate(value, index) {
14
- return html `
15
- <etools-input
16
- class="no-padding-left"
17
- no-label-float
18
- placeholder="${this.isReadonly ? '—' : this.placeholder}"
19
- .value="${value}"
20
- @value-changed="${({ detail }) => this.valueChanged(detail.value, index)}"
21
- placeholder="&#8212;"
22
- ?invalid="${this.errorMessage[index]}"
23
- error-message="${this.errorMessage[index]}"
24
- ?readonly="${this.isReadonly}"
25
- >
26
- </etools-input>
14
+ return html `
15
+ <etools-input
16
+ class="no-padding-left"
17
+ no-label-float
18
+ placeholder="${this.isReadonly ? '—' : this.placeholder}"
19
+ .value="${value}"
20
+ @value-changed="${({ detail }) => this.valueChanged(detail.value, index)}"
21
+ placeholder="&#8212;"
22
+ ?invalid="${this.errorMessage[index]}"
23
+ error-message="${this.errorMessage[index]}"
24
+ ?readonly="${this.isReadonly}"
25
+ >
26
+ </etools-input>
27
27
  `;
28
28
  }
29
29
  valueChanged(newValue, index) {
@@ -45,12 +45,12 @@ let RepeatableNumberField = class RepeatableNumberField extends RepeatableBaseFi
45
45
  // language=CSS
46
46
  return [
47
47
  ...AbstractFieldBaseClass.styles,
48
- css `
49
- @media (max-width: 380px) {
50
- .no-padding-left {
51
- padding-left: 0;
52
- }
53
- }
48
+ css `
49
+ @media (max-width: 380px) {
50
+ .no-padding-left {
51
+ padding-left: 0;
52
+ }
53
+ }
54
54
  `
55
55
  ];
56
56
  }
@@ -14,27 +14,27 @@ let RepeatableScaleField = class RepeatableScaleField extends RepeatableBaseFiel
14
14
  this.options = [];
15
15
  }
16
16
  controlTemplate(value, index) {
17
- return html `
18
- <div class="container">
19
- <etools-radio-group
20
- class="radio-group"
21
- .value="${value}"
22
- @sl-change="${(e) => this.onSelect(e.target.value, index)}"
23
- >
24
- ${repeat(this.options, (option) => html `
25
- <sl-radio class="radio-button" value="${this.getValue(option)}"> ${this.getLabel(option)} </sl-radio>
26
- `)}
27
- </etools-radio-group>
28
- <etools-button
29
- class="neutral clear-button"
30
- variant="text"
31
- ?hidden="${this.isReadonly}"
32
- @click="${() => this.valueChanged(null, index)}"
33
- >
34
- <etools-icon name="clear" slot="prefix"></etools-icon>
35
- ${getTranslation(this.language, 'CLEAR')}
36
- </etools-button>
37
- </div>
17
+ return html `
18
+ <div class="container">
19
+ <etools-radio-group
20
+ class="radio-group"
21
+ .value="${value}"
22
+ @sl-change="${(e) => this.onSelect(e.target.value, index)}"
23
+ >
24
+ ${repeat(this.options, (option) => html `
25
+ <sl-radio class="radio-button" value="${this.getValue(option)}"> ${this.getLabel(option)} </sl-radio>
26
+ `)}
27
+ </etools-radio-group>
28
+ <etools-button
29
+ class="neutral clear-button"
30
+ variant="text"
31
+ ?hidden="${this.isReadonly}"
32
+ @click="${() => this.valueChanged(null, index)}"
33
+ >
34
+ <etools-icon name="clear" slot="prefix"></etools-icon>
35
+ ${getTranslation(this.language, 'CLEAR')}
36
+ </etools-button>
37
+ </div>
38
38
  `;
39
39
  }
40
40
  onSelect(itemValue, index) {
@@ -53,42 +53,42 @@ let RepeatableScaleField = class RepeatableScaleField extends RepeatableBaseFiel
53
53
  // language=CSS
54
54
  return [
55
55
  ...AbstractFieldBaseClass.styles,
56
- css `
57
- .container {
58
- position: relative;
59
- min-height: 48px;
60
- display: flex;
61
- align-items: center;
62
- flex-direction: row;
63
- }
64
-
65
- .radio-group {
66
- display: flex;
67
- flex-direction: row;
68
- flex-wrap: wrap;
69
- }
70
-
71
- :host([is-readonly]) etools-radio-group {
72
- pointer-events: none;
73
- opacity: 0.55;
74
- }
75
-
76
- @media (max-width: 1080px) {
77
- .container {
78
- flex-direction: column;
79
- align-items: flex-start;
80
- }
81
- .radio-group {
82
- flex-direction: column;
83
- }
84
- .radio-button {
85
- padding-left: 3px;
86
- }
87
- .clear-button {
88
- margin: 0;
89
- padding-left: 0;
90
- }
91
- }
56
+ css `
57
+ .container {
58
+ position: relative;
59
+ min-height: 48px;
60
+ display: flex;
61
+ align-items: center;
62
+ flex-direction: row;
63
+ }
64
+
65
+ .radio-group {
66
+ display: flex;
67
+ flex-direction: row;
68
+ flex-wrap: wrap;
69
+ }
70
+
71
+ :host([is-readonly]) etools-radio-group {
72
+ pointer-events: none;
73
+ opacity: 0.55;
74
+ }
75
+
76
+ @media (max-width: 1080px) {
77
+ .container {
78
+ flex-direction: column;
79
+ align-items: flex-start;
80
+ }
81
+ .radio-group {
82
+ flex-direction: column;
83
+ }
84
+ .radio-button {
85
+ padding-left: 3px;
86
+ }
87
+ .clear-button {
88
+ margin: 0;
89
+ padding-left: 0;
90
+ }
91
+ }
92
92
  `
93
93
  ];
94
94
  }
@@ -6,19 +6,19 @@ import { RepeatableBaseField } from './repeatable-base-field';
6
6
  import { AbstractFieldBaseClass } from '../abstract-field-base.class';
7
7
  let RepeatableTextField = class RepeatableTextField extends RepeatableBaseField {
8
8
  controlTemplate(value, index) {
9
- return html `
10
- <etools-textarea
11
- id="textarea"
12
- class="no-padding-left"
13
- no-label-float
14
- placeholder="${this.isReadonly ? '—' : this.placeholder}"
15
- .value="${value}"
16
- @value-changed="${({ detail }) => this.valueChanged(detail.value, index)}"
17
- ?readonly="${this.isReadonly}"
18
- ?invalid="${this.errorMessage[index]}"
19
- error-message="${this.errorMessage[index]}"
20
- >
21
- </etools-textarea>
9
+ return html `
10
+ <etools-textarea
11
+ id="textarea"
12
+ class="no-padding-left"
13
+ no-label-float
14
+ placeholder="${this.isReadonly ? '—' : this.placeholder}"
15
+ .value="${value}"
16
+ @value-changed="${({ detail }) => this.valueChanged(detail.value, index)}"
17
+ ?readonly="${this.isReadonly}"
18
+ ?invalid="${this.errorMessage[index]}"
19
+ error-message="${this.errorMessage[index]}"
20
+ >
21
+ </etools-textarea>
22
22
  `;
23
23
  }
24
24
  customValidation() {
@@ -28,12 +28,12 @@ let RepeatableTextField = class RepeatableTextField extends RepeatableBaseField
28
28
  // language=CSS
29
29
  return [
30
30
  ...AbstractFieldBaseClass.styles,
31
- css `
32
- @media (max-width: 380px) {
33
- .no-padding-left {
34
- padding-left: 0;
35
- }
36
- }
31
+ css `
32
+ @media (max-width: 380px) {
33
+ .no-padding-left {
34
+ padding-left: 0;
35
+ }
36
+ }
37
37
  `
38
38
  ];
39
39
  }
@@ -20,19 +20,19 @@ let AttachmentField = class AttachmentField extends BaseField {
20
20
  return AttachmentsHelper.jwtLocalStorageKey;
21
21
  }
22
22
  controlTemplate() {
23
- return html `
24
- <!-- Upload button -->
25
- <etools-upload
26
- class="with-padding"
27
- activate-offline
28
- .uploadedFileInfo="${this.value}"
29
- ?readonly="${this.isReadonly}"
30
- @upload-finished="${({ detail }) => this.attachmentsUploaded(detail)}"
31
- @delete-file="${() => this.valueChanged(null)}"
32
- .endpointInfo="${{ endpoint: this.uploadUrl, extraInfo: { composedPath: this.computedPath } }}"
33
- .jwtLocalStorageKey="${this.jwtLocalStorageKey}"
34
- >
35
- </etools-upload>
23
+ return html `
24
+ <!-- Upload button -->
25
+ <etools-upload
26
+ class="with-padding"
27
+ activate-offline
28
+ .uploadedFileInfo="${this.value}"
29
+ ?readonly="${this.isReadonly}"
30
+ @upload-finished="${({ detail }) => this.attachmentsUploaded(detail)}"
31
+ @delete-file="${() => this.valueChanged(null)}"
32
+ .endpointInfo="${{ endpoint: this.uploadUrl, extraInfo: { composedPath: this.computedPath } }}"
33
+ .jwtLocalStorageKey="${this.jwtLocalStorageKey}"
34
+ >
35
+ </etools-upload>
36
36
  `;
37
37
  }
38
38
  customValidation() {
@@ -5,16 +5,16 @@ import { BaseField } from './base-field';
5
5
  import '@shoelace-style/shoelace/dist/components/switch/switch.js';
6
6
  let BooleanField = class BooleanField extends BaseField {
7
7
  controlTemplate() {
8
- return html `
9
- <sl-switch
10
- class="no-padding-left"
11
- ?checked="${this.value}"
12
- @sl-change="${(e) => this.valueChanged(e.target.checked)}"
13
- ?disabled="${this.isReadonly}"
14
- >
15
- </sl-switch>
16
-
17
- <div ?hidden="${!this.errorMessage}" class="error-text">${this.errorMessage}</div>
8
+ return html `
9
+ <sl-switch
10
+ class="no-padding-left"
11
+ ?checked="${this.value}"
12
+ @sl-change="${(e) => this.valueChanged(e.target.checked)}"
13
+ ?disabled="${this.isReadonly}"
14
+ >
15
+ </sl-switch>
16
+
17
+ <div ?hidden="${!this.errorMessage}" class="error-text">${this.errorMessage}</div>
18
18
  `;
19
19
  }
20
20
  customValidation() {
@@ -24,12 +24,12 @@ let BooleanField = class BooleanField extends BaseField {
24
24
  // language=CSS
25
25
  return [
26
26
  ...BaseField.styles,
27
- css `
28
- @media (max-width: 380px) {
29
- .no-padding-left {
30
- padding-left: 0;
31
- }
32
- }
27
+ css `
28
+ @media (max-width: 380px) {
29
+ .no-padding-left {
30
+ padding-left: 0;
31
+ }
32
+ }
33
33
  `
34
34
  ];
35
35
  }
@@ -10,20 +10,20 @@ let NumberField = class NumberField extends BaseField {
10
10
  this.isInteger = false;
11
11
  }
12
12
  controlTemplate() {
13
- return html `
14
- <etools-input
15
- class="no-padding-left"
16
- no-label-float
17
- placeholder="${this.isReadonly ? '—' : this.placeholder}"
18
- .value="${this.value}"
19
- @value-changed="${({ detail }) => this.valueChanged(detail.value)}"
20
- @focus="${() => (this.touched = true)}"
21
- placeholder="&#8212;"
22
- ?invalid="${this.errorMessage}"
23
- error-message="${this.errorMessage}"
24
- ?readonly="${this.isReadonly}"
25
- >
26
- </etools-input>
13
+ return html `
14
+ <etools-input
15
+ class="no-padding-left"
16
+ no-label-float
17
+ placeholder="${this.isReadonly ? '—' : this.placeholder}"
18
+ .value="${this.value}"
19
+ @value-changed="${({ detail }) => this.valueChanged(detail.value)}"
20
+ @focus="${() => (this.touched = true)}"
21
+ placeholder="&#8212;"
22
+ ?invalid="${this.errorMessage}"
23
+ error-message="${this.errorMessage}"
24
+ ?readonly="${this.isReadonly}"
25
+ >
26
+ </etools-input>
27
27
  `;
28
28
  }
29
29
  valueChanged(newValue) {
@@ -45,12 +45,12 @@ let NumberField = class NumberField extends BaseField {
45
45
  // language=CSS
46
46
  return [
47
47
  ...BaseField.styles,
48
- css `
49
- @media (max-width: 380px) {
50
- .no-padding-left {
51
- padding-left: 0;
52
- }
53
- }
48
+ css `
49
+ @media (max-width: 380px) {
50
+ .no-padding-left {
51
+ padding-left: 0;
52
+ }
53
+ }
54
54
  `
55
55
  ];
56
56
  }
@@ -13,28 +13,28 @@ let ScaleField = class ScaleField extends BaseField {
13
13
  this.options = [];
14
14
  }
15
15
  controlTemplate() {
16
- return html `
17
- <div class="container">
18
- <etools-radio-group
19
- class="radio-group"
20
- .value="${this.value}"
21
- @sl-change="${(e) => this.onSelect(e.target.value)}"
22
- >
23
- ${repeat(this.options, (option) => html `
24
- <sl-radio class="radio-button" value="${this.getValue(option)}">${this.getLabel(option)}</sl-radio>
25
- `)}
26
- </etools-radio-group>
27
- <etools-button
28
- class="neutral clear-button"
29
- variant="text"
30
- ?hidden="${this.isReadonly}"
31
- @click="${() => this.valueChanged(null)}"
32
- >
33
- <etools-icon name="clear" slot="prefix"></etools-icon>
34
- ${getTranslation(this.language, 'CLEAR')}
35
- </etools-button>
36
- </div>
37
- <div ?hidden="${!this.errorMessage}" class="error-text">${this.errorMessage}</div>
16
+ return html `
17
+ <div class="container">
18
+ <etools-radio-group
19
+ class="radio-group"
20
+ .value="${this.value}"
21
+ @sl-change="${(e) => this.onSelect(e.target.value)}"
22
+ >
23
+ ${repeat(this.options, (option) => html `
24
+ <sl-radio class="radio-button" value="${this.getValue(option)}">${this.getLabel(option)}</sl-radio>
25
+ `)}
26
+ </etools-radio-group>
27
+ <etools-button
28
+ class="neutral clear-button"
29
+ variant="text"
30
+ ?hidden="${this.isReadonly}"
31
+ @click="${() => this.valueChanged(null)}"
32
+ >
33
+ <etools-icon name="clear" slot="prefix"></etools-icon>
34
+ ${getTranslation(this.language, 'CLEAR')}
35
+ </etools-button>
36
+ </div>
37
+ <div ?hidden="${!this.errorMessage}" class="error-text">${this.errorMessage}</div>
38
38
  `;
39
39
  }
40
40
  getLabel(option) {
@@ -56,42 +56,42 @@ let ScaleField = class ScaleField extends BaseField {
56
56
  // language=CSS
57
57
  return [
58
58
  ...BaseField.styles,
59
- css `
60
- .container {
61
- position: relative;
62
- min-height: 48px;
63
- display: flex;
64
- align-items: center;
65
- flex-direction: row;
66
- }
67
-
68
- .radio-group {
69
- display: flex;
70
- flex-direction: row;
71
- flex-wrap: wrap;
72
- }
73
-
74
- :host([is-readonly]) etools-radio-group {
75
- pointer-events: none;
76
- opacity: 0.55;
77
- }
78
-
79
- @media (max-width: 1080px) {
80
- .container {
81
- flex-direction: column;
82
- align-items: flex-start;
83
- }
84
- .radio-group {
85
- flex-direction: column;
86
- }
87
- .radio-button {
88
- padding-left: 3px;
89
- }
90
- .clear-button {
91
- margin: 0;
92
- padding-left: 0;
93
- }
94
- }
59
+ css `
60
+ .container {
61
+ position: relative;
62
+ min-height: 48px;
63
+ display: flex;
64
+ align-items: center;
65
+ flex-direction: row;
66
+ }
67
+
68
+ .radio-group {
69
+ display: flex;
70
+ flex-direction: row;
71
+ flex-wrap: wrap;
72
+ }
73
+
74
+ :host([is-readonly]) etools-radio-group {
75
+ pointer-events: none;
76
+ opacity: 0.55;
77
+ }
78
+
79
+ @media (max-width: 1080px) {
80
+ .container {
81
+ flex-direction: column;
82
+ align-items: flex-start;
83
+ }
84
+ .radio-group {
85
+ flex-direction: column;
86
+ }
87
+ .radio-button {
88
+ padding-left: 3px;
89
+ }
90
+ .clear-button {
91
+ margin: 0;
92
+ padding-left: 0;
93
+ }
94
+ }
95
95
  `
96
96
  ];
97
97
  }
@@ -1,8 +1,11 @@
1
- import { CSSResultArray, TemplateResult } from 'lit';
1
+ import { CSSResultArray, PropertyValues, TemplateResult } from 'lit';
2
2
  import { BaseField } from './base-field';
3
3
  import '@unicef-polymer/etools-unicef/src/etools-input/etools-textarea';
4
+ import '../../rich-editor/rich-text';
4
5
  export declare class TextField extends BaseField<string> {
6
+ protected originalValue: string | null;
5
7
  protected controlTemplate(): TemplateResult;
8
+ updated(changedProperties: PropertyValues): void;
6
9
  protected customValidation(): string | null;
7
10
  static get styles(): CSSResultArray;
8
11
  }
@@ -1,26 +1,51 @@
1
1
  import { __decorate } from "tslib";
2
2
  import { css, html } from 'lit';
3
- import { customElement } from 'lit/decorators.js';
3
+ import { customElement, property } from 'lit/decorators.js';
4
4
  import { BaseField } from './base-field';
5
5
  import '@unicef-polymer/etools-unicef/src/etools-input/etools-textarea';
6
+ import '../../rich-editor/rich-text';
6
7
  let TextField = class TextField extends BaseField {
8
+ constructor() {
9
+ super(...arguments);
10
+ this.originalValue = null;
11
+ }
7
12
  controlTemplate() {
8
- return html `
9
- <etools-textarea
10
- id="otherInfo"
11
- class="no-padding-left"
12
- no-label-float
13
- placeholder="${this.isReadonly ? '—' : this.placeholder}"
14
- .value="${this.value}"
15
- @value-changed="${({ detail }) => this.valueChanged(detail.value)}"
16
- @focus="${() => (this.touched = true)}"
17
- ?readonly="${this.isReadonly}"
18
- ?invalid="${this.errorMessage}"
19
- name="${this.name}"
20
- error-message="${this.errorMessage}"
21
- >
22
- </etools-textarea>
23
- `;
13
+ return this.showRichEditor
14
+ ? html `<div class="finding-container no-padding-left">
15
+ <rich-text
16
+ .value="${this.originalValue}"
17
+ ?readonly="${this.isReadonly}"
18
+ @editor-changed="${({ detail }) => {
19
+ if (detail.value !== this.value) {
20
+ this.valueChanged(detail.value);
21
+ }
22
+ }}"
23
+ ></rich-text>
24
+ </div>`
25
+ : html `
26
+ <etools-textarea
27
+ id="otherInfo"
28
+ class="no-padding-left"
29
+ no-label-float
30
+ placeholder="${this.isReadonly ? '—' : this.placeholder}"
31
+ .value="${this.value}"
32
+ @value-changed="${({ detail }) => this.valueChanged(detail.value)}"
33
+ @focus="${() => (this.touched = true)}"
34
+ ?readonly="${this.isReadonly}"
35
+ ?invalid="${this.errorMessage}"
36
+ name="${this.name}"
37
+ error-message="${this.errorMessage}"
38
+ >
39
+ </etools-textarea>
40
+ `;
41
+ }
42
+ updated(changedProperties) {
43
+ super.updated(changedProperties);
44
+ // set control value only at the beginning with a proxy param (originalValue),
45
+ // avoid requestUpdate when .value change because will move carret
46
+ if (changedProperties.has('value') && this.originalValue === null) {
47
+ this.originalValue = this.value;
48
+ }
24
49
  }
25
50
  customValidation() {
26
51
  return null;
@@ -29,19 +54,22 @@ let TextField = class TextField extends BaseField {
29
54
  // language=CSS
30
55
  return [
31
56
  ...BaseField.styles,
32
- css `
33
- :host(.wide) etools-textarea {
34
- padding-left: 0;
35
- }
36
- @media (max-width: 380px) {
37
- .no-padding-left {
38
- padding-left: 0;
39
- }
40
- }
57
+ css `
58
+ :host(.wide) etools-textarea {
59
+ padding-left: 0;
60
+ }
61
+ @media (max-width: 380px) {
62
+ .no-padding-left {
63
+ padding-left: 0;
64
+ }
65
+ }
41
66
  `
42
67
  ];
43
68
  }
44
69
  };
70
+ __decorate([
71
+ property()
72
+ ], TextField.prototype, "originalValue", void 0);
45
73
  TextField = __decorate([
46
74
  customElement('text-field')
47
75
  ], TextField);