@vaadin/crud 25.0.0-alpha2 → 25.0.0-alpha20

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.
@@ -307,7 +307,7 @@ export const CrudMixin = (superClass) =>
307
307
  *
308
308
  * The object has the following JSON structure and default values:
309
309
  *
310
- * ```
310
+ * ```js
311
311
  * {
312
312
  * newItem: 'New item',
313
313
  * editItem: 'Edit item',
@@ -377,18 +377,30 @@ export const CrudMixin = (superClass) =>
377
377
  return this.__fields;
378
378
  }
379
379
 
380
+ /** @private */
381
+ get _editor() {
382
+ return this.shadowRoot.querySelector('#editor');
383
+ }
384
+
385
+ /** @private */
386
+ get _scroller() {
387
+ return this.shadowRoot.querySelector('#scroller');
388
+ }
389
+
390
+ /** @private */
391
+ get _dialogMode() {
392
+ return this.editorPosition === '' || this._fullscreen;
393
+ }
394
+
380
395
  /** @protected */
381
396
  ready() {
382
397
  super.ready();
383
398
 
384
- this.$.dialog.$.overlay.addEventListener('vaadin-overlay-outside-click', this.__cancel);
385
- this.$.dialog.$.overlay.addEventListener('vaadin-overlay-escape-press', this.__cancel);
386
-
387
399
  this._gridController = new GridSlotController(this);
388
400
  this.addController(this._gridController);
389
401
 
390
402
  // Init button controllers in `ready()` (not constructor) so that Flow can set `_noDefaultButtons`
391
- this._newButtonController = new ButtonSlotController(this, 'new', 'primary', this._noDefaultButtons);
403
+ this._newButtonController = new ButtonSlotController(this, 'new', null, this._noDefaultButtons);
392
404
  this.addController(this._newButtonController);
393
405
 
394
406
  this._headerController = new SlotController(this, 'header', 'h3', {
@@ -416,6 +428,27 @@ export const CrudMixin = (superClass) =>
416
428
  );
417
429
 
418
430
  this.addController(this.__focusRestorationController);
431
+
432
+ this._confirmCancelDialog = this.querySelector('vaadin-confirm-dialog[slot="confirm-cancel"]');
433
+ this._confirmDeleteDialog = this.querySelector('vaadin-confirm-dialog[slot="confirm-delete"]');
434
+ }
435
+
436
+ /** @protected */
437
+ updated(props) {
438
+ super.updated(props);
439
+
440
+ // When using dialog mode, hide elements not slotted into the dialog from accessibility tree
441
+ if (
442
+ props.has('_grid') ||
443
+ props.has('_newButton') ||
444
+ props.has('editorOpened') ||
445
+ props.has('editorPosition') ||
446
+ props.has('_fullscreen')
447
+ ) {
448
+ const hide = this.editorOpened && this._dialogMode;
449
+ this.__hideElement(this._grid, hide);
450
+ this.__hideElement(this._newButton, hide);
451
+ }
419
452
  }
420
453
 
421
454
  /**
@@ -474,25 +507,24 @@ export const CrudMixin = (superClass) =>
474
507
  }
475
508
 
476
509
  if (opened) {
477
- this.__ensureChildren();
478
-
479
510
  // When using bottom / aside editor position,
480
511
  // auto-focus the editor element on open.
481
- if (this._form.parentElement === this) {
482
- this.$.editor.setAttribute('tabindex', '0');
483
- this.$.editor.focus();
484
- } else {
485
- this.$.editor.removeAttribute('tabindex');
512
+ if (this._editor) {
513
+ this._editor.focus();
486
514
  }
487
- } else if (oldOpened) {
488
- // Teleport form and buttons back to light DOM when closing overlay
489
- this.__moveChildNodes(this);
515
+
516
+ // Wait to set label until header node has updated (observer seems to run after this one)
517
+ setTimeout(() => {
518
+ this.__dialogAriaLabel = this._headerNode.textContent.trim();
519
+ });
490
520
  }
491
521
 
492
522
  this.__toggleToolbar();
493
523
 
494
524
  // Make sure to reset scroll position
495
- this.$.scroller.scrollTop = 0;
525
+ if (this._scroller) {
526
+ this._scroller.scrollTop = 0;
527
+ }
496
528
  }
497
529
 
498
530
  /** @private */
@@ -500,8 +532,6 @@ export const CrudMixin = (superClass) =>
500
532
  if (fullscreen || oldFullscreen) {
501
533
  this.__toggleToolbar();
502
534
 
503
- this.__ensureChildren();
504
-
505
535
  this.toggleAttribute('fullscreen', fullscreen);
506
536
  }
507
537
  }
@@ -514,66 +544,6 @@ export const CrudMixin = (superClass) =>
514
544
  }
515
545
  }
516
546
 
