@vaadin/crud 24.1.1 → 24.1.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vaadin/crud",
3
- "version": "24.1.1",
3
+ "version": "24.1.3",
4
4
  "publishConfig": {
5
5
  "access": "public"
6
6
  },
@@ -37,16 +37,16 @@
37
37
  "dependencies": {
38
38
  "@open-wc/dedupe-mixin": "^1.3.0",
39
39
  "@polymer/polymer": "^3.0.0",
40
- "@vaadin/button": "~24.1.1",
41
- "@vaadin/component-base": "~24.1.1",
42
- "@vaadin/confirm-dialog": "~24.1.1",
43
- "@vaadin/dialog": "~24.1.1",
44
- "@vaadin/form-layout": "~24.1.1",
45
- "@vaadin/grid": "~24.1.1",
46
- "@vaadin/text-field": "~24.1.1",
47
- "@vaadin/vaadin-lumo-styles": "~24.1.1",
48
- "@vaadin/vaadin-material-styles": "~24.1.1",
49
- "@vaadin/vaadin-themable-mixin": "~24.1.1"
40
+ "@vaadin/button": "~24.1.3",
41
+ "@vaadin/component-base": "~24.1.3",
42
+ "@vaadin/confirm-dialog": "~24.1.3",
43
+ "@vaadin/dialog": "~24.1.3",
44
+ "@vaadin/form-layout": "~24.1.3",
45
+ "@vaadin/grid": "~24.1.3",
46
+ "@vaadin/text-field": "~24.1.3",
47
+ "@vaadin/vaadin-lumo-styles": "~24.1.3",
48
+ "@vaadin/vaadin-material-styles": "~24.1.3",
49
+ "@vaadin/vaadin-themable-mixin": "~24.1.3"
50
50
  },
51
51
  "devDependencies": {
52
52
  "@esm-bundle/chai": "^4.3.4",
@@ -58,5 +58,5 @@
58
58
  "web-types.json",
59
59
  "web-types.lit.json"
60
60
  ],
61
- "gitHead": "c3a3d904885bd37ebb07a84b09617a340b4fab7e"
61
+ "gitHead": "161d7de3f22afa4b67723493555c0512ce2acfe3"
62
62
  }
@@ -13,7 +13,6 @@ import '@vaadin/grid/src/vaadin-grid-column-group.js';
13
13
  import '@vaadin/grid/src/vaadin-grid-sorter.js';
14
14
  import '@vaadin/grid/src/vaadin-grid-filter.js';
15
15
  import './vaadin-crud-edit-column.js';
16
- import { getClosestElement } from '@vaadin/component-base/src/dom-utils.js';
17
16
  import { Grid } from '@vaadin/grid/src/vaadin-grid.js';
18
17
  import { capitalize, getProperty } from './vaadin-crud-helpers.js';
19
18
  import { IncludedMixin } from './vaadin-crud-include-mixin.js';
@@ -59,30 +58,6 @@ class CrudGrid extends IncludedMixin(Grid) {
59
58
  return ['__onItemsChange(items)', '__onHideEditColumnChange(hideEditColumn)'];
60
59
  }
61
60
 
62
- /** @protected */
63
- _getRowContainingNode(node) {
64
- const content = getClosestElement('vaadin-grid-cell-content', node);
65
- if (!content) {
66
- return;
67
- }
68
-
69
- const cell = content.assignedSlot.parentElement;
70
- return cell.parentElement;
71
- }
72
-
73
- /** @protected */
74
- _isItemAssigedToRow(item, row) {
75
- const model = this.__getRowModel(row);
76
- return this.getItemId(item) === this.getItemId(model.item);
77
- }
78
-
79
- /** @protected */
80
- _focusFirstVisibleRow() {
81
- const row = this.__getFirstVisibleItem();
82
- this.__rowFocusMode = true;
83
- row.focus();
84
- }
85
-
86
61
  /** @private */
