@vaadin/crud 23.0.0-alpha1 → 23.0.0-alpha5

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vaadin/crud",
3
- "version": "23.0.0-alpha1",
3
+ "version": "23.0.0-alpha5",
4
4
  "publishConfig": {
5
5
  "access": "public"
6
6
  },
@@ -18,6 +18,7 @@
18
18
  },
19
19
  "main": "vaadin-crud.js",
20
20
  "module": "vaadin-crud.js",
21
+ "type": "module",
21
22
  "files": [
22
23
  "src",
23
24
  "theme",
@@ -35,23 +36,22 @@
35
36
  "@open-wc/dedupe-mixin": "^1.3.0",
36
37
  "@polymer/iron-media-query": "^3.0.0",
37
38
  "@polymer/polymer": "^3.0.0",
38
- "@vaadin/button": "23.0.0-alpha1",
39
- "@vaadin/component-base": "23.0.0-alpha1",
40
- "@vaadin/confirm-dialog": "23.0.0-alpha1",
41
- "@vaadin/dialog": "23.0.0-alpha1",
42
- "@vaadin/form-layout": "23.0.0-alpha1",
43
- "@vaadin/grid": "23.0.0-alpha1",
44
- "@vaadin/text-field": "23.0.0-alpha1",
39
+ "@vaadin/button": "23.0.0-alpha5",
40
+ "@vaadin/component-base": "23.0.0-alpha5",
41
+ "@vaadin/confirm-dialog": "23.0.0-alpha5",
42
+ "@vaadin/dialog": "23.0.0-alpha5",
43
+ "@vaadin/form-layout": "23.0.0-alpha5",
44
+ "@vaadin/grid": "23.0.0-alpha5",
45
+ "@vaadin/text-field": "23.0.0-alpha5",
45
46
  "@vaadin/vaadin-license-checker": "^2.1.0",
46
- "@vaadin/vaadin-lumo-styles": "23.0.0-alpha1",
47
- "@vaadin/vaadin-material-styles": "23.0.0-alpha1",
48
- "@vaadin/vaadin-themable-mixin": "23.0.0-alpha1"
47
+ "@vaadin/vaadin-lumo-styles": "23.0.0-alpha5",
48
+ "@vaadin/vaadin-material-styles": "23.0.0-alpha5",
49
+ "@vaadin/vaadin-themable-mixin": "23.0.0-alpha5"
49
50
  },
50
51
  "devDependencies": {
51
52
  "@esm-bundle/chai": "^4.3.4",
52
- "@vaadin/polymer-legacy-adapter": "23.0.0-alpha1",
53
53
  "@vaadin/testing-helpers": "^0.3.2",
54
54
  "sinon": "^9.2.1"
55
55
  },
56
- "gitHead": "fbcb07328fdf88260e3b461088d207426b21c710"
56
+ "gitHead": "74f9294964eb8552d96578c14af6ad214f5257bc"
57
57
  }