517
- /** @private */
518
- __moveChildNodes(target) {
519
- const nodes = [this._headerNode, this._form];
520
- const buttons = [this._saveButton, this._cancelButton, this._deleteButton].filter(Boolean);
521
- if (!nodes.every((node) => node instanceof HTMLElement)) {
522
- return;
523
- }
524
-
525
- // Teleport header node, form, and the buttons to corresponding slots.
526
- // NOTE: order in which buttons are moved matches the order of slots.
527
- [...nodes, ...buttons].forEach((node) => {
528
- // Do not move nodes if the editor position has not changed
529
- if (node.parentNode !== target) {
530
- target.appendChild(node);
531
- }
532
- });
533
-
534
- // Wait to set label until slotted element has been moved.
535
- setTimeout(() => {
536
- this.__dialogAriaLabel = this._headerNode.textContent.trim();
537
- });
538
- }
539
-
540
- /** @private */
541
- __shouldOpenDialog(fullscreen, editorPosition) {
542
- return editorPosition === '' || fullscreen;
543
- }
544
-
545
- /** @private */
546
- __ensureChildren() {
547
- if (this.__shouldOpenDialog(this._fullscreen, this.editorPosition)) {
548
- // Move form to dialog
549
- this.__moveChildNodes(this.$.dialog.$.overlay);
550
- } else {
551
- // Move form to crud
552
- this.__moveChildNodes(this);
553
- }
554
- }
555
-
556
- /** @private */
557
- __computeDialogOpened(opened, fullscreen, editorPosition) {
558
- // Only open dialog when editorPosition is "" or fullscreen is set
559
- return this.__shouldOpenDialog(fullscreen, editorPosition) ? opened : false;
560
- }
561
-
562
- /** @private */
563
- __computeEditorHidden(opened, fullscreen, editorPosition) {
564
- // Only show editor when editorPosition is "bottom" or "aside"
565
- if (['aside', 'bottom'].includes(editorPosition) && !fullscreen) {
566
- return !opened;
567
- }
568
-
569
- return true;
570
- }
571
-
572
- /** @private */
573
- __onDialogOpened(event) {
574
- this.editorOpened = event.detail.value;
575
- }
576
-
577
547
  /** @private */
