@vaadin/crud 25.0.0-alpha8 → 25.0.0-alpha9

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": "25.0.0-alpha8",
3
+ "version": "25.0.0-alpha9",
4
4
  "publishConfig": {
5
5
  "access": "public"
6
6
  },
@@ -21,6 +21,8 @@
21
21
  "type": "module",
22
22
  "files": [
23
23
  "src",
24
+ "!src/styles/*-base-styles.d.ts",
25
+ "!src/styles/*-base-styles.js",
24
26
  "theme",
25
27
  "vaadin-*.d.ts",
26
28
  "vaadin-*.js",
@@ -35,22 +37,22 @@
35
37
  ],
36
38
  "dependencies": {
37
39
  "@open-wc/dedupe-mixin": "^1.3.0",
38
- "@vaadin/a11y-base": "25.0.0-alpha8",
39
- "@vaadin/button": "25.0.0-alpha8",
40
- "@vaadin/component-base": "25.0.0-alpha8",
41
- "@vaadin/confirm-dialog": "25.0.0-alpha8",
42
- "@vaadin/dialog": "25.0.0-alpha8",
43
- "@vaadin/form-layout": "25.0.0-alpha8",
44
- "@vaadin/grid": "25.0.0-alpha8",
45
- "@vaadin/overlay": "25.0.0-alpha8",
46
- "@vaadin/text-field": "25.0.0-alpha8",
47
- "@vaadin/vaadin-lumo-styles": "25.0.0-alpha8",
48
- "@vaadin/vaadin-themable-mixin": "25.0.0-alpha8",
40
+ "@vaadin/a11y-base": "25.0.0-alpha9",
41
+ "@vaadin/button": "25.0.0-alpha9",
42
+ "@vaadin/component-base": "25.0.0-alpha9",
43
+ "@vaadin/confirm-dialog": "25.0.0-alpha9",
44
+ "@vaadin/dialog": "25.0.0-alpha9",
45
+ "@vaadin/form-layout": "25.0.0-alpha9",
46
+ "@vaadin/grid": "25.0.0-alpha9",
47
+ "@vaadin/overlay": "25.0.0-alpha9",
48
+ "@vaadin/text-field": "25.0.0-alpha9",
49
+ "@vaadin/vaadin-lumo-styles": "25.0.0-alpha9",
50
+ "@vaadin/vaadin-themable-mixin": "25.0.0-alpha9",
49
51
  "lit": "^3.0.0"
50
52
  },
51
53
  "devDependencies": {
52
- "@vaadin/chai-plugins": "25.0.0-alpha8",
53
- "@vaadin/test-runner-commands": "25.0.0-alpha8",
54
+ "@vaadin/chai-plugins": "25.0.0-alpha9",
55
+ "@vaadin/test-runner-commands": "25.0.0-alpha9",
54
56
  "@vaadin/testing-helpers": "^2.0.0",
55
57
  "sinon": "^18.0.0"
56
58
  },
@@ -59,5 +61,5 @@
59
61
  "web-types.json",
60
62
  "web-types.lit.json"
61
63
  ],
62
- "gitHead": "ebf53673d5f639d2b1b6f2b31f640f530643ee2f"
64
+ "gitHead": "bbe4720721e0955ffc87a79b412bee38b1f0eb1e"
63
65
  }
