Skip to content

Commit

Permalink
experiment: add LitElement based version of vaadin-crud (#8346)
Browse files Browse the repository at this point in the history
  • Loading branch information
tomivirkki authored Dec 20, 2024
1 parent 2860b7c commit 242df2b
Show file tree
Hide file tree
Showing 43 changed files with 684 additions and 51 deletions.
18 changes: 3 additions & 15 deletions packages/crud/src/vaadin-crud-edit-column.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
import './vaadin-crud-edit.js';
import { defineCustomElement } from '@vaadin/component-base/src/define.js';
import { GridColumn } from '@vaadin/grid/src/vaadin-grid-column.js';
import { editColumnDefaultRenderer } from './vaadin-crud-helpers.js';

/**
* `<vaadin-crud-edit-column>` is a helper element for the `<vaadin-grid>`
Expand Down Expand Up @@ -69,21 +70,8 @@ class CrudEditColumn extends GridColumn {
*
* @override
*/
_defaultRenderer(root, _column) {
let edit = root.firstElementChild;
if (!edit) {
edit = document.createElement('vaadin-crud-edit');
if (this.hasAttribute('theme')) {
edit.setAttribute('theme', this.getAttribute('theme'));
}
root.appendChild(edit);
}

if (this.ariaLabel) {
edit.setAttribute('aria-label', this.ariaLabel);
} else {
edit.removeAttribute('aria-label');
}
_defaultRenderer(root, column) {
editColumnDefaultRenderer(root, column);
}
}

Expand Down
25 changes: 3 additions & 22 deletions packages/crud/src/vaadin-crud-form.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
import '@vaadin/text-field/src/vaadin-text-field.js';
import { defineCustomElement } from '@vaadin/component-base/src/define.js';
import { FormLayout } from '@vaadin/form-layout/src/vaadin-form-layout.js';
import { capitalize } from './vaadin-crud-helpers.js';
import { createField, createFields } from './vaadin-crud-helpers.js';
import { IncludedMixin } from './vaadin-crud-include-mixin.js';

/**
Expand Down Expand Up @@ -64,31 +64,12 @@ class CrudForm extends IncludedMixin(FormLayout) {

/** @private */
__createField(parent, path) {
const field = document.createElement('vaadin-text-field');
field.label = capitalize(path);
field.path = path;
field.required = true;
parent.appendChild(field);
this._fields.push(field);
return field;
return createField(this, parent, path);
}

/** @private */
__createFields(parent, object, path) {
Object.keys(object).forEach((prop) => {
if (!this.include && this.exclude && this.exclude.test(prop)) {
return;
}
const newPath = (path ? `${path}.` : '') + prop;
if (object[prop] && typeof object[prop] === 'object') {
this.__createFields(parent, object[prop], newPath);
} else {
this.__createField(parent, newPath);
}
});
if (!this._fields.length) {
this._fields = undefined;
}
return createFields(this, parent, object, path);
}
}