578
548
  __onGridEdit(event) {
579
549
  event.stopPropagation();
@@ -617,8 +587,7 @@ export const CrudMixin = (superClass) =>
617
587
  * @private
618
588
  */
619
589
  __formChanged(form, oldForm) {
620
- if (oldForm && oldForm.parentElement) {
621
- oldForm.parentElement.removeChild(oldForm);
590
+ if (oldForm) {
622
591
  oldForm.removeEventListener('change', this.__onFormChange);
623
592
  oldForm.removeEventListener('input', this.__onFormChange);
624
593
  }
@@ -786,7 +755,7 @@ export const CrudMixin = (superClass) =>
786
755
  this.__isDirty && // Form change has been made
787
756
  this.editedItem !== item // Item is different
788
757
  ) {
789
- this.$.confirmCancel.opened = true;
758
+ this._confirmCancelDialog.opened = true;
790
759
  this.addEventListener(
791
760
  'cancel',
792
761
  (event) => {
@@ -986,7 +955,7 @@ export const CrudMixin = (superClass) =>
986
955
  /** @private */
987
956
  __cancel() {
988
957
  if (this.__isDirty) {
989
- this.$.confirmCancel.opened = true;
958
+ this._confirmCancelDialog.opened = true;
990
959
  } else {
991
960
  this.__confirmCancel();
992
961
  }
@@ -1003,7 +972,7 @@ export const CrudMixin = (superClass) =>
1003
972
 
1004
973
  /** @private */
1005
974
  __delete() {
1006
- this.$.confirmDelete.opened = true;
975
+ this._confirmDeleteDialog.opened = true;
1007
976
  }
1008
977
 
1009
978
  /** @private */
@@ -1020,6 +989,17 @@ export const CrudMixin = (superClass) =>
1020
989
  }
1021
990
  }
1022
991
 
992
+ /** @private */
993
+ __hideElement(element, value) {
994
+ if (!element) return;
995
+
996
+ if (value) {
997
+ element.setAttribute('aria-hidden', 'true');
998
+ } else {
999
+ element.removeAttribute('aria-hidden');
1000
+ }
1001
+ }
1002
+
1023
1003
  /**
1024
1004
  * Fired when user wants to edit an existing item. If the default is prevented, then
1025
1005
  * a new item is not assigned to the form, giving that responsibility to the app, though
@@ -132,11 +132,26 @@ export * from './vaadin-crud-mixin.js';
132
132
  *
133
133
  * ### Styling
134
134
  *
135
- * The following shadow DOM parts are available for styling:
135
+ * The following shadow DOM parts are available for styling when the editor is rendered next to, or below, the grid:
136
136
  *
137
137
  * Part name | Description
138
138
  * ----------------|----------------
139
- * `toolbar` | Toolbar container at the bottom. By default it contains the the `new` button
139
+ * `toolbar` | Toolbar container at the bottom of the grid. By default, it contains the `new` button
140
+ * `editor` | The editor container
141
+ * `scroller` | The wrapper for the header and the form
142
+ * `header` | The header of the editor
143
+ * `footer` | The footer of the editor
144
+ *
145
+ * The following shadow DOM parts are available for styling when the editor renders as a dialog:
146
+ *
147
+ * Part name | Description
148
+ * ----------------|----------------
149
+ * `toolbar` | Toolbar container at the bottom of the grid. By default, it contains the `new` button
150
+ * `overlay` | The dialog overlay
151
+ * `backdrop` | The dialog backdrop
152
+ * `header` | The header of the dialog
153
+ * `footer` | The footer of the dialog
154
+ * `content` | The wrapper for the form
140
155
  *
141
156
  * The following custom properties are available:
142
157
  *
@@ -13,14 +13,15 @@ import '@vaadin/confirm-dialog/src/vaadin-confirm-dialog.js';
13
13
  import './vaadin-crud-dialog.js';
14
14
  import './vaadin-crud-grid.js';
15
15
  import './vaadin-crud-form.js';
16
- import { html, LitElement } from 'lit';
16
+ import { html, LitElement, nothing, render } from 'lit';
17
17
  import { ifDefined } from 'lit/directives/if-defined.js';
18
18
  import { defineCustomElement } from '@vaadin/component-base/src/define.js';
19
19
  import { ElementMixin } from '@vaadin/component-base/src/element-mixin.js';
20
20
  import { PolylitMixin } from '@vaadin/component-base/src/polylit-mixin.js';
21
+ import { LumoInjectionMixin } from '@vaadin/vaadin-themable-mixin/lumo-injection-mixin.js';
21
22
  import { ThemableMixin } from '@vaadin/vaadin-themable-mixin/vaadin-themable-mixin.js';
23
+ import { crudStyles } from './styles/vaadin-crud-base-styles.js';
22
24
  import { CrudMixin } from './vaadin-crud-mixin.js';
23
- import { crudStyles } from './vaadin-crud-styles.js';
24
25
 
25
26
  /**
26
27
  * `<vaadin-crud>` is a Web Component for [CRUD](https://en.wikipedia.org/wiki/Create,_read,_update_and_delete) operations.
@@ -139,11 +140,26 @@ import { crudStyles } from './vaadin-crud-styles.js';
139
140
  *
140
141
  * ### Styling
141
142
  *
142
- * The following shadow DOM parts are available for styling:
143
+ * The following shadow DOM parts are available for styling when the editor is rendered next to, or below, the grid:
143
144
  *
144
145
  * Part name | Description
145
146
  * ----------------|----------------
146
- * `toolbar` | Toolbar container at the bottom. By default it contains the the `new` button
147
+ * `toolbar` | Toolbar container at the bottom of the grid. By default, it contains the `new` button
148
+ * `editor` | The editor container
149
+ * `scroller` | The wrapper for the header and the form
150
+ * `header` | The header of the editor
151
+ * `footer` | The footer of the editor
152
+ *
153
+ * The following shadow DOM parts are available for styling when the editor renders as a dialog:
154
+ *
155
+ * Part name | Description
156
+ * ----------------|----------------
157
+ * `toolbar` | Toolbar container at the bottom of the grid. By default, it contains the `new` button
158
+ * `overlay` | The dialog overlay
159
+ * `backdrop` | The dialog backdrop
160
+ * `header` | The header of the dialog
161
+ * `footer` | The footer of the dialog
162
+ * `content` | The wrapper for the form
147
163
  *
148
164
  * The following custom properties are available:
149
165
  *
@@ -170,7 +186,15 @@ import { crudStyles } from './vaadin-crud-styles.js';
170
186
  * @mixes ThemableMixin
171
187
  * @mixes CrudMixin
172
188
  */
173
- class Crud extends CrudMixin(ElementMixin(ThemableMixin(PolylitMixin(LitElement)))) {
189
+ class Crud extends CrudMixin(ElementMixin(ThemableMixin(PolylitMixin(LumoInjectionMixin(LitElement))))) {
190
+ static get is() {
191
+ return 'vaadin-crud';
192
+ }
193
+
194
+ static get cvdlName() {
195
+ return 'vaadin-crud';
196
+ }
197
+
174
198
  static get styles() {
175
199
  return crudStyles;
176
200
  }
@@ -188,71 +212,104 @@ class Crud extends CrudMixin(ElementMixin(ThemableMixin(PolylitMixin(LitElement)
188
212
  </div>
189
213
  </div>
190
214
 
191
- <div
192
- part="editor"
193
- id="editor"
194
- role="group"
195
- aria-labelledby="header"
196
- ?hidden="${this.__computeEditorHidden(this.editorOpened, this._fullscreen, this.editorPosition)}"
197
- >
198
- <div part="scroller" id="scroller">
199
- <div part="header" id="header">
200
- <slot name="header"></slot>
201
- </div>
202
- <slot name="form"></slot>
203
- </div>
215
+ ${!this._dialogMode
216
+ ? html`
217
+ <div
218
+ part="editor"
219
+ id="editor"
220
+ role="group"
221
+ aria-labelledby="header"
222
+ tabindex="0"
223
+ ?hidden="${!this.editorOpened}"
224
+ >
225
+ <div part="scroller" id="scroller">
226
+ <div part="header" id="header">
227
+ <slot name="header"></slot>
228
+ </div>
229
+ <slot name="form"></slot>
230
+ </div>
204
231
 
205
- <div part="footer" role="toolbar">
206
- <slot name="save-button"></slot>
207
- <slot name="cancel-button"></slot>
208
- <slot name="delete-button"></slot>
209
- </div>
210
- </div>
232
+ <div part="footer" role="toolbar">
233
+ <slot name="save-button"></slot>
234
+ <slot name="cancel-button"></slot>
235
+ <slot name="delete-button"></slot>
236
+ </div>
237
+ </div>
238
+ `
239
+ : nothing}
211
240
  </div>
212
241
 
213
- <vaadin-crud-dialog
214
- id="dialog"
215
- .opened="${this.__computeDialogOpened(this.editorOpened, this._fullscreen, this.editorPosition)}"
216
- .fullscreen="${this._fullscreen}"
217
- .ariaLabel="${this.__dialogAriaLabel}"
218
- .noCloseOnOutsideClick="${this.__isDirty}"
219
- .noCloseOnEsc="${this.__isDirty}"
220
- theme="${ifDefined(this._theme)}"
221
- @opened-changed="${this.__onDialogOpened}"
222
- ></vaadin-crud-dialog>
242
+ ${this._dialogMode
243
+ ? html`
244
+ <vaadin-crud-dialog
245
+ id="dialog"
246
+ aria-label="${ifDefined(this.__dialogAriaLabel)}"
247
+ theme="${ifDefined(this._theme)}"
248
+ exportparts="backdrop, overlay, header, content, footer"
249
+ .crudElement="${this}"
250
+ .opened="${this.editorOpened}"
251
+ .fullscreen="${this._fullscreen}"
252
+ .noCloseOnOutsideClick="${this.__isDirty}"
253
+ .noCloseOnEsc="${this.__isDirty}"
254
+ @cancel="${this.__cancel}"
255
+ >
256
+ <slot name="header" slot="header"></slot>
257
+ <slot name="form" slot="form"></slot>
258
+ <slot name="save-button" slot="save-button"></slot>
259
+ <slot name="cancel-button" slot="cancel-button"></slot>
260
+ <slot name="delete-button" slot="delete-button"></slot>
261
+ </vaadin-crud-dialog>
262
+ `
263
+ : nothing}
223
264
 
224
- <vaadin-confirm-dialog
225
- theme="${ifDefined(this._theme)}"
226
- id="confirmCancel"
227
- @confirm="${this.__confirmCancel}"
228
- cancel-button-visible
229
- .confirmText="${this.__effectiveI18n.confirm.cancel.button.confirm}"
230
- .cancelText="${this.__effectiveI18n.confirm.cancel.button.dismiss}"
231
- .header="${this.__effectiveI18n.confirm.cancel.title}"
232
- .message="${this.__effectiveI18n.confirm.cancel.content}"
233
- confirm-theme="primary"
234
- ></vaadin-confirm-dialog>
265
+ <slot name="confirm-cancel"></slot>
235
266
 
236
- <vaadin-confirm-dialog
237
- theme="${ifDefined(this._theme)}"
238
- id="confirmDelete"
239
- @confirm="${this.__confirmDelete}"
240
- cancel-button-visible
241
- .confirmText="${this.__effectiveI18n.confirm.delete.button.confirm}"
242
- .cancelText="${this.__effectiveI18n.confirm.delete.button.dismiss}"
243
- .header="${this.__effectiveI18n.confirm.delete.title}"
244
- .message="${this.__effectiveI18n.confirm.delete.content}"
245
- confirm-theme="primary error"
246
- ></vaadin-confirm-dialog>
267
+ <slot name="confirm-delete"></slot>
247
268
  `;
248
269
  }
249
270
 
250
- static get is() {
251
- return 'vaadin-crud';
271
+ /**
272
+ * Override update to render slotted overlays into light DOM after rendering shadow DOM.
273
+ * @param changedProperties
274
+ * @protected
275
+ */
276
+ update(changedProperties) {
277
+ super.update(changedProperties);
278
+
279
+ this.__renderSlottedOverlays();
252
280
  }
253
281
 
254
- static get cvdlName() {
255
- return 'vaadin-crud';
282
+ /** @private */
283
+ __renderSlottedOverlays() {
284
+ render(
285
+ html`
286
+ <vaadin-confirm-dialog
287
+ theme="${ifDefined(this._theme)}"
288
+ slot="confirm-cancel"
289
+ @confirm="${this.__confirmCancel}"
290
+ cancel-button-visible
291
+ .confirmText="${this.__effectiveI18n.confirm.cancel.button.confirm}"
292
+ .cancelText="${this.__effectiveI18n.confirm.cancel.button.dismiss}"
293
+ .header="${this.__effectiveI18n.confirm.cancel.title}"
294
+ .message="${this.__effectiveI18n.confirm.cancel.content}"
295
+ confirm-theme="primary"
296
+ ></vaadin-confirm-dialog>
297
+
298
+ <vaadin-confirm-dialog
299
+ theme="${ifDefined(this._theme)}"
300
+ slot="confirm-delete"
301
+ @confirm="${this.__confirmDelete}"
302
+ cancel-button-visible
303
+ .confirmText="${this.__effectiveI18n.confirm.delete.button.confirm}"
304
+ .cancelText="${this.__effectiveI18n.confirm.delete.button.dismiss}"
305
+ .header="${this.__effectiveI18n.confirm.delete.title}"
306
+ .message="${this.__effectiveI18n.confirm.delete.content}"
307
+ confirm-theme="primary error"
308
+ ></vaadin-confirm-dialog>
309
+ `,
310
+ this,
311
+ { host: this },
312
+ );
256
313
  }
257
314
  }
258
315
 
package/vaadin-crud.js CHANGED
@@ -1,2 +1,2 @@
1
- import './theme/lumo/vaadin-crud.js';
1
+ import './src/vaadin-crud.js';
2
2
  export * from './src/vaadin-crud.js';
package/web-types.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "$schema": "https://json.schemastore.org/web-types",
3
3
  "name": "@vaadin/crud",
4
- "version": "25.0.0-alpha2",
4
+ "version": "25.0.0-alpha20",
5
5
  "description-markup": "markdown",
6
6
  "contributions": {
7
7
  "html": {
@@ -10,6 +10,17 @@
10
10
  "name": "vaadin-crud-edit",
11
11
  "description": "`<vaadin-crud-edit>` is a helper element for `<vaadin-grid-column>` that provides\nan easily themable button that fires an `edit` event with the row item as detail\nwhen clicked.\n\nTypical usage is in a `<vaadin-grid-column>` of a custom `<vaadin-grid>` inside\na `<vaadin-crud>` to enable editing.",
12
12
  "attributes": [
13
+ {
14
+ "name": "disabled",
15
+ "description": "When disabled, the button is rendered as \"dimmed\" and prevents all\nuser interactions (mouse and keyboard).\n\nSince disabled buttons are not focusable and cannot react to hover\nevents by default, it can cause accessibility issues by making them\nentirely invisible to assistive technologies, and prevents the use\nof Tooltips to explain why the action is not available. This can be\naddressed by enabling the feature flag `accessibleDisabledButtons`,\nwhich makes disabled buttons focusable and hoverable, while still\npreventing them from being triggered:\n\n```js\n// Set before any button is attached to the DOM.\nwindow.Vaadin.featureFlags.accessibleDisabledButtons = true\n```",
16
+ "value": {
17
+ "type": [
18
+ "boolean",
19
+ "null",
20
+ "undefined"
21
+ ]
22
+ }
23
+ },
13
24
  {
14
25
  "name": "theme",
15
26
  "description": "The theme variants to apply to the component.",
@@ -23,7 +34,19 @@
23
34
  }
24
35
  ],
25
36
  "js": {
26
- "properties": [],
37
+ "properties": [
38
+ {
39
+ "name": "disabled",
40
+ "description": "When disabled, the button is rendered as \"dimmed\" and prevents all\nuser interactions (mouse and keyboard).\n\nSince disabled buttons are not focusable and cannot react to hover\nevents by default, it can cause accessibility issues by making them\nentirely invisible to assistive technologies, and prevents the use\nof Tooltips to explain why the action is not available. This can be\naddressed by enabling the feature flag `accessibleDisabledButtons`,\nwhich makes disabled buttons focusable and hoverable, while still\npreventing them from being triggered:\n\n```js\n// Set before any button is attached to the DOM.\nwindow.Vaadin.featureFlags.accessibleDisabledButtons = true\n```",
41
+ "value": {
42
+ "type": [
43
+ "boolean",
44
+ "null",
45
+ "undefined"
46
+ ]
47
+ }
48
+ }
49
+ ],
27
50
  "events": [
28
51
  {
29
52
  "name": "edit",
@@ -311,7 +334,7 @@
311
334
  },
312
335
  {
313
336
  "name": "renderer",
314
- "description": "Custom function for rendering the cell content.\nReceives three arguments:\n\n- `root` The cell content DOM element. Append your content to it.\n- `column` The `<vaadin-grid-column>` element.\n- `model` The object with the properties related with\n the rendered item, contains:\n - `model.index` The index of the item.\n - `model.item` The item.\n - `model.expanded` Sublevel toggle state.\n - `model.level` Level of the tree represented with a horizontal offset of the toggle button.\n - `model.selected` Selected state.\n - `model.detailsOpened` Details opened state.",
337
+ "description": "Custom function for rendering the cell content.\nReceives three arguments:\n\n- `root` The cell content DOM element. Append your content to it.\n- `column` The `<vaadin-grid-column>` element.\n- `model` The object with the properties related with\n the rendered item, contains:\n - `model.index` The index of the item.\n - `model.item` The item.\n - `model.expanded` Sublevel toggle state.\n - `model.level` Level of the tree represented with a horizontal offset of the toggle button.\n - `model.selected` Selected state.\n - `model.detailsOpened` Details opened state.\n - `model.hasChildren` Whether the item has children.",
315
338
  "value": {
316
339
  "type": [
317
340
  "GridBodyRenderer",
@@ -357,7 +380,7 @@
357
380
  },
358
381
  {
359
382
  "name": "vaadin-crud",
360
- "description": "`<vaadin-crud>` is a Web Component for [CRUD](https://en.wikipedia.org/wiki/Create,_read,_update_and_delete) operations.\n\n### Quick Start\n\nAssign an array to the [`items`](https://cdn.vaadin.com/vaadin-web-components/25.0.0-alpha2/#/elements/vaadin-crud#property-items) property.\n\nA grid and an editor will be automatically generated and configured based on the data structure provided.\n\n```html\n<vaadin-crud></vaadin-crud>\n```\n```js\nconst crud = document.querySelector('vaadin-crud');\n\ncrud.items = [\n { name: 'John', surname: 'Lennon', role: 'singer' },\n { name: 'Ringo', surname: 'Starr', role: 'drums' },\n // ... more items\n];\n```\n\n### Data Provider Function\n\nOtherwise, you can provide a [`dataProvider`](https://cdn.vaadin.com/vaadin-web-components/25.0.0-alpha2/#/elements/vaadin-crud#property-dataProvider) function.\n\n```js\nconst crud = document.querySelector('vaadin-crud');\n\nconst users = [\n { name: 'John', surname: 'Lennon', role: 'singer' },\n { name: 'Ringo', surname: 'Starr', role: 'drums' },\n // ... more items\n];\n\ncrud.dataProvider = (params, callback) => {\n const chunk = users.slice(params.page * params.pageSize, params.page * params.pageSize + params.pageSize);\n callback(chunk, people.length);\n};\n```\n\nNOTE: The auto-generated editor only supports string types. If you need to handle special cases\ncustomizing the editor is discussed below.\n\n### Customization\n\nAlternatively you can fully configure the component by using `slot` names.\n\nSlot name | Description\n---------------|----------------\n`grid` | To replace the auto-generated grid with a custom one.\n`form` | To replace the auto-generated form.\n`save-button` | To replace the \"Save\" button.\n`cancel-button`| To replace the \"Cancel\" button.\n`delete-button`| To replace the \"Delete\" button.\n`toolbar` | To provide the toolbar content (by default, it's empty).\n`new-button` | To replace the \"New item\" button.\n\n#### Example:\n\n```html\n<vaadin-crud id=\"crud\">\n <vaadin-grid slot=\"grid\">\n <vaadin-crud-edit-column></vaadin-crud-edit-column>\n <vaadin-grid-column id=\"column1\"></vaadin-grid-column>\n <vaadin-grid-column id=\"column2\"></vaadin-grid-column>\n </vaadin-grid>\n\n <vaadin-form-layout slot=\"form\">\n <vaadin-text-field label=\"First\" path=\"name\"></vaadin-text-field>\n <vaadin-text-field label=\"Surname\" path=\"surname\"></vaadin-text-field>\n </vaadin-form-layout>\n\n <div slot=\"toolbar\">Total singers: 2</div>\n <button slot=\"new-button\">New singer</button>\n\n <button slot=\"save-button\">Save changes</button>\n <button slot=\"cancel-button\">Discard changes</button>\n <button slot=\"delete-button\">Delete singer</button>\n</vaadin-crud>\n```\n```js\nconst crud = document.querySelector('#crud');\n\nconst column1 = document.querySelector('#column1');\ncolumn1.headerRenderer = (root, column) => {\n root.textContent = 'Name';\n};\ncolumn1.renderer = (root, column, model) => {\n root.textContent = model.item.name;\n};\n\nconst column2 = document.querySelector('#column2');\ncolumn2.headerRenderer = (root, column) => {\n root.textContent = 'Surname';\n};\ncolumn2.renderer = (root, column, model) => {\n root.textContent = model.item.surname;\n};\n\ncrud.items = [\n { name: 'John', surname: 'Lennon', role: 'singer' },\n { name: 'Ringo', surname: 'Starr', role: 'drums' },\n // ... more items\n];\n```\n\n### Helpers\n\nThe following elements are used to auto-configure the grid and the editor\n- [`<vaadin-crud-edit-column>`](https://cdn.vaadin.com/vaadin-web-components/25.0.0-alpha2/#/elements/vaadin-crud-edit-column)\n- `<vaadin-crud-grid>` - can be replaced with custom [`<vaadin-grid>`](https://cdn.vaadin.com/vaadin-web-components/25.0.0-alpha2/#/elements/vaadin-grid)\n- `<vaadin-crud-form>` - can be replaced with custom [`<vaadin-form-layout>`](https://cdn.vaadin.com/vaadin-web-components/25.0.0-alpha2/#/elements/vaadin-form-layout)\n\n### Styling\n\nThe following shadow DOM parts are available for styling:\n\nPart name | Description\n----------------|----------------\n`toolbar` | Toolbar container at the bottom. By default it contains the the `new` button\n\nThe following custom properties are available:\n\nCustom Property | Description | Default\n----------------|----------------\n--vaadin-crud-editor-max-height | max height of editor when opened on the bottom | 40%\n--vaadin-crud-editor-max-width | max width of editor when opened on the side | 40%\n\nSee [Styling Components](https://vaadin.com/docs/latest/styling/styling-components) documentation.",
383
+ "description": "`<vaadin-crud>` is a Web Component for [CRUD](https://en.wikipedia.org/wiki/Create,_read,_update_and_delete) operations.\n\n### Quick Start\n\nAssign an array to the [`items`](https://cdn.vaadin.com/vaadin-web-components/25.0.0-alpha20/#/elements/vaadin-crud#property-items) property.\n\nA grid and an editor will be automatically generated and configured based on the data structure provided.\n\n```html\n<vaadin-crud></vaadin-crud>\n```\n```js\nconst crud = document.querySelector('vaadin-crud');\n\ncrud.items = [\n { name: 'John', surname: 'Lennon', role: 'singer' },\n { name: 'Ringo', surname: 'Starr', role: 'drums' },\n // ... more items\n];\n```\n\n### Data Provider Function\n\nOtherwise, you can provide a [`dataProvider`](https://cdn.vaadin.com/vaadin-web-components/25.0.0-alpha20/#/elements/vaadin-crud#property-dataProvider) function.\n\n```js\nconst crud = document.querySelector('vaadin-crud');\n\nconst users = [\n { name: 'John', surname: 'Lennon', role: 'singer' },\n { name: 'Ringo', surname: 'Starr', role: 'drums' },\n // ... more items\n];\n\ncrud.dataProvider = (params, callback) => {\n const chunk = users.slice(params.page * params.pageSize, params.page * params.pageSize + params.pageSize);\n callback(chunk, people.length);\n};\n```\n\nNOTE: The auto-generated editor only supports string types. If you need to handle special cases\ncustomizing the editor is discussed below.\n\n### Customization\n\nAlternatively you can fully configure the component by using `slot` names.\n\nSlot name | Description\n---------------|----------------\n`grid` | To replace the auto-generated grid with a custom one.\n`form` | To replace the auto-generated form.\n`save-button` | To replace the \"Save\" button.\n`cancel-button`| To replace the \"Cancel\" button.\n`delete-button`| To replace the \"Delete\" button.\n`toolbar` | To provide the toolbar content (by default, it's empty).\n`new-button` | To replace the \"New item\" button.\n\n#### Example:\n\n```html\n<vaadin-crud id=\"crud\">\n <vaadin-grid slot=\"grid\">\n <vaadin-crud-edit-column></vaadin-crud-edit-column>\n <vaadin-grid-column id=\"column1\"></vaadin-grid-column>\n <vaadin-grid-column id=\"column2\"></vaadin-grid-column>\n </vaadin-grid>\n\n <vaadin-form-layout slot=\"form\">\n <vaadin-text-field label=\"First\" path=\"name\"></vaadin-text-field>\n <vaadin-text-field label=\"Surname\" path=\"surname\"></vaadin-text-field>\n </vaadin-form-layout>\n\n <div slot=\"toolbar\">Total singers: 2</div>\n <button slot=\"new-button\">New singer</button>\n\n <button slot=\"save-button\">Save changes</button>\n <button slot=\"cancel-button\">Discard changes</button>\n <button slot=\"delete-button\">Delete singer</button>\n</vaadin-crud>\n```\n```js\nconst crud = document.querySelector('#crud');\n\nconst column1 = document.querySelector('#column1');\ncolumn1.headerRenderer = (root, column) => {\n root.textContent = 'Name';\n};\ncolumn1.renderer = (root, column, model) => {\n root.textContent = model.item.name;\n};\n\nconst column2 = document.querySelector('#column2');\ncolumn2.headerRenderer = (root, column) => {\n root.textContent = 'Surname';\n};\ncolumn2.renderer = (root, column, model) => {\n root.textContent = model.item.surname;\n};\n\ncrud.items = [\n { name: 'John', surname: 'Lennon', role: 'singer' },\n { name: 'Ringo', surname: 'Starr', role: 'drums' },\n // ... more items\n];\n```\n\n### Helpers\n\nThe following elements are used to auto-configure the grid and the editor\n- [`<vaadin-crud-edit-column>`](https://cdn.vaadin.com/vaadin-web-components/25.0.0-alpha20/#/elements/vaadin-crud-edit-column)\n- `<vaadin-crud-grid>` - can be replaced with custom [`<vaadin-grid>`](https://cdn.vaadin.com/vaadin-web-components/25.0.0-alpha20/#/elements/vaadin-grid)\n- `<vaadin-crud-form>` - can be replaced with custom [`<vaadin-form-layout>`](https://cdn.vaadin.com/vaadin-web-components/25.0.0-alpha20/#/elements/vaadin-form-layout)\n\n### Styling\n\nThe following shadow DOM parts are available for styling when the editor is rendered next to, or below, the grid:\n\nPart name | Description\n----------------|----------------\n`toolbar` | Toolbar container at the bottom of the grid. By default, it contains the `new` button\n`editor` | The editor container\n`scroller` | The wrapper for the header and the form\n`header` | The header of the editor\n`footer` | The footer of the editor\n\nThe following shadow DOM parts are available for styling when the editor renders as a dialog:\n\nPart name | Description\n----------------|----------------\n`toolbar` | Toolbar container at the bottom of the grid. By default, it contains the `new` button\n`overlay` | The dialog overlay\n`backdrop` | The dialog backdrop\n`header` | The header of the dialog\n`footer` | The footer of the dialog\n`content` | The wrapper for the form\n\nThe following custom properties are available:\n\nCustom Property | Description | Default\n----------------|----------------\n--vaadin-crud-editor-max-height | max height of editor when opened on the bottom | 40%\n--vaadin-crud-editor-max-width | max width of editor when opened on the side | 40%\n\nSee [Styling Components](https://vaadin.com/docs/latest/styling/styling-components) documentation.",
361
384
  "attributes": [
362
385
  {
363
386
  "name": "i18n",
@@ -421,7 +444,7 @@
421
444
  },
422
445
  {
423
446
  "name": "include",
424
- "description": "A comma-separated list of fields to include in the generated grid and the generated editor.\n\nIt can be used to explicitly define the field order.\n\nWhen it is defined [`exclude`](https://cdn.vaadin.com/vaadin-web-components/25.0.0-alpha2/#/elements/vaadin-crud#property-exclude) is ignored.\n\nDefault is undefined meaning that all properties in the object should be mapped to fields.",
447
+ "description": "A comma-separated list of fields to include in the generated grid and the generated editor.\n\nIt can be used to explicitly define the field order.\n\nWhen it is defined [`exclude`](https://cdn.vaadin.com/vaadin-web-components/25.0.0-alpha20/#/elements/vaadin-crud#property-exclude) is ignored.\n\nDefault is undefined meaning that all properties in the object should be mapped to fields.",
425
448
  "value": {
426
449
  "type": [
427
450
  "string",
@@ -432,7 +455,7 @@
432
455
  },
433
456
  {
434
457
  "name": "exclude",
435
- "description": "A comma-separated list of fields to be excluded from the generated grid and the generated editor.\n\nWhen [`include`](https://cdn.vaadin.com/vaadin-web-components/25.0.0-alpha2/#/elements/vaadin-crud#property-include) is defined, this parameter is ignored.\n\nDefault is to exclude all private fields (those properties starting with underscore)",
458
+ "description": "A comma-separated list of fields to be excluded from the generated grid and the generated editor.\n\nWhen [`include`](https://cdn.vaadin.com/vaadin-web-components/25.0.0-alpha20/#/elements/vaadin-crud#property-include) is defined, this parameter is ignored.\n\nDefault is to exclude all private fields (those properties starting with underscore)",
436
459
  "value": {
437
460
  "type": [
438
461
  "string",
@@ -479,7 +502,7 @@
479
502
  "properties": [
480
503
  {
481
504
  "name": "i18n",
482
- "description": "The object used to localize this component. To change the default\nlocalization, replace this with an object that provides all properties, or\njust the individual properties you want to change.\n\nThe object has the following JSON structure and default values:\n\n```\n{\n newItem: 'New item',\n editItem: 'Edit item',\n saveItem: 'Save',\n cancel: 'Cancel',\n deleteItem: 'Delete...',\n editLabel: 'Edit',\n confirm: {\n delete: {\n title: 'Confirm delete',\n content: 'Are you sure you want to delete the selected item? This action cannot be undone.',\n button: {\n confirm: 'Delete',\n dismiss: 'Cancel'\n }\n },\n cancel: {\n title: 'Unsaved changes',\n content: 'There are unsaved modifications to the item.',\n button: {\n confirm: 'Discard',\n dismiss: 'Continue editing'\n }\n }\n }\n}\n```",
505
+ "description": "The object used to localize this component. To change the default\nlocalization, replace this with an object that provides all properties, or\njust the individual properties you want to change.\n\nThe object has the following JSON structure and default values:\n\n```js\n{\n newItem: 'New item',\n editItem: 'Edit item',\n saveItem: 'Save',\n cancel: 'Cancel',\n deleteItem: 'Delete...',\n editLabel: 'Edit',\n confirm: {\n delete: {\n title: 'Confirm delete',\n content: 'Are you sure you want to delete the selected item? This action cannot be undone.',\n button: {\n confirm: 'Delete',\n dismiss: 'Cancel'\n }\n },\n cancel: {\n title: 'Unsaved changes',\n content: 'There are unsaved modifications to the item.',\n button: {\n confirm: 'Discard',\n dismiss: 'Continue editing'\n }\n }\n }\n}\n```",
483
506
  "value": {
484
507
  "type": [
485
508
  "CrudI18n"
@@ -568,7 +591,7 @@
568
591
  },
569
592
  {
570
593
  "name": "include",
571
- "description": "A comma-separated list of fields to include in the generated grid and the generated editor.\n\nIt can be used to explicitly define the field order.\n\nWhen it is defined [`exclude`](https://cdn.vaadin.com/vaadin-web-components/25.0.0-alpha2/#/elements/vaadin-crud#property-exclude) is ignored.\n\nDefault is undefined meaning that all properties in the object should be mapped to fields.",
594
+ "description": "A comma-separated list of fields to include in the generated grid and the generated editor.\n\nIt can be used to explicitly define the field order.\n\nWhen it is defined [`exclude`](https://cdn.vaadin.com/vaadin-web-components/25.0.0-alpha20/#/elements/vaadin-crud#property-exclude) is ignored.\n\nDefault is undefined meaning that all properties in the object should be mapped to fields.",
572
595
  "value": {
573
596
  "type": [
574
597
  "string",
@@ -579,7 +602,7 @@
579
602
  },
580
603
  {
581
604
  "name": "exclude",
582
- "description": "A comma-separated list of fields to be excluded from the generated grid and the generated editor.\n\nWhen [`include`](https://cdn.vaadin.com/vaadin-web-components/25.0.0-alpha2/#/elements/vaadin-crud#property-include) is defined, this parameter is ignored.\n\nDefault is to exclude all private fields (those properties starting with underscore)",
605
+ "description": "A comma-separated list of fields to be excluded from the generated grid and the generated editor.\n\nWhen [`include`](https://cdn.vaadin.com/vaadin-web-components/25.0.0-alpha20/#/elements/vaadin-crud#property-include) is defined, this parameter is ignored.\n\nDefault is to exclude all private fields (those properties starting with underscore)",
583
606
  "value": {
584
607
  "type": [
585
608
  "string",