@@ -0,0 +1,121 @@
1
+ /**
2
+ * @license
3
+ * Copyright (c) 2018 - 2022 Vaadin Ltd.
4
+ * This program is available under Commercial Vaadin Developer License 4.0, available at https://vaadin.com/license/cvdl-4.0.
5
+ */
6
+ import { html } from '@polymer/polymer/lib/utils/html-tag.js';
7
+ import { Dialog, DialogOverlay } from '@vaadin/dialog/src/vaadin-dialog.js';
8
+ import { css, registerStyles } from '@vaadin/vaadin-themable-mixin/vaadin-themable-mixin.js';
9
+
10
+ registerStyles(
11
+ 'vaadin-crud-dialog-overlay',
12
+ css`
13
+ [part='overlay'] {
14
+ max-width: 54em;
15
+ min-width: 20em;
16
+ }
17
+
18
+ [part='content'] {
19
+ display: flex;
20
+ flex-direction: column;
21
+ padding: 0;
22
+ }
23
+
24
+ [part='scroller'] {
25
+ display: flex;
26
+ flex-direction: column;
27
+ overflow: auto;
28
+ flex: auto;
29
+ }
30
+
31
+ [part='footer'] {
32
+ display: flex;
33
+ flex: none;
34
+ flex-direction: row-reverse;
35
+ }
36
+
37
+ :host([fullscreen]) {
38
+ top: 0;
39
+ left: 0;
40
+ right: 0;
41
+ bottom: 0;
42
+ padding: 0;
43
+ }
44
+
45
+ :host([fullscreen]) [part='overlay'] {
46
+ height: 100vh;
47
+ width: 100vw;
48
+ border-radius: 0 !important;
49
+ }
50
+
51
+ :host([fullscreen]) [part='content'] {
52
+ flex: 1;
53
+ }
54
+ `,
55
+ { moduleId: 'vaadin-crud-dialog-overlay-styles' }
56
+ );
57
+
58
+ let memoizedTemplate;
59
+
60
+ const editorTemplate = html`
61
+ <div part="scroller" role="group" aria-labelledby="header">
62
+ <div part="header" id="header">
63
+ <slot name="header"></slot>
64
+ </div>
65
+ <slot name="form"></slot>
66
+ </div>
67
+
68
+ <div part="footer" role="toolbar">
69
+ <slot name="save-button"></slot>
70
+ <slot name="cancel-button"></slot>
71
+ <slot name="delete-button"></slot>
72
+ </div>
73
+ `;
74
+
75
+ class CrudDialogOverlay extends DialogOverlay {
76
+ static get is() {
77
+ return 'vaadin-crud-dialog-overlay';
78
+ }
79
+
80
+ static get template() {
81
+ if (!memoizedTemplate) {
82
+ memoizedTemplate = super.template.cloneNode(true);
83
+ const contentPart = memoizedTemplate.content.querySelector('[part="content"]');
84
+ const defaultSlot = contentPart.querySelector('slot:not([name])');
85
+ contentPart.removeChild(defaultSlot);
86
+ contentPart.appendChild(editorTemplate.content.cloneNode(true));
87
+ }
88
+ return memoizedTemplate;
89
+ }
90
+ }
91
+
92
+ customElements.define('vaadin-crud-dialog-overlay', CrudDialogOverlay);
93
+
94
+ class CrudDialog extends Dialog {
95
+ /**
96
+ * Override template to provide custom overlay tag name.
97
+ */
98
+ static get template() {
99
+ return html`
100
+ <style>
101
+ :host {
102
+ display: none;
103
+ }
104
+ </style>
105
+
106
+ <vaadin-crud-dialog-overlay
107
+ id="overlay"
108
+ on-opened-changed="_onOverlayOpened"
109
+ on-mousedown="_bringOverlayToFront"
110
+ on-touchstart="_bringOverlayToFront"
111
+ theme$="[[theme]]"
112
+ modeless="[[modeless]]"
113
+ with-backdrop="[[!modeless]]"
114
+ resizable$="[[resizable]]"
115
+ focus-trap
116
+ ></vaadin-crud-dialog-overlay>
117
+ `;
118
+ }
119
+ }
120
+
121
+ customElements.define('vaadin-crud-dialog', CrudDialog);
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * @license
3
- * Copyright (c) 2021 Vaadin Ltd.
3
+ * Copyright (c) 2018 - 2022 Vaadin Ltd.
4
4
  * This program is available under Apache License Version 2.0, available at https://vaadin.com/license/
5
5
  */
6
6
  import { GridColumn } from '@vaadin/grid/src/vaadin-grid-column.js';
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * @license
3
- * Copyright (c) 2017 - 2021 Vaadin Ltd.
3
+ * Copyright (c) 2018 - 2022 Vaadin Ltd.
4
4
  * This program is available under Commercial Vaadin Developer License 4.0, available at https://vaadin.com/license/cvdl-4.0.
5
5
  */
6
6
  import './vaadin-crud-edit.js';
@@ -1,9 +1,9 @@
1
1
  /**
2
2
  * @license
3
- * Copyright (c) 2021 Vaadin Ltd.
3
+ * Copyright (c) 2018 - 2022 Vaadin Ltd.
4
4
  * This program is available under Apache License Version 2.0, available at https://vaadin.com/license/
5
5
  */
6
- import { ThemableMixin } from '@vaadin/vaadin-themable-mixin/vaadin-themable-mixin.js';
6
+ import { Button } from '@vaadin/button/src/vaadin-button.js';
7
7
 