Expand Down
1 change: 1 addition & 0 deletions packages/crud/src/vaadin-crud-grid-mixin.js
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ export const CrudGridMixin = (superClass) =>
*/
hideEditColumn: {
type: Boolean,
sync: true,
},
};
}
Expand Down
44 changes: 44 additions & 0 deletions packages/crud/src/vaadin-crud-helpers.js
Original file line number Diff line number Diff line change
Expand Up @@ -66,3 +66,47 @@ export function setProperty(path, value, obj) {
export function isValidEditorPosition(editorPosition) {
return ['bottom', 'aside'].includes(editorPosition);
}

export function editColumnDefaultRenderer(root, column) {
let edit = root.firstElementChild;
if (!edit) {
edit = document.createElement('vaadin-crud-edit');
if (column.hasAttribute('theme')) {
edit.setAttribute('theme', column.getAttribute('theme'));
}
root.appendChild(edit);
}

if (column.ariaLabel) {
edit.setAttribute('aria-label', column.ariaLabel);
} else {
edit.removeAttribute('aria-label');
}
}

export function createField(crudForm, parent, path) {
const field = document.createElement('vaadin-text-field');
field.label = capitalize(path);
field.path = path;
field.required = true;
parent.appendChild(field);
crudForm._fields.push(field);
return field;
}

export function createFields(crudForm, parent, object, path) {
Object.keys(object).forEach((prop) => {
if (!crudForm.include && crudForm.exclude && crudForm.exclude.test(prop)) {
return;
}
const newPath = (path ? `${path}.` : '') + prop;
if (object[prop] && typeof object[prop] === 'object') {
createFields(crudForm, parent, object[prop], newPath);
} else {
createField(crudForm, parent, newPath);
}
});
if (!crudForm._fields.length) {
crudForm._fields = undefined;
}
}
2 changes: 2 additions & 0 deletions packages/crud/src/vaadin-crud-include-mixin.js
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ export const IncludedMixin = (superClass) =>
exclude: {
value: '^_',
observer: '__onExcludeChange',
sync: true,
},

/**
Expand All @@ -40,6 +41,7 @@ export const IncludedMixin = (superClass) =>
*/
include: {
observer: '__onIncludeChange',
sync: true,
},
};
}
Expand Down
12 changes: 11 additions & 1 deletion packages/crud/src/vaadin-crud-mixin.js
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,7 @@ export const CrudMixin = (superClass) =>
type: Object,
observer: '__editedItemChanged',
notify: true,
sync: true,
},