@@ -0,0 +1,13 @@
1
+ /**
2
+ * @license
3
+ * Copyright (c) 2000 - 2025 Vaadin Ltd.
4
+ *
5
+ * This program is available under Vaadin Commercial License and Service Terms.
6
+ *
7
+ *
8
+ * See https://vaadin.com/commercial-license-and-service-terms for the full
9
+ * license.
10
+ */
11
+ import type { CSSResult } from 'lit';
12
+
13
+ export const crudStyles: CSSResult;
@@ -0,0 +1,162 @@
1
+ /**
2
+ * @license
3
+ * Copyright (c) 2000 - 2025 Vaadin Ltd.
4
+ *
5
+ * This program is available under Vaadin Commercial License and Service Terms.
6
+ *
7
+ *
8
+ * See https://vaadin.com/commercial-license-and-service-terms for the full
9
+ * license.
10
+ */
11
+ import '@vaadin/component-base/src/style-props.js';
12
+ import { css } from 'lit';
13
+
14
+ export const crudStyles = css`
15
+ :host {
16
+ --vaadin-grid-border-width: 0px;
17
+ --vaadin-grid-border-radius: var(--vaadin-crud-border-radius, var(--vaadin-radius-l));
18
+ --vaadin-crud-editor-max-height: 40%;
19
+ --vaadin-crud-editor-max-width: 40%;
20
+ border: var(--vaadin-crud-border-width, 1px) solid var(--vaadin-crud-border-color, var(--vaadin-border-color));
21
+ border-radius: var(--vaadin-crud-border-radius, var(--vaadin-radius-l));
22
+ height: 400px;
23
+ width: 100%;
24
+ background: var(--vaadin-crud-background, var(--vaadin-background-color));
25
+ }
26
+
27
+ :host,
28
+ #main {
29
+ align-self: stretch;
30
+ display: flex;
31
+ flex-direction: column;
32
+ position: relative;
33
+ }
34
+
35
+ #main {
36
+ flex: 1 1 100%;
37
+ height: 100%;
38
+ min-width: 0;
39
+ min-height: 0;
40
+ }
41
+
42
+ ::slotted(vaadin-crud-grid) {
43
+ border-end-start-radius: 0;
44
+ border-end-end-radius: 0;
45
+ }
46
+
47
+ :host([hidden]),
48
+ [hidden] {
49
+ display: none !important;
50
+ }
51
+
52
+ #container {
53
+ display: flex;
54
+ height: 100%;
55
+ }
56
+
57
+ :host([editor-position='bottom']) #container {
58
+ flex-direction: column;
59
+ }
60
+
61
+ :host([editor-position='aside'][editor-opened]) #main {
62
+ border-inline-end: var(--vaadin-crud-border-width, 1px) solid
63
+ var(--vaadin-crud-border-color, var(--vaadin-border-color));
64
+ }
65
+
66
+ :host([editor-position='aside'][editor-opened]) ::slotted(vaadin-crud-grid) {
67
+ border-start-end-radius: 0;
68
+ border-end-end-radius: 0;
69
+ }
70
+
71
+ :host([editor-position='aside'][editor-opened]) :is(#container, [part='editor']) {
72
+ border-start-end-radius: inherit;
73
+ border-end-end-radius: inherit;
74
+ }
75
+
76
+ :host([editor-position='bottom'][editor-opened]) #main {
77
+ border-bottom: var(--vaadin-crud-border-width, 1px) solid
78
+ var(--vaadin-crud-border-color, var(--vaadin-border-color));
79
+ }
80
+
81
+ :host([editor-position='bottom'][editor-opened]) :is(#container, [part='editor']) {
82
+ border-end-start-radius: inherit;
83
+ border-end-end-radius: inherit;
84
+ }
85
+
86
+ [part='toolbar'] {
87
+ align-items: baseline;
88
+ background: var(--vaadin-crud-toolbar-background, transparent);
89
+ border-top: var(--vaadin-crud-border-width, 1px) solid var(--vaadin-crud-border-color, var(--vaadin-border-color));
90
+ display: flex;
91
+ flex-shrink: 0;
92
+ justify-content: flex-end;
93
+ padding: var(--vaadin-crud-toolbar-padding, var(--vaadin-padding));
94
+ }
95
+
96
+ :host([no-toolbar]) [part='toolbar'] {
97
+ display: none;
98
+ }
99
+
100
+ [part='editor'] {
101
+ display: flex;
102
+ flex-direction: column;
103
+ height: 100%;
104
+ z-index: 1;
105
+ }
106
+
107
+ [part='editor']:focus-visible {
108
+ outline: var(--vaadin-focus-ring-width) solid var(--vaadin-focus-ring-color);
109
+ }
110
+
111
+ :host(:not([editor-position=''])[editor-opened]:not([fullscreen])) [part='editor'] {
112
+ flex: 1 0 100%;
113
+ }
114
+
115
+ :host([editor-position='bottom'][editor-opened]:not([fullscreen])) [part='editor'] {
116
+ max-height: var(--vaadin-crud-editor-max-height);
117
+ }
118
+
119
+ :host([editor-position='aside'][editor-opened]:not([fullscreen])) [part='editor'] {
120
+ max-width: var(--vaadin-crud-editor-max-width);
121
+ min-width: 300px;
122
+ }
123
+
124
+ [part='scroller'] {
125
+ display: flex;
126
+ flex: auto;
127
+ flex-direction: column;
128
+ overflow: auto;
129
+ }
130
+
131
+ [part='header'] {
132
+ color: var(--vaadin-crud-header-color, var(--vaadin-color));
133
+ font-size: var(--vaadin-crud-header-font-size, 1em);
134
+ font-weight: var(--vaadin-crud-header-font-weight, 600);
135
+ line-height: var(--vaadin-crud-header-line-height, inherit);
136
+ padding: var(--vaadin-crud-header-padding, var(--vaadin-padding));
137
+ }
138
+
139
+ ::slotted([slot='header']) {
140
+ color: inherit !important;
141
+ display: contents;
142
+ font: inherit !important;
143
+ overflow-wrap: anywhere;
144
+ }
145
+
146
+ ::slotted([slot='form']) {
147
+ padding: var(--vaadin-crud-form-padding, var(--vaadin-padding));
148
+ }
149
+
150
+ [part='footer'] {
151
+ background: var(--vaadin-crud-footer-background, transparent);
152
+ border-top: var(--vaadin-crud-border-width, 1px) solid var(--vaadin-crud-border-color, var(--vaadin-border-color));
153
+ display: flex;
154
+ flex: none;
155
+ gap: var(--vaadin-crud-footer-gap, var(--vaadin-gap-container-inline));
156
+ padding: var(--vaadin-crud-footer-padding, var(--vaadin-padding));
157
+ }
158
+
159
+ ::slotted([slot='delete-button']) {
160
+ margin-inline-start: auto;
161
+ }
162
+ `;
@@ -0,0 +1,13 @@
1
+ /**
2
+ * @license
3
+ * Copyright (c) 2000 - 2025 Vaadin Ltd.
4
+ *
5
+ * This program is available under Vaadin Commercial License and Service Terms.
6
+ *
7
+ *
8
+ * See https://vaadin.com/commercial-license-and-service-terms for the full
9
+ * license.
10
+ */
11
+ import type { CSSResult } from 'lit';
12
+
13
+ export declare const crudDialogOverlayStyles: CSSResult;
@@ -0,0 +1,48 @@
1
+ /**
2
+ * @license
3
+ * Copyright (c) 2000 - 2025 Vaadin Ltd.
4
+ *
5
+ * This program is available under Vaadin Commercial License and Service Terms.
6
+ *
7
+ *
8
+ * See https://vaadin.com/commercial-license-and-service-terms for the full
9
+ * license.
10
+ */
11
+ import '@vaadin/component-base/src/style-props.js';
12
+ import { css } from 'lit';
13
+ import { dialogOverlayStyles } from '@vaadin/dialog/src/styles/vaadin-dialog-overlay-base-styles.js';
14
+
15
+ const crudDialogOverlay = css`
16
+ [part='header'] {
17
+ color: var(--vaadin-crud-dialog-header-color, var(--vaadin-color));
18
+ font-size: var(--vaadin-crud-dialog-header-font-size, 1em);
19
+ font-weight: var(--vaadin-crud-dialog-header-font-weight, 600);
20
+ line-height: var(--vaadin-crud-dialog-header-line-height, inherit);
21
+ padding: var(--vaadin-crud-header-padding, var(--vaadin-padding));
22
+ }
23
+
24
+ ::slotted([slot='header']) {
25
+ color: inherit !important;
26
+ display: contents;
27
+ font: inherit !important;
28
+ overflow-wrap: anywhere;
29
+ }
30
+
31
+ :host(:is(*, #id)) [part='content'] {
32
+ overflow: auto;
33
+ overscroll-behavior: contain;
34
+ padding: var(--vaadin-crud-form-padding, var(--vaadin-padding));
35
+ }
36
+
37
+ ::slotted([slot='form']) {
38
+ --vaadin-crud-form-padding: 0;
39
+ }
40
+
41
+ [part='footer'] {
42
+ justify-content: normal;
43
+ background: var(--vaadin-crud-footer-background, transparent);
44
+ border-top: var(--vaadin-crud-border-width, 1px) solid var(--vaadin-crud-border-color, var(--vaadin-border-color));
45
+ }
46
+ `;
47
+
48
+ export const crudDialogOverlayStyles = [...dialogOverlayStyles, crudDialogOverlay];
@@ -0,0 +1,28 @@
1
+ /**
2
+ * @license
3
+ * Copyright (c) 2000 - 2025 Vaadin Ltd.
4
+ *
5
+ * This program is available under Vaadin Commercial License and Service Terms.
6
+ *
7
+ *
8
+ * See https://vaadin.com/commercial-license-and-service-terms for the full
9
+ * license.
10
+ */
11
+ import '@vaadin/component-base/src/style-props.js';
12
+ import { css } from 'lit';
13
+
14
+ export const crudEditStyles = css`
15
+ [part='icon'] {
16
+ background: currentColor;
17
+ display: block;
18
+ height: var(--vaadin-icon-size, 1lh);
19
+ mask-image: var(--_vaadin-icon-edit);
20
+ width: var(--vaadin-icon-size, 1lh);
21
+ }
22
+
23
+ @media (forced-colors: active) {
24
+ [part='icon'] {
25
+ background: CanvasText;
26
+ }
27
+ }
28
+ `;
@@ -0,0 +1,17 @@
1
+ /**
2
+ * @license
3
+ * Copyright (c) 2000 - 2025 Vaadin Ltd.
4
+ *
5
+ * This program is available under Vaadin Commercial License and Service Terms.
6
+ *
7
+ *
8
+ * See https://vaadin.com/commercial-license-and-service-terms for the full
9
+ * license.
10
+ */
11
+ import { css } from 'lit';
12
+
13
+ export const crudEditStyles = css`
14
+ :host {
15
+ display: block;
16
+ }
17
+ `;
@@ -0,0 +1,13 @@
1
+ /**
2
+ * @license
3
+ * Copyright (c) 2000 - 2025 Vaadin Ltd.
4
+ *
5
+ * This program is available under Vaadin Commercial License and Service Terms.
6
+ *
7
+ *
8
+ * See https://vaadin.com/commercial-license-and-service-terms for the full
9
+ * license.
10
+ */
11
+ import type { CSSResult } from 'lit';
12
+
13
+ export const crudGridStyles: CSSResult;
@@ -0,0 +1,21 @@
1
+ /**
2
+ * @license
3
+ * Copyright (c) 2000 - 2025 Vaadin Ltd.
4
+ *
5
+ * This program is available under Vaadin Commercial License and Service Terms.
6
+ *
7
+ *
8
+ * See https://vaadin.com/commercial-license-and-service-terms for the full
9
+ * license.
10
+ */
11
+ import '@vaadin/component-base/src/style-props.js';
12
+ import { css } from 'lit';
13
+ import { gridStyles } from '@vaadin/grid/src/styles/vaadin-grid-base-styles.js';
14
+
15
+ const crudGrid = css`
16
+ #scroller {
17
+ border-radius: inherit;
18
+ }
19
+ `;
20
+
21
+ export const crudGridStyles = [gridStyles, crudGrid];
@@ -0,0 +1,13 @@
1
+ /**
2
+ * @license
3
+ * Copyright (c) 2000 - 2025 Vaadin Ltd.
4
+ *
5
+ * This program is available under Vaadin Commercial License and Service Terms.
6
+ *
7
+ *
8
+ * See https://vaadin.com/commercial-license-and-service-terms for the full
9
+ * license.
10
+ */
11
+ import type { CSSResult } from 'lit';
12
+
13
+ export const crudGridStyles: CSSResult;
@@ -0,0 +1,13 @@
1
+ /**
2
+ * @license
3
+ * Copyright (c) 2000 - 2025 Vaadin Ltd.
4
+ *
5
+ * This program is available under Vaadin Commercial License and Service Terms.
6
+ *
7
+ *
8
+ * See https://vaadin.com/commercial-license-and-service-terms for the full
9
+ * license.
10
+ */
11
+ import { gridStyles } from '@vaadin/grid/src/styles/vaadin-grid-core-styles.js';
12
+
13
+ export const crudGridStyles = [gridStyles];
@@ -42,7 +42,7 @@ export class ButtonSlotController extends SlotController {
42
42
  }