87
62
  __onItemsChange(items) {
88
63
  if ((!this.dataProvider || this.dataProvider === this._arrayDataProvider) && !this.include && items && items[0]) {
@@ -250,7 +250,7 @@ export type CrudEventMap<T> = CrudCustomEventMap<T> & HTMLElementEventMap;
250
250
  * --vaadin-crud-editor-max-height | max height of editor when opened on the bottom | 40%
251
251
  * --vaadin-crud-editor-max-width | max width of editor when opened on the side | 40%
252
252
  *
253
- * See [Styling Components](https://vaadin.com/docs/latest/styling/custom-theme/styling-components) documentation.
253
+ * See [Styling Components](https://vaadin.com/docs/latest/styling/styling-components) documentation.
254
254
  *
255
255
  * @fires {CustomEvent} editor-opened-changed - Fired when the `editorOpened` property changes.
256
256
  * @fires {CustomEvent} edited-item-changed - Fired when `editedItem` property changes.
@@ -26,16 +26,48 @@ import { ThemableMixin } from '@vaadin/vaadin-themable-mixin/vaadin-themable-mix
26
26
  import { getProperty, setProperty } from './vaadin-crud-helpers.js';
27
27
 
28
28
  /**
29
+ * A controller for initializing slotted button.
29
30
  * @private
30
- * A to initialize slotted button.
31
31
  */
32
32
  class ButtonSlotController extends SlotController {
33
33
  constructor(host, type, theme) {
34
- super(host, `${type}-button`, 'vaadin-button', {
35
- initializer: (button) => {
36
- button.setAttribute('theme', theme);
37
- },
38
- });
34
+ super(host, `${type}-button`, 'vaadin-button');
35
+
36
+ this.type = type;
37
+ this.theme = theme;
38
+ }
39
+
40
+ /**
41
+ * Override method inherited from `SlotController`
42
+ * to mark custom slotted button as the default.
43
+ *
44
+ * @param {Node} node
45
+ * @protected
46
+ * @override
47
+ */
48
+ initNode(node) {
49
+ // Needed by Flow counterpart to apply i18n to custom button
50
+ if (node._isDefault) {
51
+ this.defaultNode = node;
52
+ }
53
+
54
+ if (node === this.defaultNode) {
55
+ node.setAttribute('theme', this.theme);
56
+ }
57
+
58
+ const { host, type } = this;
59
+ const property = `_${type}Button`;
60
+ const listener = `__${type}`;
61
+
62
+ // TODO: restore default button when a corresponding slotted button is removed.
63
+ // This would require us to detect where to insert a button after teleporting it,
64
+ // which happens after opening a dialog and closing it (default editor position).
65
+ if (host[property] && host[property] !== node) {
66
+ host[property].remove();
67
+ }
68
+
69
+ node.addEventListener('click', host[listener]);
70
+ host[property] = node;
39
71
  }
40
72
  }
41
73
 
@@ -169,7 +201,7 @@ class ButtonSlotController extends SlotController {
169
201
  * --vaadin-crud-editor-max-height | max height of editor when opened on the bottom | 40%
170
202
  * --vaadin-crud-editor-max-width | max width of editor when opened on the side | 40%
171
203
  *
172
- * See [Styling Components](https://vaadin.com/docs/latest/styling/custom-theme/styling-components) documentation.
204
+ * See [Styling Components](https://vaadin.com/docs/latest/styling/styling-components) documentation.
173
205
  *
174
206
  * @fires {CustomEvent} editor-opened-changed - Fired when the `editorOpened` property changes.
175
207
  * @fires {CustomEvent} edited-item-changed - Fired when `editedItem` property changes.
@@ -241,6 +273,7 @@ class Crud extends ControllerMixin(ElementMixin(ThemableMixin(PolymerElement)))
241
273
  display: flex;
242
274
  flex-direction: column;
243
275
  height: 100%;
276
+ outline: none;
244
277
  }
245
278
 
246
279
  :host(:not([editor-position=''])[editor-opened]:not([fullscreen])) [part='editor'] {
@@ -280,8 +313,14 @@ class Crud extends ControllerMixin(ElementMixin(ThemableMixin(PolymerElement)))
280
313
  </div>
281
314
  </div>
282
315
 
283
- <div id="editor" part="editor" hidden$="[[__computeEditorHidden(editorOpened, _fullscreen, editorPosition)]]">
284
- <div part="scroller" id="scroller" role="group" aria-labelledby="header">
316
+ <div
317
+ part="editor"
318
+ id="editor"
319
+ role="group"
320
+ aria-labelledby="header"
321
+ hidden$="[[__computeEditorHidden(editorOpened, _fullscreen, editorPosition)]]"
322
+ >
323
+ <div part="scroller" id="scroller">
285
324
  <div part="header" id="header">
286
325
  <slot name="header"></slot>
287
326
  </div>
@@ -665,6 +704,11 @@ class Crud extends ControllerMixin(ElementMixin(ThemableMixin(PolymerElement)))
665
704
  this.__onGridSizeChanged = this.__onGridSizeChanged.bind(this);
666
705
  this.__onGridActiveItemChanged = this.__onGridActiveItemChanged.bind(this);
667
706
 
707
+ this._newButtonController = new ButtonSlotController(this, 'new', 'primary');
708
+ this._saveButtonController = new ButtonSlotController(this, 'save', 'primary');
709
+ this._cancelButtonController = new ButtonSlotController(this, 'cancel', 'tertiary');
710
+ this._deleteButtonController = new ButtonSlotController(this, 'delete', 'tertiary error');
711
+
668
712
  this.__focusRestorationController = new FocusRestorationController();
669
713
 
670
714
  this._observer = new FlattenedNodesObserver(this, (info) => {
@@ -708,12 +752,12 @@ class Crud extends ControllerMixin(ElementMixin(ThemableMixin(PolymerElement)))
708
752
 
709
753
  this.addController(new SlotController(this, 'form', 'vaadin-crud-form'));
710
754
 
711
- this.addController(new ButtonSlotController(this, 'new', 'primary'));
755
+ this.addController(this._newButtonController);
712
756
 
713
757
  // NOTE: order in which buttons are added should match the order of slots in template
714
- this.addController(new ButtonSlotController(this, 'save', 'primary'));
715
- this.addController(new ButtonSlotController(this, 'cancel', 'tertiary'));
716
- this.addController(new ButtonSlotController(this, 'delete', 'tertiary error'));
758
+ this.addController(this._saveButtonController);
759
+ this.addController(this._cancelButtonController);
760
+ this.addController(this._deleteButtonController);
717
761
 
718
762
  this.addController(
719
763
  new MediaQueryController(this._fullscreenMediaQuery, (matches) => {
@@ -782,6 +826,15 @@ class Crud extends ControllerMixin(ElementMixin(ThemableMixin(PolymerElement)))
782
826
 
783
827
  if (opened) {
784
828
  this.__ensureChildren();
829
+
830
+ // When using bottom / aside editor position,
831
+ // auto-focus the editor element on open.
832
+ if (this._form.parentElement === this) {
833
+ this.$.editor.setAttribute('tabindex', '0');
834
+ this.$.editor.focus();
835
+ } else {
836
+ this.$.editor.removeAttribute('tabindex');
837
+ }
785
838
  }
786
839
 
787
840
  this.__toggleToolbar();
@@ -868,9 +921,6 @@ class Crud extends ControllerMixin(ElementMixin(ThemableMixin(PolymerElement)))
868
921
 
869
922
  /** @private */
870
923
  __onDomChange(addedNodes) {
871
- // TODO: restore default button when a corresponding slotted button is removed.
872
- // This would require us to detect where to insert a button after teleporting it,
873
- // which happens after opening a dialog and closing it (default editor position).
874
924
  addedNodes
875
925
  .filter((node) => node.nodeType === Node.ELEMENT_NODE)
876
926
  .forEach((node) => {
@@ -886,9 +936,6 @@ class Crud extends ControllerMixin(ElementMixin(ThemableMixin(PolymerElement)))
886
936
  this.__editOnClickChanged(this.editOnClick, this._grid);
887
937
  } else if (slotAttributeValue === 'form') {
888
938
  this._form = node;
889
- } else if (slotAttributeValue.indexOf('button') >= 0) {
890
- const [button] = slotAttributeValue.split('-');
891
- this.__setupSlottedButton(button, node);
892
939
  }
893
940
  });
894
941
 
@@ -979,7 +1026,7 @@ class Crud extends ControllerMixin(ElementMixin(ThemableMixin(PolymerElement)))
979
1026
  }
980
1027
 
981
1028
  /**
982
- * @param {HTMLElement | undefined} form
1029
+ * @param {HTMLElement | undefined} grid
983
1030
  * @param {string} theme
984
1031
  * @param {string | string[] | undefined} include
985
1032
  * @param {string | RegExp} exclude
@@ -1021,7 +1068,10 @@ class Crud extends ControllerMixin(ElementMixin(ThemableMixin(PolymerElement)))
1021
1068
  __saveButtonPropsChanged(saveButton, i18nLabel, isDirty) {
1022
1069
  if (saveButton) {
1023
1070
  saveButton.toggleAttribute('disabled', this.__isSaveBtnDisabled(isDirty));
1024
- saveButton.textContent = i18nLabel;
1071
+
1072
+ if (saveButton === this._saveButtonController.defaultNode) {
1073
+ saveButton.textContent = i18nLabel;
1074
+ }
1025
1075
  }
1026
1076
  }
1027
1077
 
@@ -1033,18 +1083,21 @@ class Crud extends ControllerMixin(ElementMixin(ThemableMixin(PolymerElement)))
1033
1083
  */
1034
1084
  __deleteButtonPropsChanged(deleteButton, i18nLabel, isNew) {
1035
1085
  if (deleteButton) {
1036
- deleteButton.textContent = i18nLabel;
1037
1086
  deleteButton.toggleAttribute('hidden', isNew);
1087
+
1088
+ if (deleteButton === this._deleteButtonController.defaultNode) {
1089
+ deleteButton.textContent = i18nLabel;
1090
+ }
1038
1091
  }
1039
1092
  }
1040
1093
 
1041
1094
  /**
1042
- * @param {HTMLElement | undefined} saveButton
1095
+ * @param {HTMLElement | undefined} cancelButton
1043
1096
  * @param {string} i18nLabel
1044
1097
  * @private
1045
1098
  */
1046
1099
  __cancelButtonPropsChanged(cancelButton, i18nLabel) {
1047
- if (cancelButton) {
1100
+ if (cancelButton && cancelButton === this._cancelButtonController.defaultNode) {
1048
1101
  cancelButton.textContent = i18nLabel;
1049
1102
  }
1050
1103
  }
@@ -1055,28 +1108,11 @@ class Crud extends ControllerMixin(ElementMixin(ThemableMixin(PolymerElement)))
1055
1108
  * @private
1056
1109
  */
1057
1110
  __newButtonPropsChanged(newButton, i18nNewItem) {
1058
- if (newButton) {
1111
+ if (newButton && newButton === this._newButtonController.defaultNode) {
1059
1112
  newButton.textContent = i18nNewItem;
1060
1113
  }
1061
1114
  }
1062
1115
 
1063
- /**
1064
- * @param {string} type
1065
- * @param {HTMLElement} newButton
1066
- * @private
1067
- */
1068
- __setupSlottedButton(type, button) {
1069
- const property = `_${type}Button`;
1070
- const listener = `__${type}`;
1071
-
1072
- if (this[property] && this[property] !== button) {
1073
- this[property].remove();
1074
- }
1075
-
1076
- button.addEventListener('click', this[listener]);
1077
- this[property] = button;
1078
- }
1079
-
1080
1116
  /** @private */
1081
1117
  __dataProviderChanged(dataProvider) {
1082
1118
  if (this._grid) {
@@ -1271,7 +1307,7 @@ class Crud extends ControllerMixin(ElementMixin(ThemableMixin(PolymerElement)))
1271
1307
  return;
1272
1308
  }
1273
1309
 
1274
- if (this._grid._isItemAssigedToRow(this.editedItem, row) && this._grid._isInViewport(row)) {
1310
+ if (this._grid._isItemAssignedToRow(this.editedItem, row) && this._grid._isInViewport(row)) {
1275
1311
  this.__focusRestorationController.restoreFocus();
1276
1312
  } else {
1277
1313
  this._grid._focusFirstVisibleRow();
@@ -96,6 +96,14 @@ registerStyles(
96
96
  [part='editor'] {
97
97
  background: var(--lumo-base-color);
98
98
  box-sizing: border-box;
99
+ position: relative;
100
+ }
101
+
102
+ [part='editor']:focus::before {
103
+ position: absolute;
104
+ inset: 0;
105
+ content: '';
106
+ box-shadow: inset 0 0 0 2px var(--lumo-primary-color-50pct);
99
107
  }
100
108
 
101
109
  :host(:not([editor-position=''])) [part='editor']:not([hidden]) {
@@ -72,6 +72,17 @@ registerStyles(
72
72
  background: var(--material-background-color);
73
73
  }
74
74
 
75
+ [part='editor'] {
76
+ position: relative;
77
+ }
78
+
79
+ [part='editor']:focus::before {
80
+ position: absolute;
81
+ inset: 0;
82
+ content: '';
83
+ box-shadow: inset 0 0 0 2px var(--material-primary-color);
84
+ }
85
+
75
86
  [part='toolbar'] {
76
87
  padding: 8px;
77
88
  background-color: var(--material-secondary-background-color);
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": "24.1.1",
4
+ "version": "24.1.3",
5
5
  "description-markup": "markdown",
6
6
  "contributions": {
7
7
  "html": {
@@ -295,7 +295,7 @@
295
295
  },
296
296
  {
297
297
  "name": "vaadin-crud",
298
- "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/24.1.1/#/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/24.1.1/#/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/24.1.1/#/elements/vaadin-crud-edit-column)\n- `<vaadin-crud-grid>` - can be replaced with custom [`<vaadin-grid>`](https://cdn.vaadin.com/vaadin-web-components/24.1.1/#/elements/vaadin-grid)\n- `<vaadin-crud-form>` - can be replaced with custom [`<vaadin-form-layout>`](https://cdn.vaadin.com/vaadin-web-components/24.1.1/#/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/custom-theme/styling-components) documentation.",
298
+ "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/24.1.3/#/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/24.1.3/#/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/24.1.3/#/elements/vaadin-crud-edit-column)\n- `<vaadin-crud-grid>` - can be replaced with custom [`<vaadin-grid>`](https://cdn.vaadin.com/vaadin-web-components/24.1.3/#/elements/vaadin-grid)\n- `<vaadin-crud-form>` - can be replaced with custom [`<vaadin-form-layout>`](https://cdn.vaadin.com/vaadin-web-components/24.1.3/#/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.",
299
299
  "attributes": [
300
300
  {
301
301
  "name": "editor-position",
@@ -350,7 +350,7 @@
350
350
  },
351
351
  {
352
352
  "name": "include",
353
- "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/24.1.1/#/elements/vaadin-crud#property-exclude) is ignored.\n\nDefault is undefined meaning that all properties in the object should be mapped to fields.",
353
+ "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/24.1.3/#/elements/vaadin-crud#property-exclude) is ignored.\n\nDefault is undefined meaning that all properties in the object should be mapped to fields.",
354
354
  "value": {
355
355
  "type": [
356
356
  "string",
@@ -361,7 +361,7 @@
361
361
  },
362
362
  {
363
363
  "name": "exclude",
364
- "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/24.1.1/#/elements/vaadin-crud#property-include) is defined, this parameter is ignored.\n\nDefault is to exclude all private fields (those properties starting with underscore)",
364
+ "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/24.1.3/#/elements/vaadin-crud#property-include) is defined, this parameter is ignored.\n\nDefault is to exclude all private fields (those properties starting with underscore)",
365
365
  "value": {
366
366
  "type": [
367
367
  "string",
@@ -488,7 +488,7 @@
488
488
  },
489
489
  {
490
490
  "name": "include",
491
- "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/24.1.1/#/elements/vaadin-crud#property-exclude) is ignored.\n\nDefault is undefined meaning that all properties in the object should be mapped to fields.",
491
+ "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/24.1.3/#/elements/vaadin-crud#property-exclude) is ignored.\n\nDefault is undefined meaning that all properties in the object should be mapped to fields.",
492
492
  "value": {
493
493
  "type": [
494
494
  "string",
@@ -499,7 +499,7 @@
499
499
  },
500
500
  {
501
501
  "name": "exclude",
502
- "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/24.1.1/#/elements/vaadin-crud#property-include) is defined, this parameter is ignored.\n\nDefault is to exclude all private fields (those properties starting with underscore)",
502
+ "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/24.1.3/#/elements/vaadin-crud#property-include) is defined, this parameter is ignored.\n\nDefault is to exclude all private fields (those properties starting with underscore)",
503
503
  "value": {
504
504
  "type": [
505
505
  "string",
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "$schema": "https://json.schemastore.org/web-types",
3
3
  "name": "@vaadin/crud",
4
- "version": "24.1.1",
4
+ "version": "24.1.3",
5
5
  "description-markup": "markdown",
6
6
  "framework": "lit",
7
7
  "framework-config": {
@@ -121,7 +121,7 @@
121
121
  },
122
122
  {
123
123
  "name": "vaadin-crud",
124
- "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/24.1.1/#/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/24.1.1/#/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/24.1.1/#/elements/vaadin-crud-edit-column)\n- `<vaadin-crud-grid>` - can be replaced with custom [`<vaadin-grid>`](https://cdn.vaadin.com/vaadin-web-components/24.1.1/#/elements/vaadin-grid)\n- `<vaadin-crud-form>` - can be replaced with custom [`<vaadin-form-layout>`](https://cdn.vaadin.com/vaadin-web-components/24.1.1/#/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/custom-theme/styling-components) documentation.",
124
+ "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/24.1.3/#/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/24.1.3/#/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/24.1.3/#/elements/vaadin-crud-edit-column)\n- `<vaadin-crud-grid>` - can be replaced with custom [`<vaadin-grid>`](https://cdn.vaadin.com/vaadin-web-components/24.1.3/#/elements/vaadin-grid)\n- `<vaadin-crud-form>` - can be replaced with custom [`<vaadin-form-layout>`](https://cdn.vaadin.com/vaadin-web-components/24.1.3/#/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.",
125
125
  "extension": true,
126
126
  "attributes": [
127
127
  {
@@ -196,14 +196,14 @@
196
196
  },
197
197
  {
198
198
  "name": ".include",
199
- "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/24.1.1/#/elements/vaadin-crud#property-exclude) is ignored.\n\nDefault is undefined meaning that all properties in the object should be mapped to fields.",
199
+ "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/24.1.3/#/elements/vaadin-crud#property-exclude) is ignored.\n\nDefault is undefined meaning that all properties in the object should be mapped to fields.",
200
200
  "value": {
201
201
  "kind": "expression"
202
202
  }
203
203
  },
204
204
  {
205
205
  "name": ".exclude",
206
- "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/24.1.1/#/elements/vaadin-crud#property-include) is defined, this parameter is ignored.\n\nDefault is to exclude all private fields (those properties starting with underscore)",
206
+ "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/24.1.3/#/elements/vaadin-crud#property-include) is defined, this parameter is ignored.\n\nDefault is to exclude all private fields (those properties starting with underscore)",
207
207
  "value": {
208
208
  "kind": "expression"
209
209
  }