/**
Expand All @@ -117,6 +118,7 @@ export const CrudMixin = (superClass) =>
value: '',
reflectToAttribute: true,
observer: '__editorPositionChanged',
sync: true,
},

/**
Expand All @@ -128,6 +130,7 @@ export const CrudMixin = (superClass) =>
editOnClick: {
type: Boolean,
value: false,
sync: true,
},

/**
Expand Down Expand Up @@ -194,6 +197,7 @@ export const CrudMixin = (superClass) =>
reflectToAttribute: true,
notify: true,
observer: '__editorOpenedChanged',
sync: true,
},

/**
Expand All @@ -218,6 +222,7 @@ export const CrudMixin = (superClass) =>
type: Boolean,
value: false,
reflectToAttribute: true,
sync: true,
},

/**
Expand Down Expand Up @@ -261,6 +266,7 @@ export const CrudMixin = (superClass) =>
*/
i18n: {
type: Object,
sync: true,
value() {
return {
newItem: 'New item',
Expand Down Expand Up @@ -295,7 +301,10 @@ export const CrudMixin = (superClass) =>
__dialogAriaLabel: String,

/** @private */
__isDirty: Boolean,
__isDirty: {
type: Boolean,
sync: true,
},

/** @private */
__isNew: Boolean,
Expand All @@ -307,6 +316,7 @@ export const CrudMixin = (superClass) =>
_fullscreen: {
type: Boolean,
observer: '__fullscreenChanged',
sync: true,
},

/**
Expand Down
11 changes: 11 additions & 0 deletions packages/crud/src/vaadin-lit-crud-dialog.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
/**
* @license
* Copyright (c) 2000 - 2024 Vaadin Ltd.
*
* This program is available under Vaadin Commercial License and Service Terms.
*
*
* See https://vaadin.com/commercial-license-and-service-terms for the full
* license.
*/
export * from './vaadin-crud-dialog.js';
128 changes: 128 additions & 0 deletions packages/crud/src/vaadin-lit-crud-dialog.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
/**
* @license
* Copyright (c) 2000 - 2024 Vaadin Ltd.
*
* This program is available under Vaadin Commercial License and Service Terms.
*
*
* See https://vaadin.com/commercial-license-and-service-terms for the full
* license.
*/
import { css, html, LitElement } from 'lit';
import { ifDefined } from 'lit/directives/if-defined.js';
import { defineCustomElement } from '@vaadin/component-base/src/define.js';
import { DirMixin } from '@vaadin/component-base/src/dir-mixin.js';
import { OverlayClassMixin } from '@vaadin/component-base/src/overlay-class-mixin.js';
import { PolylitMixin } from '@vaadin/component-base/src/polylit-mixin.js';
import { DialogBaseMixin } from '@vaadin/dialog/src/vaadin-dialog-base-mixin.js';
import { dialogOverlay, resizableOverlay } from '@vaadin/dialog/src/vaadin-dialog-styles.js';
import { OverlayMixin } from '@vaadin/overlay/src/vaadin-overlay-mixin.js';
import { overlayStyles } from '@vaadin/overlay/src/vaadin-overlay-styles.js';
import { ThemableMixin } from '@vaadin/vaadin-themable-mixin/vaadin-themable-mixin.js';
import { ThemePropertyMixin } from '@vaadin/vaadin-themable-mixin/vaadin-theme-property-mixin.js';
import { crudDialogOverlayStyles } from './vaadin-crud-styles.js';

/**
* An element used internally by `<vaadin-crud>`. Not intended to be used separately.
*
* @extends HTMLElement
* @mixes DirMixin
* @mixes OverlayMixin
* @mixes ThemableMixin
* @private
*/
class CrudDialogOverlay extends OverlayMixin(DirMixin(ThemableMixin(PolylitMixin(LitElement)))) {
static get is() {
return 'vaadin-crud-dialog-overlay';
}

static get styles() {
return [overlayStyles, dialogOverlay, resizableOverlay, crudDialogOverlayStyles];
}

/** @protected */
render() {
return html`
<div part="backdrop" id="backdrop" ?hidden="${!this.withBackdrop}"></div>
<div part="overlay" id="overlay" tabindex="0">
<section id="resizerContainer" class="resizer-container">
<header part="header"><slot name="header"></slot></header>
<div part="content" id="content">
<slot name="form"></slot>
</div>
<footer part="footer" role="toolbar">
<slot name="save-button"></slot>
<slot name="cancel-button"></slot>
<slot name="delete-button"></slot>
</footer>
</section>
</div>
`;
}

/**
* @protected
* @override
*/
ready() {
super.ready();

// CRUD has header and footer but does not use renderers
this.setAttribute('has-header', '');
this.setAttribute('has-footer', '');
}
}

defineCustomElement(CrudDialogOverlay);

/**
* An element used internally by `<vaadin-crud>`. Not intended to be used separately.
* @private
*/
class CrudDialog extends DialogBaseMixin(OverlayClassMixin(ThemePropertyMixin(PolylitMixin(LitElement)))) {
static get is() {
return 'vaadin-crud-dialog';
}

static get styles() {
return css`
:host {
display: none;
}
`;
}

static get properties() {
return {
ariaLabel: {
type: String,
},

fullscreen: {
type: Boolean,
},
};
}

/** @protected */
render() {
return html`
<vaadin-crud-dialog-overlay
id="overlay"
.opened="${this.opened}"
aria-label="${ifDefined(this.ariaLabel)}"
@opened-changed="${this._onOverlayOpened}"
@mousedown="${this._bringOverlayToFront}"
@touchstart="${this._bringOverlayToFront}"
theme="${ifDefined(this._theme)}"
.modeless="${this.modeless}"
.withBackdrop="${!this.modeless}"
?fullscreen="${this.fullscreen}"
role="dialog"
focus-trap
></vaadin-crud-dialog-overlay>
`;
}
}

defineCustomElement(CrudDialog);
11 changes: 11 additions & 0 deletions packages/crud/src/vaadin-lit-crud-edit-column.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
/**
* @license
* Copyright (c) 2000 - 2024 Vaadin Ltd.
*
* This program is available under Vaadin Commercial License and Service Terms.
*
*
* See https://vaadin.com/commercial-license-and-service-terms for the full
* license.
*/
export * from './vaadin-crud-edit-column.js';
Loading

0 comments on commit 242df2b

Please sign in to comment.