@exmg/exm-form 1.1.27 → 1.1.29

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.
@@ -3,7 +3,7 @@ import '@material/web/button/outlined-button.js';
3
3
  import '@material/web/button/filled-button.js';
4
4
  import '@material/web/divider/divider.js';
5
5
  import { ExmgElement } from '@exmg/lit-base';
6
- declare const ExmFormBase_base: import("./exm-form-validate-mixin.js").Constructor<import("./exm-form-validate-mixin.js").FormValidateMixinInterface> & typeof ExmgElement;
6
+ declare const ExmFormBase_base: import("./exm-form-dirty-mixin.js").Constructor<import("./exm-form-dirty-mixin.js").FormDirtyMixinInterface> & import("./exm-form-validate-mixin.js").Constructor<import("./exm-form-validate-mixin.js").FormValidateMixinInterface> & typeof ExmgElement;
7
7
  export declare class ExmFormBase extends ExmFormBase_base {
8
8
  /**
9
9
  * Submit button copy
@@ -13,6 +13,14 @@ export declare class ExmFormBase extends ExmFormBase_base {
13
13
  * Cancel button copy
14
14
  */
15
15
  cancelBtn: string;
16
+ /**
17
+ * Hide cancel button
18
+ */
19
+ hideCancelButton: boolean;
20
+ /**
21
+ * Show reset button
22
+ */
23
+ showResetButton: boolean;
16
24
  /**
17
25
  * Internall used to show button spinner.
18
26
  */
@@ -9,7 +9,8 @@ import { ExmgElement } from '@exmg/lit-base';
9
9
  import { classMap } from 'lit/directives/class-map.js';
10
10
  import { ExmFormValidateMixin } from './exm-form-validate-mixin.js';
11
11
  import { serializeFormData } from './utils/serializeFormData.js';
12
- export class ExmFormBase extends ExmFormValidateMixin(ExmgElement) {
12
+ import { ExmFormDirtyMixin } from './exm-form-dirty-mixin.js';
13
+ export class ExmFormBase extends ExmFormDirtyMixin(ExmFormValidateMixin(ExmgElement)) {
13
14
  constructor() {
14
15
  super(...arguments);
15
16
  /**
@@ -20,6 +21,14 @@ export class ExmFormBase extends ExmFormValidateMixin(ExmgElement) {
20
21
  * Cancel button copy
21
22
  */
22
23
  this.cancelBtn = 'Cancel';
24
+ /**
25
+ * Hide cancel button
26
+ */
27
+ this.hideCancelButton = false;
28
+ /**
29
+ * Show reset button
30
+ */
31
+ this.showResetButton = false;
23
32
  /**
24
33
  * Internall used to show button spinner.
25
34
  */
@@ -108,9 +117,20 @@ export class ExmFormBase extends ExmFormValidateMixin(ExmgElement) {
108
117
  renderActions() {
109
118
  return html `
110
119
  <footer class="actions">
111
- <md-outlined-button dialogFocus @click=${() => this.fire('form-cancel')}>
112
- ${this.cancelBtn}
113
- </md-outlined-button>
120
+ ${this.showResetButton
121
+ ? html `
122
+ <md-icon-button ?disabled=${!this.dirty} @click=${this.reset}>
123
+ <md-icon>restart_alt</md-icon>
124
+ </md-icon-button>
125
+ `
126
+ : nothing}
127
+ ${this.hideCancelButton
128
+ ? nothing
129
+ : html `
130
+ <md-outlined-button dialogFocus @click=${() => this.fire('form-cancel')}>
131
+ ${this.cancelBtn}
132
+ </md-outlined-button>
133
+ `}
114
134
  <md-filled-button
115
135
  type="button"
116
136
  @click=${this.handleSubmit}
@@ -142,6 +162,12 @@ __decorate([
142
162
  __decorate([
143
163
  property({ type: String })
144
164
  ], ExmFormBase.prototype, "cancelBtn", void 0);
165
+ __decorate([
166
+ property({ type: Boolean, attribute: 'hide-cancel-button' })
167
+ ], ExmFormBase.prototype, "hideCancelButton", void 0);
168
+ __decorate([
169
+ property({ type: Boolean, attribute: 'show-reset-button' })
170
+ ], ExmFormBase.prototype, "showResetButton", void 0);
145
171
  __decorate([
146
172
  property({ type: Boolean })
147
173
  ], ExmFormBase.prototype, "submitting", void 0);
@@ -0,0 +1,10 @@
1
+ import { LitElement } from 'lit';
2
+ export type Constructor<T> = new (...args: any[]) => T;
3
+ export declare class FormDirtyMixinClass extends LitElement {
4
+ }
5
+ export declare class FormDirtyMixinInterface {
6
+ dirty: boolean;
7
+ getForm(): HTMLFormElement | null;
8
+ takeFormDataSnapshot(): void;
9
+ }
10
+ export declare const ExmFormDirtyMixin: <T extends Constructor<LitElement & FormDirtyMixinClass>>(superClass: T) => Constructor<FormDirtyMixinInterface> & T;
@@ -0,0 +1,92 @@
1
+ import { __decorate } from "tslib";
2
+ import { LitElement } from 'lit';
3
+ import { state } from 'lit/decorators.js';
4
+ export class FormDirtyMixinClass extends LitElement {
5
+ }
6
+ export const ExmFormDirtyMixin = (superClass) => {
7
+ class FormDirtyMixinElement extends superClass {
8
+ constructor(...args) {
9
+ super(...args);
10
+ this.dirty = false;
11
+ this.onFormChanged = this.updateDirtyState.bind(this);
12
+ }
13
+ getForm() {
14
+ var _a, _b;
15
+ return (_b = (_a = this.shadowRoot) === null || _a === void 0 ? void 0 : _a.querySelector('form')) !== null && _b !== void 0 ? _b : null;
16
+ }
17
+ getCurrentFormData() {
18
+ const form = this.getForm();
19
+ if (!form)
20
+ return;
21
+ return new FormData(form);
22
+ }
23
+ // NOTE: We have to compare formdata like this... we can't do a direct comparison unfortunately
24
+ formDataEquals(formData1, formData2) {
25
+ if (!formData1 || !formData2)
26
+ return false;
27
+ return JSON.stringify([...formData1]) === JSON.stringify([...formData2]);
28
+ }
29
+ fireDirtyChanged() {
30
+ this.dispatchEvent(new CustomEvent('form-dirty-changed', {
31
+ detail: this.dirty,
32
+ bubbles: true,
33
+ composed: true,
34
+ }));
35
+ }
36
+ async updateDirtyState() {
37
+ await this.updateComplete;
38
+ const current = this.getCurrentFormData();
39
+ if (!current)
40
+ return;
41
+ if (this.formDataEquals(current, this.formDataSnapshot)) {
42
+ this.resetDirtyState();
43
+ return;
44
+ }
45
+ if (!this.dirty) {
46
+ this.dirty = true;
47
+ this.fireDirtyChanged();
48
+ }
49
+ }
50
+ resetDirtyState() {
51
+ if (this.dirty) {
52
+ this.dirty = false;
53
+ this.fireDirtyChanged();
54
+ }
55
+ }
56
+ // NOTE: Sometimes we want to make a snapshot from a form on for example drawer open instead of on firstUpdated
57
+ takeFormDataSnapshot() {
58
+ const form = this.getForm();
59
+ if (!form)
60
+ return;
61
+ this.formDataSnapshot = new FormData(form);
62
+ }
63
+ async firstUpdated() {
64
+ var _a;
65
+ // @ts-ignore
66
+ (_a = super.firstUpdated) === null || _a === void 0 ? void 0 : _a.call(this);
67
+ await this.updateComplete;
68
+ const form = this.getForm();
69
+ if (!form)
70
+ return;
71
+ this.takeFormDataSnapshot();
72
+ form.addEventListener('input', this.onFormChanged);
73
+ form.addEventListener('change', this.onFormChanged);
74
+ form.addEventListener('reset', this.onFormChanged);
75
+ }
76
+ async disconnectedCallback() {
77
+ var _a;
78
+ const form = this.getForm();
79
+ if (form) {
80
+ form.removeEventListener('input', this.onFormChanged);
81
+ form.removeEventListener('change', this.onFormChanged);
82
+ form.removeEventListener('reset', this.onFormChanged);
83
+ }
84
+ (_a = super.disconnectedCallback) === null || _a === void 0 ? void 0 : _a.call(this);
85
+ }
86
+ }
87
+ __decorate([
88
+ state()
89
+ ], FormDirtyMixinElement.prototype, "dirty", void 0);
90
+ return FormDirtyMixinElement;
91
+ };
92
+ //# sourceMappingURL=exm-form-dirty-mixin.js.map
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@exmg/exm-form",
3
- "version": "1.1.27",
3
+ "version": "1.1.29",
4
4
  "type": "module",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -31,7 +31,7 @@
31
31
  },
32
32
  "license": "MIT",
33
33
  "dependencies": {
34
- "@exmg/exm-button": "^1.1.27"
34
+ "@exmg/exm-button": "^1.1.29"
35
35
  },
36
36
  "peerDependencies": {
37
37
  "lit": "^3.2.1",
@@ -41,5 +41,5 @@
41
41
  "publishConfig": {
42
42
  "access": "public"
43
43
  },
44
- "gitHead": "4e9a663fa89175607c2cdffaf3611cc2125939f8"
44
+ "gitHead": "4f87060160e9545bc7190a0f5e1e47a311933e9c"
45
45
  }