8
8
  /**
9
9
  * `<vaadin-crud-edit>` is a helper element for `<vaadin-grid-column>` that provides
@@ -13,7 +13,7 @@ import { ThemableMixin } from '@vaadin/vaadin-themable-mixin/vaadin-themable-mix
13
13
  * Typical usage is in a `<vaadin-grid-column>` of a custom `<vaadin-grid>` inside
14
14
  * a `<vaadin-crud>` to enable editing.
15
15
  */
16
- declare class CrudEdit extends ThemableMixin(HTMLElement) {}
16
+ declare class CrudEdit extends Button {}
17
17
 
18
18
  declare global {
19
19
  interface HTMLElementTagNameMap {
@@ -1,10 +1,10 @@
1
1
  /**
2
2
  * @license
3
- * Copyright (c) 2017 - 2021 Vaadin Ltd.
3
+ * Copyright (c) 2018 - 2022 Vaadin Ltd.
4
4
  * This program is available under Commercial Vaadin Developer License 4.0, available at https://vaadin.com/license/cvdl-4.0.
5
5
  */
6
- import { html, PolymerElement } from '@polymer/polymer/polymer-element.js';
7
- import { ThemableMixin } from '@vaadin/vaadin-themable-mixin/vaadin-themable-mixin.js';
6
+ import { html } from '@polymer/polymer/polymer-element.js';
7
+ import { Button } from '@vaadin/button/src/vaadin-button.js';
8
8
 
9
9
  /**
10
10
  * `<vaadin-crud-edit>` is a helper element for `<vaadin-grid-column>` that provides
@@ -17,7 +17,7 @@ import { ThemableMixin } from '@vaadin/vaadin-themable-mixin/vaadin-themable-mix
17
17
  * @extends HTMLElement
18
18
  * @mixes ThemableMixin
19
19
  */
20
- class CrudEdit extends ThemableMixin(PolymerElement) {
20
+ class CrudEdit extends Button {
21
21
  static get template() {
22
22
  return html`
23
23
  <style>
@@ -25,6 +25,7 @@ class CrudEdit extends ThemableMixin(PolymerElement) {
25
25
  display: block;
26
26
  }
27
27
  </style>
28
+ <div part="icon"></div>
28
29
  `;
29
30
  }
30
31
 
@@ -37,7 +38,6 @@ class CrudEdit extends ThemableMixin(PolymerElement) {
37
38
  super.ready();
38
39
  this.addEventListener('click', this.__onClick);
39
40
  this.setAttribute('aria-label', 'Edit');
40
- this.setAttribute('role', 'button');
41
41
  }
42
42
 
43
43
  /** @private */
@@ -57,4 +57,4 @@ class CrudEdit extends ThemableMixin(PolymerElement) {
57
57
  */
58
58
  }
59
59
 
60
- window.customElements.define(CrudEdit.is, CrudEdit);
60
+ customElements.define(CrudEdit.is, CrudEdit);
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * @license
3
- * Copyright (c) 2021 Vaadin Ltd.
3
+ * Copyright (c) 2018 - 2022 Vaadin Ltd.
4
4
  * This program is available under Apache License Version 2.0, available at https://vaadin.com/license/
5
5
  */
6
6
  import { FormLayout } from '@vaadin/form-layout/src/vaadin-form-layout.js';
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * @license
3
- * Copyright (c) 2017 - 2021 Vaadin Ltd.
3
+ * Copyright (c) 2018 - 2022 Vaadin Ltd.
4
4
  * This program is available under Commercial Vaadin Developer License 4.0, available at https://vaadin.com/license/cvdl-4.0.
5
5
  */
6
6
  import '@vaadin/text-field/src/vaadin-text-field.js';
@@ -44,7 +44,7 @@ class CrudForm extends IncludedMixin(FormLayout) {
44
44
  this.innerHTML = '';
45
45
  this._fields = [];
46
46
  this.__createFields(this, object);
47
- this.notifyResize();
47
+ this._updateLayout();
48
48
  }
49
49
 
50
50
  /** @private */
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * @license
3
- * Copyright (c) 2021 Vaadin Ltd.
3
+ * Copyright (c) 2018 - 2022 Vaadin Ltd.
4
4
  * This program is available under Apache License Version 2.0, available at https://vaadin.com/license/
5
5
  */
6
6
  import { Grid } from '@vaadin/grid/src/vaadin-grid.js';
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * @license
3
- * Copyright (c) 2017 - 2021 Vaadin Ltd.
3
+ * Copyright (c) 2018 - 2022 Vaadin Ltd.
4
4
  * This program is available under Commercial Vaadin Developer License 4.0, available at https://vaadin.com/license/cvdl-4.0.
5
5
  */
6
6
  import '@vaadin/grid/src/vaadin-grid-column.js';
@@ -109,10 +109,27 @@ class CrudGrid extends IncludedMixin(Grid) {
109
109
  */
110
110
  _configure(item) {
111
111
  this.innerHTML = '';
112
- this.__createColumns(this, item);
112
+ this.__createColumns(this, item, undefined, this.__getPropertyDepth(item));
113
113
  this.__toggleEditColumn();
114
114
  }
115
115
 
116
+ /**
117
+ * Return the deepest property depth of the object
118
+ * @private
119
+ */
120
+ __getPropertyDepth(object) {
121
+ if (!object || typeof object !== 'object') {
122
+ return 0;
123
+ }
124
+
125
+ return Object.keys(object).reduce((deepest, prop) => {
126
+ if (this.exclude && this.exclude.test(prop)) {
127
+ return deepest;
128
+ }
129
+ return Math.max(deepest, 1 + this.__getPropertyDepth(object[prop]));
130
+ }, 0);
131
+ }
132
+
116
133
  /**
117
134
  * Parse the camelCase column names into sentence case headers.
118
135
  * @param {string} path
@@ -130,25 +147,38 @@ class CrudGrid extends IncludedMixin(Grid) {
130
147
 
131
148
  /** @private */
132
149
  __createColumn(parent, path) {
133
- const col = document.createElement('vaadin-grid-column');
134
-
135
- col.renderer = (root, column, model) => {
136
- root.textContent = path ? this.get(path, model.item) : model.item;
137
- };
150
+ let col;
151
+ if (!this.noFilter && !this.noSort && !parent.__sortColumnGroup) {
152
+ // This crud-grid has both a sorter and a filter, but neither has yet been
153
+ // created => col should become the sorter group column
154
+ col = this.__createGroup(parent);
155
+ col.__sortColumnGroup = true;
156
+ // Create the filter column under this sorter group column
157
+ this.__createColumn(col, path);
158
+ } else {
159
+ // In all other cases, col should be a regular column with a renderer
160
+ col = document.createElement('vaadin-grid-column');
161
+ parent.appendChild(col);
162
+ col.renderer = (root, _column, model) => {
163
+ root.textContent = path ? this.get(path, model.item) : model.item;
164
+ };
165
+ }
138
166
 
139
167
  if (!this.noHead && path) {
168
+ // Create a header renderer for the column (or column group)
140
169
  col.headerRenderer = (root) => {
141
170
  const label = this._generateHeader(path);
142
171
 
143
- if (!this.noSort) {
144
- const sorter = window.document.createElement('vaadin-grid-sorter');
172
+ if (col.__sortColumnGroup || (this.noFilter && !this.noSort)) {
173
+ // The column is either the sorter group column or the root level
174
+ // sort column (in case a filter isn't used at all) => add the sort indicator
175
+ const sorter = document.createElement('vaadin-grid-sorter');
145
176
  sorter.setAttribute('path', path);
146
177
  sorter.textContent = label;
147
178
  root.appendChild(sorter);
148
- }
149
-
150
- if (!this.noFilter) {
151
- const filter = window.document.createElement('vaadin-grid-filter');
179
+ } else if (!this.noFilter) {
180
+ // Filtering is enabled in this crud-grid, create the filter element
181
+ const filter = document.createElement('vaadin-grid-filter');
152
182
  filter.setAttribute('path', path);
153
183
  filter.style.display = 'flex';
154
184
 
@@ -164,42 +194,63 @@ class CrudGrid extends IncludedMixin(Grid) {
164
194
 
165
195
  filter.appendChild(textField);
166
196
  root.appendChild(filter);
167
- }
168
-
169
- if (this.noSort && this.noFilter) {
197
+ } else if (this.noSort && this.noFilter) {
198
+ // Neither sorter nor filter are enabled, just add the label
170
199
  root.textContent = label;
171
200
  }
172
201
  };
173
202
  }
174
-
175
- parent.appendChild(col);
176
- return col;
177
203
  }
178
204
 
179
- /** @private */
180
- __createColumns(parent, object, path) {
181
- if (typeof object === 'object') {
205
+ /**
206
+ * Creates the column structure for the (sub)object.
207
+ *
208
+ * @param {HTMLElement} parent May be the crud-grid or a column group.
209
+ * @param {Object} object The object to create the sub-columns for.
210
+ * @param {string} path The property path from the root item to the object.
211
+ * @param {number} depth The depth of the object in the object hierarchy.
212
+ * @private
213
+ **/
214
+ __createColumns(parent, object, path, depth) {
215
+ if (object && typeof object === 'object') {
216
+ // Iterate over the object properties
182
217
  Object.keys(object).forEach((prop) => {
183
218
  if (!this.include && this.exclude && this.exclude.test(prop)) {
184
219
  return;
185
220
  }
186
- const newPath = (path ? `${path}.` : '') + prop;
187
- if (object[prop] && typeof object[prop] === 'object') {
188
- const group = this.noHead ? parent : this.__createGroup(parent, newPath, object[prop]);
189
- this.__createColumns(group, object[prop], newPath);
190
- } else {
191
- this.__createColumn(parent, newPath);
221
+ // Sub-object of the current object
222
+ const subObject = object[prop];
223
+ // Full path to the sub-object
224
+ const subObjectPath = path ? `${path}.${prop}` : prop;
225
+
226
+ // The column element for the sub-object
227
+ let subObjectColumn = parent;
228
+ if (!this.noHead && depth > 1) {
229
+ const isSubObject = subObject && typeof subObject === 'object';
230
+ // If the sub-object is an actual object, create a column group with the property
231
+ // name as the header text, otherwise create a group without a header
232
+ subObjectColumn = this.__createGroup(parent, isSubObject ? prop : undefined);
192
233
  }
234
+
235
+ // Run recursively for the sub-object level
236
+ this.__createColumns(subObjectColumn, subObject, subObjectPath, depth - 1);
193
237
  });
238
+ } else if (depth > 1) {
239
+ // The object has been fully traversed, but empty wrapping column
240
+ // groups are still needed to complete the full object depth
241
+ this.__createColumns(this.__createGroup(parent), undefined, path, depth - 1);
194
242
  } else {
195
- this.__createColumn(parent, '');
243
+ // The column group depth is complete, create the actual leaf column
244
+ this.__createColumn(parent, path);
196
245
  }
197
246
  }
198
247
 
199
248
  /** @private */
200
- __createGroup(parent, path) {
249
+ __createGroup(parent, header) {
201
250
  const grp = document.createElement('vaadin-grid-column-group');
202
- grp.headerRenderer = (root) => (root.textContent = this.__capitalize(path.replace(/^.*\./, '')));
251
+ if (header) {
252
+ grp.header = this.__capitalize(header);
253
+ }
203
254
  parent.appendChild(grp);
204
255
  return grp;
205
256
  }
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * @license
3
- * Copyright (c) 2021 Vaadin Ltd.
3
+ * Copyright (c) 2018 - 2022 Vaadin Ltd.
4
4
  * This program is available under Apache License Version 2.0, available at https://vaadin.com/license/
5
5
  */
6
6
  import { Constructor } from '@open-wc/dedupe-mixin';
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * @license
3
- * Copyright (c) 2017 - 2021 Vaadin Ltd.
3
+ * Copyright (c) 2018 - 2022 Vaadin Ltd.
4
4
  * This program is available under Commercial Vaadin Developer License 4.0, available at https://vaadin.com/license/cvdl-4.0.
5
5
  */
6
6
 
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * @license
3
- * Copyright (c) 2021 Vaadin Ltd.
3
+ * Copyright (c) 2018 - 2022 Vaadin Ltd.
4
4
  * This program is available under Apache License Version 2.0, available at https://vaadin.com/license/
5
5
  */
6
6
  import { ElementMixin } from '@vaadin/component-base/src/element-mixin.js';
@@ -335,7 +335,7 @@ declare class Crud<Item> extends ElementMixin(ThemableMixin(HTMLElement)) {
335
335
  readonly size: number | null | undefined;
336
336
 
337
337
  /**
338
- * Controls visiblity state of toolbar.
338
+ * Controls visibility state of toolbar.
339
339
  * When set to false toolbar is hidden and shown when set to true.
340
340
  * @attr {boolean} no-toolbar
341
341
  */