43
43
 
44
44
  // Respect default theme attribute set by the Flow counterpart
45
- if (node === this.defaultNode && !node.hasAttribute('theme')) {
45
+ if (node === this.defaultNode && this.theme && !node.hasAttribute('theme')) {
46
46
  node.setAttribute('theme', this.theme);
47
47
  }
48
48
 
@@ -40,13 +40,24 @@ class CrudDialogOverlay extends OverlayMixin(DirMixin(ThemableMixin(PolylitMixin
40
40
  return crudDialogOverlayStyles;
41
41
  }
42
42
 
43
+ /**
44
+ * Override method from OverlayFocusMixin to use the owner (CRUD element) as modal root
45
+ * @protected
46
+ * @override
47
+ */
48
+ get _modalRoot() {
49
+ return this.owner;
50
+ }
51
+
43
52
  /** @protected */
44
53
  render() {
45
54
  return html`
46
55
  <div part="backdrop" id="backdrop" ?hidden="${!this.withBackdrop}"></div>
47
56
  <div part="overlay" id="overlay" tabindex="0">
48
57
  <section id="resizerContainer" class="resizer-container">
49
- <header part="header"><slot name="header"></slot></header>
58
+ <header part="header">
59
+ <slot name="header"></slot>
60
+ </header>
50
61
  <div part="content" id="content">
51
62
  <slot name="form"></slot>
52
63
  </div>
@@ -86,21 +97,28 @@ class CrudDialog extends DialogBaseMixin(OverlayClassMixin(ThemePropertyMixin(Po
86
97
 
87
98
  static get styles() {
88
99
  return css`
89
- :host {
90
- display: none;
100
+ :host([opened]),
101
+ :host([opening]),
102
+ :host([closing]) {
103
+ display: contents !important;
104
+ }
105
+
106
+ :host,
107
+ :host([hidden]) {
108
+ display: none !important;
91
109
  }
92
110
  `;
93
111
  }
94
112
 
95
113
  static get properties() {
96
114
  return {
97
- ariaLabel: {
98
- type: String,
99
- },
100
-
101
115
  fullscreen: {
102
116
  type: Boolean,
103
117
  },
118
+
119
+ crudElement: {
120
+ type: Object,
121
+ },
104
122
  };
105
123
  }
106
124
 
@@ -109,20 +127,33 @@ class CrudDialog extends DialogBaseMixin(OverlayClassMixin(ThemePropertyMixin(Po
109
127
  return html`
110
128
  <vaadin-crud-dialog-overlay
111
129
  id="overlay"
130
+ .owner="${this.crudElement}"
112
131
  .opened="${this.opened}"
113
- aria-label="${ifDefined(this.ariaLabel)}"
114
132
  @opened-changed="${this._onOverlayOpened}"
115
133
  @mousedown="${this._bringOverlayToFront}"
116
134
  @touchstart="${this._bringOverlayToFront}"
135
+ @vaadin-overlay-outside-click="${this.__cancel}"
136
+ @vaadin-overlay-escape-press="${this.__cancel}"
117
137
  theme="${ifDefined(this._theme)}"
118
138
  .modeless="${this.modeless}"
119
139
  .withBackdrop="${!this.modeless}"
120
140
  ?fullscreen="${this.fullscreen}"
121
- role="dialog"
122
141
  focus-trap
123
- ></vaadin-crud-dialog-overlay>
142
+ exportparts="backdrop, overlay, header, content, footer"
143
+ >
144
+ <slot name="header" slot="header"></slot>
145
+ <slot name="form" slot="form"></slot>
146
+ <slot name="save-button" slot="save-button"></slot>
147
+ <slot name="cancel-button" slot="cancel-button"></slot>
148
+ <slot name="delete-button" slot="delete-button"></slot>
149
+ </vaadin-crud-dialog-overlay>
124
150
  `;
125
151
  }
152
+
153
+ /** @private **/
154
+ __cancel() {
155
+ this.dispatchEvent(new CustomEvent('cancel'));
156
+ }
126
157
  }
127
158
 
128
159
  defineCustomElement(CrudDialog);
@@ -8,9 +8,10 @@
8
8
  * See https://vaadin.com/commercial-license-and-service-terms for the full
9
9
  * license.
10
10
  */
11
- import { css, html } from 'lit';
11
+ import { html } from 'lit';
12
12
  import { Button } from '@vaadin/button/src/vaadin-button.js';
13
13
  import { defineCustomElement } from '@vaadin/component-base/src/define.js';
14
+ import { crudEditStyles } from './styles/vaadin-crud-edit-core-styles.js';
14
15
 
15
16
  /**
16
17
  * `<vaadin-crud-edit>` is a helper element for `<vaadin-grid-column>` that provides
@@ -30,14 +31,7 @@ class CrudEdit extends Button {
30
31
  }
31
32
 
32
33
  static get styles() {
33
- return [
34
- super.styles,
35
- css`
36
- :host {
37
- display: block;
38
- }
39
- `,
40
- ];
34
+ return [super.styles, crudEditStyles];
41
35
  }
42
36
 
43
37
  /** @protected */
@@ -15,6 +15,7 @@ import '@vaadin/grid/src/vaadin-grid-sorter.js';
15
15
  import './vaadin-crud-edit-column.js';
16
16
  import { defineCustomElement } from '@vaadin/component-base/src/define.js';
17
17
  import { Grid } from '@vaadin/grid/src/vaadin-grid.js';
18
+ import { crudGridStyles } from './styles/vaadin-crud-grid-core-styles.js';
18
19
  import { CrudGridMixin } from './vaadin-crud-grid-mixin.js';
19
20
 
20
21
  /**
@@ -28,6 +29,10 @@ class CrudGrid extends CrudGridMixin(Grid) {
28
29
  static get is() {
29
30
  return 'vaadin-crud-grid';
30
31
  }
32
+
33
+ static get styles() {
34
+ return crudGridStyles;
35
+ }
31
36
  }
32
37
 
33
38
  defineCustomElement(CrudGrid);
@@ -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', {
@@ -421,6 +433,24 @@ export const CrudMixin = (superClass) =>
421
433
  this._confirmDeleteDialog = this.querySelector('vaadin-confirm-dialog[slot="confirm-delete"]');
422
434
  }
423
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
+ }
452
+ }
453
+
424
454
  /**
425
455
  * @param {boolean} isDirty
426
456
  * @private
@@ -477,25 +507,24 @@ export const CrudMixin = (superClass) =>
477
507
  }
478
508
 
479
509
  if (opened) {
480
- this.__ensureChildren();
481
-
482
510
  // When using bottom / aside editor position,
483
511
  // auto-focus the editor element on open.
484
- if (this._form.parentElement === this) {
485
- this.$.editor.setAttribute('tabindex', '0');
486
- this.$.editor.focus();
487
- } else {
488
- this.$.editor.removeAttribute('tabindex');
512
+ if (this._editor) {
513
+ this._editor.focus();
489
514
  }
490
- } else if (oldOpened) {
491
- // Teleport form and buttons back to light DOM when closing overlay
492
- 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
+ });
493
520
  }
494
521
 
495
522
  this.__toggleToolbar();
496
523
 
497
524
  // Make sure to reset scroll position
498
- this.$.scroller.scrollTop = 0;
525
+ if (this._scroller) {
526
+ this._scroller.scrollTop = 0;
527
+ }
499
528
  }
500
529
 
501
530
  /** @private */
@@ -503,8 +532,6 @@ export const CrudMixin = (superClass) =>
503
532
  if (fullscreen || oldFullscreen) {
504
533
  this.__toggleToolbar();
505
534
 
506
- this.__ensureChildren();
507
-
508
535
  this.toggleAttribute('fullscreen', fullscreen);
509
536
  }
510
537
  }
@@ -517,66 +544,6 @@ export const CrudMixin = (superClass) =>
517
544
  }
518
545
  }
519
546
 
520
- /** @private */
521
- __moveChildNodes(target) {
522
- const nodes = [this._headerNode, this._form];
523
- const buttons = [this._saveButton, this._cancelButton, this._deleteButton].filter(Boolean);
524
- if (!nodes.every((node) => node instanceof HTMLElement)) {
525
- return;
526
- }
527
-
528
- // Teleport header node, form, and the buttons to corresponding slots.
529
- // NOTE: order in which buttons are moved matches the order of slots.
530
- [...nodes, ...buttons].forEach((node) => {
531
- // Do not move nodes if the editor position has not changed
532
- if (node.parentNode !== target) {
533
- target.appendChild(node);
534
- }
535
- });
536
-
537
- // Wait to set label until slotted element has been moved.
538
- setTimeout(() => {
539
- this.__dialogAriaLabel = this._headerNode.textContent.trim();
540
- });
541
- }
542
-
543
- /** @private */
544
- __shouldOpenDialog(fullscreen, editorPosition) {
545
- return editorPosition === '' || fullscreen;
546
- }
547
-
548
- /** @private */
549
- __ensureChildren() {
550
- if (this.__shouldOpenDialog(this._fullscreen, this.editorPosition)) {
551
- // Move form to dialog
552
- this.__moveChildNodes(this.$.dialog.$.overlay);
553
- } else {
554
- // Move form to crud
555
- this.__moveChildNodes(this);
556
- }
557
- }
558
-
559
- /** @private */
560
- __computeDialogOpened(opened, fullscreen, editorPosition) {
561
- // Only open dialog when editorPosition is "" or fullscreen is set
562
- return this.__shouldOpenDialog(fullscreen, editorPosition) ? opened : false;
563
- }
564
-
565
- /** @private */
566
- __computeEditorHidden(opened, fullscreen, editorPosition) {
567
- // Only show editor when editorPosition is "bottom" or "aside"
568
- if (['aside', 'bottom'].includes(editorPosition) && !fullscreen) {
569
- return !opened;
570
- }
571
-
572
- return true;
573
- }
574
-
575
- /** @private */
576
- __onDialogOpened(event) {
577
- this.editorOpened = event.detail.value;
578
- }
579
-
580
547
  /** @private */
581
548
  __onGridEdit(event) {
582
549
  event.stopPropagation();
@@ -620,8 +587,7 @@ export const CrudMixin = (superClass) =>
620
587
  * @private
621
588
  */
622
589
  __formChanged(form, oldForm) {
623
- if (oldForm && oldForm.parentElement) {
624
- oldForm.parentElement.removeChild(oldForm);
590
+ if (oldForm) {
625
591
  oldForm.removeEventListener('change', this.__onFormChange);
626
592
  oldForm.removeEventListener('input', this.__onFormChange);
627
593
  }
@@ -1023,6 +989,17 @@ export const CrudMixin = (superClass) =>
1023
989
  }
1024
990
  }
1025
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
+
1026
1003
  /**
1027
1004
  * Fired when user wants to edit an existing item. If the default is prevented, then
1028
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,7 +13,7 @@ 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, render } 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';
@@ -140,11 +140,26 @@ import { CrudMixin } from './vaadin-crud-mixin.js';
140
140
  *
141
141
  * ### Styling
142
142
  *
143
- * 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:
144
144
  *
145
145
  * Part name | Description
146
146
  * ----------------|----------------
147
- * `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
148
163
  *
149
164
  * The following custom properties are available:
150
165
  *
@@ -197,38 +212,55 @@ class Crud extends CrudMixin(ElementMixin(ThemableMixin(PolylitMixin(LumoInjecti
197
212
  </div>
198
213
  </div>
199
214
 
200
- <div
201
- part="editor"
202
- id="editor"
203
- role="group"
204
- aria-labelledby="header"
205
- ?hidden="${this.__computeEditorHidden(this.editorOpened, this._fullscreen, this.editorPosition)}"
206
- >
207
- <div part="scroller" id="scroller">
208
- <div part="header" id="header">
209
- <slot name="header"></slot>
210
- </div>
211
- <slot name="form"></slot>
212
- </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>
213
231
 
214
- <div part="footer" role="toolbar">
215
- <slot name="save-button"></slot>
216
- <slot name="cancel-button"></slot>
217
- <slot name="delete-button"></slot>
218
- </div>
219
- </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}
220
240
  </div>
221
241
 
222
- <vaadin-crud-dialog
223
- id="dialog"
224
- .opened="${this.__computeDialogOpened(this.editorOpened, this._fullscreen, this.editorPosition)}"
225
- .fullscreen="${this._fullscreen}"
226
- .ariaLabel="${this.__dialogAriaLabel}"
227
- .noCloseOnOutsideClick="${this.__isDirty}"
228
- .noCloseOnEsc="${this.__isDirty}"
229
- theme="${ifDefined(this._theme)}"
230
- @opened-changed="${this.__onDialogOpened}"
231
- ></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}
232
264
 
233
265
  <slot name="confirm-cancel"></slot>
234
266
 
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-alpha8",
4
+ "version": "25.0.0-alpha9",
5
5
  "description-markup": "markdown",
6
6
  "contributions": {
7
7
  "html": {
@@ -357,7 +357,7 @@
357
357
  },
358
358
  {
359
359
  "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-alpha8/#/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-alpha8/#/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-alpha8/#/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-alpha8/#/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-alpha8/#/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.",
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-alpha9/#/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-alpha9/#/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-alpha9/#/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-alpha9/#/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-alpha9/#/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
361
  "attributes": [
362
362
  {
363
363
  "name": "i18n",
@@ -421,7 +421,7 @@
421
421
  },
422
422
  {
423
423
  "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-alpha8/#/elements/vaadin-crud#property-exclude) is ignored.\n\nDefault is undefined meaning that all properties in the object should be mapped to fields.",
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-alpha9/#/elements/vaadin-crud#property-exclude) is ignored.\n\nDefault is undefined meaning that all properties in the object should be mapped to fields.",
425
425
  "value": {
426
426
  "type": [
427
427
  "string",
@@ -432,7 +432,7 @@
432
432
  },
433
433
  {
434
434
  "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-alpha8/#/elements/vaadin-crud#property-include) is defined, this parameter is ignored.\n\nDefault is to exclude all private fields (those properties starting with underscore)",
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-alpha9/#/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
436
  "value": {
437
437
  "type": [
438
438
  "string",
@@ -568,7 +568,7 @@
568
568
  },
569
569
  {
570
570
  "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-alpha8/#/elements/vaadin-crud#property-exclude) is ignored.\n\nDefault is undefined meaning that all properties in the object should be mapped to fields.",
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-alpha9/#/elements/vaadin-crud#property-exclude) is ignored.\n\nDefault is undefined meaning that all properties in the object should be mapped to fields.",
572
572
  "value": {
573
573
  "type": [
574
574
  "string",
@@ -579,7 +579,7 @@
579
579
  },
580
580
  {
581
581
  "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-alpha8/#/elements/vaadin-crud#property-include) is defined, this parameter is ignored.\n\nDefault is to exclude all private fields (those properties starting with underscore)",
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-alpha9/#/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
583
  "value": {
584
584
  "type": [
585
585
  "string",
@@ -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-alpha8",
4
+ "version": "25.0.0-alpha9",
5
5
  "description-markup": "markdown",
6
6
  "framework": "lit",
7
7
  "framework-config": {
@@ -142,7 +142,7 @@
142
142
  },
143
143
  {
144
144
  "name": "vaadin-crud",
145
- "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-alpha8/#/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-alpha8/#/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-alpha8/#/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-alpha8/#/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-alpha8/#/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.",
145
+ "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-alpha9/#/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-alpha9/#/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-alpha9/#/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-alpha9/#/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-alpha9/#/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.",
146
146
  "extension": true,
147
147
  "attributes": [
148
148
  {
@@ -224,14 +224,14 @@
224
224
  },
225
225
  {
226
226
  "name": ".include",
227
- "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-alpha8/#/elements/vaadin-crud#property-exclude) is ignored.\n\nDefault is undefined meaning that all properties in the object should be mapped to fields.",
227
+ "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-alpha9/#/elements/vaadin-crud#property-exclude) is ignored.\n\nDefault is undefined meaning that all properties in the object should be mapped to fields.",
228
228
  "value": {
229
229
  "kind": "expression"
230
230
  }
231
231
  },
232
232
  {
233
233
  "name": ".exclude",
234
- "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-alpha8/#/elements/vaadin-crud#property-include) is defined, this parameter is ignored.\n\nDefault is to exclude all private fields (those properties starting with underscore)",
234
+ "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-alpha9/#/elements/vaadin-crud#property-include) is defined, this parameter is ignored.\n\nDefault is to exclude all private fields (those properties starting with underscore)",
235
235
  "value": {
236
236
  "kind": "expression"
237
237
  }