@vaadin/dashboard 24.6.0-alpha1
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/LICENSE +3 -0
- package/README.md +34 -0
- package/package.json +57 -0
- package/src/keyboard-controller.js +107 -0
- package/src/vaadin-dashboard-button.js +45 -0
- package/src/vaadin-dashboard-helpers.js +99 -0
- package/src/vaadin-dashboard-item-mixin.d.ts +20 -0
- package/src/vaadin-dashboard-item-mixin.js +355 -0
- package/src/vaadin-dashboard-layout-mixin.d.ts +28 -0
- package/src/vaadin-dashboard-layout-mixin.js +148 -0
- package/src/vaadin-dashboard-layout.d.ts +56 -0
- package/src/vaadin-dashboard-layout.js +70 -0
- package/src/vaadin-dashboard-section.d.ts +76 -0
- package/src/vaadin-dashboard-section.js +203 -0
- package/src/vaadin-dashboard-styles.js +143 -0
- package/src/vaadin-dashboard-widget.d.ts +101 -0
- package/src/vaadin-dashboard-widget.js +271 -0
- package/src/vaadin-dashboard.d.ts +290 -0
- package/src/vaadin-dashboard.js +489 -0
- package/src/widget-reorder-controller.js +247 -0
- package/src/widget-resize-controller.js +214 -0
- package/theme/lumo/vaadin-dashboard-button-styles.d.ts +2 -0
- package/theme/lumo/vaadin-dashboard-button-styles.js +8 -0
- package/theme/lumo/vaadin-dashboard-button.d.ts +1 -0
- package/theme/lumo/vaadin-dashboard-button.js +1 -0
- package/theme/lumo/vaadin-dashboard-layout-styles.d.ts +1 -0
- package/theme/lumo/vaadin-dashboard-layout-styles.js +11 -0
- package/theme/lumo/vaadin-dashboard-layout.d.ts +2 -0
- package/theme/lumo/vaadin-dashboard-layout.js +2 -0
- package/theme/lumo/vaadin-dashboard-section-styles.d.ts +5 -0
- package/theme/lumo/vaadin-dashboard-section-styles.js +22 -0
- package/theme/lumo/vaadin-dashboard-section.d.ts +3 -0
- package/theme/lumo/vaadin-dashboard-section.js +3 -0
- package/theme/lumo/vaadin-dashboard-styles.d.ts +1 -0
- package/theme/lumo/vaadin-dashboard-styles.js +16 -0
- package/theme/lumo/vaadin-dashboard-widget-styles.d.ts +9 -0
- package/theme/lumo/vaadin-dashboard-widget-styles.js +242 -0
- package/theme/lumo/vaadin-dashboard-widget.d.ts +3 -0
- package/theme/lumo/vaadin-dashboard-widget.js +3 -0
- package/theme/lumo/vaadin-dashboard.d.ts +4 -0
- package/theme/lumo/vaadin-dashboard.js +4 -0
- package/theme/material/vaadin-dashboard-layout.d.ts +1 -0
- package/theme/material/vaadin-dashboard-layout.js +1 -0
- package/theme/material/vaadin-dashboard-section.d.ts +1 -0
- package/theme/material/vaadin-dashboard-section.js +1 -0
- package/theme/material/vaadin-dashboard-widget.d.ts +1 -0
- package/theme/material/vaadin-dashboard-widget.js +1 -0
- package/theme/material/vaadin-dashboard.d.ts +3 -0
- package/theme/material/vaadin-dashboard.js +3 -0
- package/vaadin-dashboard-layout.d.ts +1 -0
- package/vaadin-dashboard-layout.js +3 -0
- package/vaadin-dashboard-section.d.ts +1 -0
- package/vaadin-dashboard-section.js +3 -0
- package/vaadin-dashboard-widget.d.ts +1 -0
- package/vaadin-dashboard-widget.js +3 -0
- package/vaadin-dashboard.d.ts +1 -0
- package/vaadin-dashboard.js +3 -0
- package/web-types.json +260 -0
- package/web-types.lit.json +146 -0
|
@@ -0,0 +1,489 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license
|
|
3
|
+
* Copyright (c) 2000 - 2024 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-dashboard-widget.js';
|
|
12
|
+
import './vaadin-dashboard-section.js';
|
|
13
|
+
import { html, LitElement } from 'lit';
|
|
14
|
+
import { defineCustomElement } from '@vaadin/component-base/src/define.js';
|
|
15
|
+
import { ElementMixin } from '@vaadin/component-base/src/element-mixin.js';
|
|
16
|
+
import { PolylitMixin } from '@vaadin/component-base/src/polylit-mixin.js';
|
|
17
|
+
import { css, ThemableMixin } from '@vaadin/vaadin-themable-mixin/vaadin-themable-mixin.js';
|
|
18
|
+
import {
|
|
19
|
+
getElementItem,
|
|
20
|
+
getItemsArrayOfItem,
|
|
21
|
+
itemsEqual,
|
|
22
|
+
SYNCHRONIZED_ATTRIBUTES,
|
|
23
|
+
WRAPPER_LOCAL_NAME,
|
|
24
|
+
} from './vaadin-dashboard-helpers.js';
|
|
25
|
+
import { getDefaultI18n } from './vaadin-dashboard-item-mixin.js';
|
|
26
|
+
import { DashboardLayoutMixin } from './vaadin-dashboard-layout-mixin.js';
|
|
27
|
+
import { DashboardSection } from './vaadin-dashboard-section.js';
|
|
28
|
+
import { hasWidgetWrappers } from './vaadin-dashboard-styles.js';
|
|
29
|
+
import { WidgetReorderController } from './widget-reorder-controller.js';
|
|
30
|
+
import { WidgetResizeController } from './widget-resize-controller.js';
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* A responsive, grid-based dashboard layout component
|
|
34
|
+
*
|
|
35
|
+
* ### Quick Start
|
|
36
|
+
*
|
|
37
|
+
* Assign an array to the [`items`](#/elements/vaadin-dashboard#property-items) property.
|
|
38
|
+
* Set a renderer function to the [`renderer`](#/elements/vaadin-dashboard#property-renderer) property.
|
|
39
|
+
*
|
|
40
|
+
* The widgets and the sections will be generated and configured based on the renderer and the items provided.
|
|
41
|
+
*
|
|
42
|
+
* ```html
|
|
43
|
+
* <vaadin-dashboard></vaadin-dashboard>
|
|
44
|
+
* ```
|
|
45
|
+
*
|
|
46
|
+
* ```js
|
|
47
|
+
* const dashboard = document.querySelector('vaadin-dashboard');
|
|
48
|
+
*
|
|
49
|
+
* dashboard.items = [
|
|
50
|
+
* { title: 'Widget 1 title', content: 'Text 1', rowspan: 2 },
|
|
51
|
+
* { title: 'Widget 2 title', content: 'Text 2', colspan: 2 },
|
|
52
|
+
* {
|
|
53
|
+
* title: 'Section title',
|
|
54
|
+
* items: [{ title: 'Widget in section title', content: 'Text 3' }]
|
|
55
|
+
* },
|
|
56
|
+
* // ... more items
|
|
57
|
+
* ];
|
|
58
|
+
*
|
|
59
|
+
* dashboard.renderer = (root, _dashboard, { item }) => {
|
|
60
|
+
* const widget = root.firstElementChild || document.createElement('vaadin-dashboard-widget');
|
|
61
|
+
* if (!root.contains(widget)) {
|
|
62
|
+
* root.appendChild(widget);
|
|
63
|
+
* }
|
|
64
|
+
* widget.widgetTitle = item.title;
|
|
65
|
+
* widget.textContent = item.content;
|
|
66
|
+
* };
|
|
67
|
+
* ```
|
|
68
|
+
*
|
|
69
|
+
* ### Styling
|
|
70
|
+
*
|
|
71
|
+
* The following custom properties are available:
|
|
72
|
+
*
|
|
73
|
+
* Custom Property | Description
|
|
74
|
+
* ------------------------------------|-------------
|
|
75
|
+
* `--vaadin-dashboard-col-min-width` | minimum column width of the dashboard
|
|
76
|
+
* `--vaadin-dashboard-col-max-width` | maximum column width of the dashboard
|
|
77
|
+
* `--vaadin-dashboard-row-min-height` | minimum row height of the dashboard
|
|
78
|
+
* `--vaadin-dashboard-col-max-count` | maximum column count of the dashboard
|
|
79
|
+
* `--vaadin-dashboard-spacing` | spacing between child elements and space around its outer edges. Must be in length units (0 is not allowed, 0px is)
|
|
80
|
+
*
|
|
81
|
+
* The following state attributes are available for styling:
|
|
82
|
+
*
|
|
83
|
+
* Attribute | Description
|
|
84
|
+
* ---------------|-------------
|
|
85
|
+
* `editable` | Set when the dashboard is editable.
|
|
86
|
+
* `dense-layout` | Set when the dashboard is in dense mode.
|
|
87
|
+
* `item-selected`| Set when an item is selected.
|
|
88
|
+
*
|
|
89
|
+
* See [Styling Components](https://vaadin.com/docs/latest/styling/styling-components) documentation.
|
|
90
|
+
*
|
|
91
|
+
* @fires {CustomEvent} dashboard-item-moved - Fired when an item was moved
|
|
92
|
+
* @fires {CustomEvent} dashboard-item-resized - Fired when an item was resized
|
|
93
|
+
* @fires {CustomEvent} dashboard-item-removed - Fired when an item was removed
|
|
94
|
+
* @fires {CustomEvent} dashboard-item-selected-changed - Fired when an item selected state changed
|
|
95
|
+
* @fires {CustomEvent} dashboard-item-move-mode-changed - Fired when an item move mode changed
|
|
96
|
+
* @fires {CustomEvent} dashboard-item-resize-mode-changed - Fired when an item resize mode changed
|
|
97
|
+
*
|
|
98
|
+
* @customElement
|
|
99
|
+
* @extends HTMLElement
|
|
100
|
+
* @mixes ElementMixin
|
|
101
|
+
* @mixes DashboardLayoutMixin
|
|
102
|
+
* @mixes ThemableMixin
|
|
103
|
+
*/
|
|
104
|
+
class Dashboard extends DashboardLayoutMixin(ElementMixin(ThemableMixin(PolylitMixin(LitElement)))) {
|
|
105
|
+
static get is() {
|
|
106
|
+
return 'vaadin-dashboard';
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
static get cvdlName() {
|
|
110
|
+
return 'vaadin-dashboard';
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
static get styles() {
|
|
114
|
+
return [
|
|
115
|
+
super.styles,
|
|
116
|
+
css`
|
|
117
|
+
#grid[item-resizing] {
|
|
118
|
+
-webkit-user-select: none;
|
|
119
|
+
user-select: none;
|
|
120
|
+
}
|
|
121
|
+
`,
|
|
122
|
+
hasWidgetWrappers,
|
|
123
|
+
];
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
static get properties() {
|
|
127
|
+
return {
|
|
128
|
+
/**
|
|
129
|
+
* An array containing the items of the dashboard
|
|
130
|
+
* @type {!Array<!DashboardItem> | null | undefined}
|
|
131
|
+
*/
|
|
132
|
+
items: {
|
|
133
|
+
type: Array,
|
|
134
|
+
},
|
|
135
|
+
|
|
136
|
+
/**
|
|
137
|
+
* Custom function for rendering a widget for each dashboard item.
|
|
138
|
+
* Placing something else than a widget in the wrapper is not supported.
|
|
139
|
+
* Receives three arguments:
|
|
140
|
+
*
|
|
141
|
+
* - `root` The container for the widget.
|
|
142
|
+
* - `dashboard` The reference to the `<vaadin-dashboard>` element.
|
|
143
|
+
* - `model` The object with the properties related with the rendered
|
|
144
|
+
* item, contains:
|
|
145
|
+
* - `model.item` The item.
|
|
146
|
+
*
|
|
147
|
+
* @type {DashboardRenderer | null | undefined}
|
|
148
|
+
*/
|
|
149
|
+
renderer: {
|
|
150
|
+
type: Function,
|
|
151
|
+
},
|
|
152
|
+
|
|
153
|
+
/**
|
|
154
|
+
* Whether the dashboard is editable.
|
|
155
|
+
*/
|
|
156
|
+
editable: {
|
|
157
|
+
type: Boolean,
|
|
158
|
+
},
|
|
159
|
+
|
|
160
|
+
/**
|
|
161
|
+
* The object used to localize this component.
|
|
162
|
+
*
|
|
163
|
+
* To change the default localization, replace the entire
|
|
164
|
+
* `i18n` object with a custom one.
|
|
165
|
+
*
|
|
166
|
+
* The object has the following structure and default values:
|
|
167
|
+
* ```
|
|
168
|
+
* {
|
|
169
|
+
* selectSection: 'Select section for editing',
|
|
170
|
+
* selectWidget: 'Select widget for editing',
|
|
171
|
+
* remove: 'Remove',
|
|
172
|
+
* resize: 'Resize',
|
|
173
|
+
* resizeApply: 'Apply',
|
|
174
|
+
* resizeShrinkWidth: 'Shrink width',
|
|
175
|
+
* resizeGrowWidth: 'Grow width',
|
|
176
|
+
* resizeShrinkHeight: 'Shrink height',
|
|
177
|
+
* resizeGrowHeight: 'Grow height',
|
|
178
|
+
* move: 'Move',
|
|
179
|
+
* moveApply: 'Apply',
|
|
180
|
+
* moveForward: 'Move Forward',
|
|
181
|
+
* moveBackward: 'Move Backward',
|
|
182
|
+
* }
|
|
183
|
+
* ```
|
|
184
|
+
*/
|
|
185
|
+
i18n: {
|
|
186
|
+
type: Object,
|
|
187
|
+
value: () => {
|
|
188
|
+
return {
|
|
189
|
+
...getDefaultI18n(),
|
|
190
|
+
};
|
|
191
|
+
},
|
|
192
|
+
},
|
|
193
|
+
};
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
static get observers() {
|
|
197
|
+
return ['__itemsOrRendererChanged(items, renderer, editable, i18n)'];
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
constructor() {
|
|
201
|
+
super();
|
|
202
|
+
this.__widgetReorderController = new WidgetReorderController(this);
|
|
203
|
+
this.__widgetResizeController = new WidgetResizeController(this);
|
|
204
|
+
this.addEventListener('item-remove', (e) => this.__itemRemove(e));
|
|
205
|
+
this.addEventListener('item-selected-changed', (e) => this.__itemSelectedChanged(e));
|
|
206
|
+
this.addEventListener('item-move-mode-changed', (e) => this.__itemMoveModeChanged(e));
|
|
207
|
+
this.addEventListener('item-resize-mode-changed', (e) => this.__itemResizeModeChanged(e));
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
/** @protected */
|
|
211
|
+
ready() {
|
|
212
|
+
super.ready();
|
|
213
|
+
this.addController(this.__widgetReorderController);
|
|
214
|
+
this.addController(this.__widgetResizeController);
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
/** @protected */
|
|
218
|
+
render() {
|
|
219
|
+
return html`<div id="grid"><slot></slot></div>`;
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
/** @private */
|
|
223
|
+
__itemsOrRendererChanged(items, renderer) {
|
|
224
|
+
this.__renderItemWrappers(items || []);
|
|
225
|
+
|
|
226
|
+
this.querySelectorAll(WRAPPER_LOCAL_NAME).forEach((wrapper) => {
|
|
227
|
+
if (wrapper.firstElementChild && wrapper.firstElementChild.localName === 'vaadin-dashboard-section') {
|
|
228
|
+
return;
|
|
229
|
+
}
|
|
230
|
+
const item = getElementItem(wrapper);
|
|
231
|
+
if (item.component instanceof HTMLElement) {
|
|
232
|
+
if (item.component.parentElement !== wrapper) {
|
|
233
|
+
wrapper.textContent = '';
|
|
234
|
+
wrapper.appendChild(item.component);
|
|
235
|
+
}
|
|
236
|
+
} else if (renderer) {
|
|
237
|
+
renderer(wrapper, this, { item });
|
|
238
|
+
} else {
|
|
239
|
+
wrapper.innerHTML = '';
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
if (wrapper.firstElementChild) {
|
|
243
|
+
SYNCHRONIZED_ATTRIBUTES.forEach((attr) => {
|
|
244
|
+
wrapper.firstElementChild.toggleAttribute(attr, !!wrapper[attr]);
|
|
245
|
+
});
|
|
246
|
+
wrapper.firstElementChild.__i18n = this.i18n;
|
|
247
|
+
}
|
|
248
|
+
});
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
/** @private */
|
|
252
|
+
__renderItemWrappers(items, hostElement = this) {
|
|
253
|
+
// Get all the wrappers in the host element
|
|
254
|
+
let wrappers = [...hostElement.children].filter((el) => el.localName === WRAPPER_LOCAL_NAME);
|
|
255
|
+
let previousWrapper = null;
|
|
256
|
+
|
|
257
|
+
const focusedWrapper = wrappers.find((wrapper) => wrapper.querySelector('[focused]'));
|
|
258
|
+
const focusedWrapperWillBeRemoved = focusedWrapper && !this.__isActiveWrapper(focusedWrapper);
|
|
259
|
+
const wrapperClosestToRemovedFocused =
|
|
260
|
+
focusedWrapperWillBeRemoved && this.__getClosestActiveWrapper(focusedWrapper);
|
|
261
|
+
|
|
262
|
+
items.forEach((item) => {
|
|
263
|
+
// Find the wrapper for the item or create a new one
|
|
264
|
+
const wrapper = wrappers.find((el) => itemsEqual(getElementItem(el), item)) || this.__createWrapper(item);
|
|
265
|
+
wrappers = wrappers.filter((el) => el !== wrapper);
|
|
266
|
+
|
|
267
|
+
// Update the wrapper style
|
|
268
|
+
this.__updateWrapper(wrapper, item);
|
|
269
|
+
|
|
270
|
+
if (!wrapper.contains(document.activeElement)) {
|
|
271
|
+
if (previousWrapper) {
|
|
272
|
+
// Append the wrapper after the previous one if it's not already there
|
|
273
|
+
if (wrapper.previousElementSibling !== previousWrapper) {
|
|
274
|
+
previousWrapper.after(wrapper);
|
|
275
|
+
}
|
|
276
|
+
} else if (hostElement.firstChild) {
|
|
277
|
+
// Insert the wrapper as the first child of the host element if it's not already there
|
|
278
|
+
if (wrapper !== hostElement.firstChild) {
|
|
279
|
+
hostElement.insertBefore(wrapper, hostElement.firstChild);
|
|
280
|
+
}
|
|
281
|
+
} else {
|
|
282
|
+
// Append the wrapper to the empty host element
|
|
283
|
+
hostElement.appendChild(wrapper);
|
|
284
|
+
}
|
|
285
|
+
}
|
|
286
|
+
previousWrapper = wrapper;
|
|
287
|
+
|
|
288
|
+
// Render section if the item has subitems
|
|
289
|
+
if (item.items) {
|
|
290
|
+
let section = wrapper.firstElementChild;
|
|
291
|
+
const isComponentSection = item.component instanceof DashboardSection;
|
|
292
|
+
if (!(section instanceof DashboardSection)) {
|
|
293
|
+
// Create a new section if it doesn't exist
|
|
294
|
+
section = isComponentSection ? item.component : document.createElement('vaadin-dashboard-section');
|
|
295
|
+
wrapper.appendChild(section);
|
|
296
|
+
}
|
|
297
|
+
if (!isComponentSection) {
|
|
298
|
+
section.sectionTitle = item.title;
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
SYNCHRONIZED_ATTRIBUTES.forEach((attr) => section.toggleAttribute(attr, !!wrapper[attr]));
|
|
302
|
+
section.__i18n = this.i18n;
|
|
303
|
+
|
|
304
|
+
// Render the subitems
|
|
305
|
+
this.__renderItemWrappers(item.items, section);
|
|
306
|
+
}
|
|
307
|
+
});
|
|
308
|
+
|
|
309
|
+
// Remove the unused wrappers
|
|
310
|
+
wrappers.forEach((wrapper) => wrapper.remove());
|
|
311
|
+
|
|
312
|
+
requestAnimationFrame(() => {
|
|
313
|
+
if (focusedWrapperWillBeRemoved) {
|
|
314
|
+
// The wrapper containing the focused element was removed. Try to focus the element in the closest wrapper.
|
|
315
|
+
this.__focusWrapperContent(wrapperClosestToRemovedFocused || this.querySelector(WRAPPER_LOCAL_NAME));
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
const focusedItem = this.querySelector('[focused]');
|
|
319
|
+
if (focusedItem && !this.__insideViewport(focusedItem)) {
|
|
320
|
+
// If the focused wrapper is not in the viewport, scroll it into view
|
|
321
|
+
focusedItem.scrollIntoView();
|
|
322
|
+
}
|
|
323
|
+
});
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
/** @private */
|
|
327
|
+
__insideViewport(element) {
|
|
328
|
+
const rect = element.getBoundingClientRect();
|
|
329
|
+
const dashboardRect = this.getBoundingClientRect();
|
|
330
|
+
return (
|
|
331
|
+
rect.bottom >= dashboardRect.top &&
|
|
332
|
+
rect.right >= dashboardRect.left &&
|
|
333
|
+
rect.top <= dashboardRect.bottom &&
|
|
334
|
+
rect.left <= dashboardRect.right
|
|
335
|
+
);
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
/** @private */
|
|
339
|
+
__focusWrapperContent(wrapper) {
|
|
340
|
+
if (wrapper && wrapper.firstElementChild) {
|
|
341
|
+
wrapper.firstElementChild.focus();
|
|
342
|
+
}
|
|
343
|
+
}
|
|
344
|
+
|
|
345
|
+
/**
|
|
346
|
+
* Checks if the wrapper represents an item that is part of the dashboard's items array
|
|
347
|
+
* @private
|
|
348
|
+
*/
|
|
349
|
+
__isActiveWrapper(wrapper) {
|
|
350
|
+
if (!wrapper || wrapper.localName !== WRAPPER_LOCAL_NAME) {
|
|
351
|
+
return false;
|
|
352
|
+
}
|
|
353
|
+
return getItemsArrayOfItem(getElementItem(wrapper), this.items);
|
|
354
|
+
}
|
|
355
|
+
|
|
356
|
+
/** @private */
|
|
357
|
+
__getClosestActiveWrapper(wrapper) {
|
|
358
|
+
if (!wrapper || this.__isActiveWrapper(wrapper)) {
|
|
359
|
+
return wrapper;
|
|
360
|
+
}
|
|
361
|
+
|
|
362
|
+
// Starting from the given wrapper element, iterates through the siblings in the given direction
|
|
363
|
+
// to find the closest wrapper that represents an item in the dashboard's items array
|
|
364
|
+
const findSiblingWrapper = (wrapper, dir) => {
|
|
365
|
+
while (wrapper) {
|
|
366
|
+
if (this.__isActiveWrapper(wrapper)) {
|
|
367
|
+
return wrapper;
|
|
368
|
+
}
|
|
369
|
+
wrapper = dir === 1 ? wrapper.nextElementSibling : wrapper.previousElementSibling;
|
|
370
|
+
}
|
|
371
|
+
};
|
|
372
|
+
|
|
373
|
+
return (
|
|
374
|
+
findSiblingWrapper(wrapper, 1) ||
|
|
375
|
+
findSiblingWrapper(wrapper, -1) ||
|
|
376
|
+
this.__getClosestActiveWrapper(wrapper.parentElement.closest(WRAPPER_LOCAL_NAME))
|
|
377
|
+
);
|
|
378
|
+
}
|
|
379
|
+
|
|
380
|
+
/** @private */
|
|
381
|
+
__createWrapper(item) {
|
|
382
|
+
const wrapper = document.createElement(WRAPPER_LOCAL_NAME);
|
|
383
|
+
wrapper.__item = item;
|
|
384
|
+
return wrapper;
|
|
385
|
+
}
|
|
386
|
+
|
|
387
|
+
/** @private */
|
|
388
|
+
__updateWrapper(wrapper, item) {
|
|
389
|
+
const style = `
|
|
390
|
+
${item.colspan ? `--vaadin-dashboard-item-colspan: ${item.colspan};` : ''}
|
|
391
|
+
${item.rowspan ? `--vaadin-dashboard-item-rowspan: ${item.rowspan};` : ''}
|
|
392
|
+
`.trim();
|
|
393
|
+
|
|
394
|
+
wrapper.__item = item;
|
|
395
|
+
wrapper.setAttribute('style', style);
|
|
396
|
+
wrapper.editable = this.editable;
|
|
397
|
+
wrapper.dragging = this.__widgetReorderController.draggedItem === item;
|
|
398
|
+
wrapper['first-child'] = item === getItemsArrayOfItem(item, this.items)[0];
|
|
399
|
+
wrapper['last-child'] = item === getItemsArrayOfItem(item, this.items).slice(-1)[0];
|
|
400
|
+
wrapper.i18n = this.i18n;
|
|
401
|
+
}
|
|
402
|
+
|
|
403
|
+
/** @private */
|
|
404
|
+
__itemRemove(e) {
|
|
405
|
+
e.stopImmediatePropagation();
|
|
406
|
+
const item = getElementItem(e.target);
|
|
407
|
+
const items = getItemsArrayOfItem(item, this.items);
|
|
408
|
+
items.splice(items.indexOf(item), 1);
|
|
409
|
+
this.items = [...this.items];
|
|
410
|
+
this.toggleAttribute('item-selected', false);
|
|
411
|
+
this.dispatchEvent(
|
|
412
|
+
new CustomEvent('dashboard-item-removed', { cancelable: true, detail: { item, items: this.items } }),
|
|
413
|
+
);
|
|
414
|
+
}
|
|
415
|
+
|
|
416
|
+
/** @private */
|
|
417
|
+
__dispatchCustomEvent(eventName, item, value) {
|
|
418
|
+
if (!item) {
|
|
419
|
+
return;
|
|
420
|
+
}
|
|
421
|
+
this.dispatchEvent(
|
|
422
|
+
new CustomEvent(eventName, {
|
|
423
|
+
detail: {
|
|
424
|
+
item,
|
|
425
|
+
value,
|
|
426
|
+
},
|
|
427
|
+
}),
|
|
428
|
+
);
|
|
429
|
+
}
|
|
430
|
+
|
|
431
|
+
/** @private */
|
|
432
|
+
__itemSelectedChanged(e) {
|
|
433
|
+
e.stopImmediatePropagation();
|
|
434
|
+
this.__dispatchCustomEvent('dashboard-item-selected-changed', getElementItem(e.target), e.detail.value);
|
|
435
|
+
this.toggleAttribute('item-selected', e.detail.value);
|
|
436
|
+
}
|
|
437
|
+
|
|
438
|
+
/** @private */
|
|
439
|
+
__itemMoveModeChanged(e) {
|
|
440
|
+
e.stopImmediatePropagation();
|
|
441
|
+
this.__dispatchCustomEvent('dashboard-item-move-mode-changed', getElementItem(e.target), e.detail.value);
|
|
442
|
+
}
|
|
443
|
+
|
|
444
|
+
/** @private */
|
|
445
|
+
__itemResizeModeChanged(e) {
|
|
446
|
+
e.stopImmediatePropagation();
|
|
447
|
+
this.__dispatchCustomEvent('dashboard-item-resize-mode-changed', getElementItem(e.target), e.detail.value);
|
|
448
|
+
}
|
|
449
|
+
|
|
450
|
+
/**
|
|
451
|
+
* Fired when an item selected state changed
|
|
452
|
+
*
|
|
453
|
+
* @event dashboard-item-selected-changed
|
|
454
|
+
*/
|
|
455
|
+
|
|
456
|
+
/**
|
|
457
|
+
* Fired when an item move mode changed
|
|
458
|
+
*
|
|
459
|
+
* @event dashboard-item-move-mode-changed
|
|
460
|
+
*/
|
|
461
|
+
|
|
462
|
+
/**
|
|
463
|
+
* Fired when an item resize mode changed
|
|
464
|
+
*
|
|
465
|
+
* @event dashboard-item-resize-mode-changed
|
|
466
|
+
*/
|
|
467
|
+
|
|
468
|
+
/**
|
|
469
|
+
* Fired when an item was moved
|
|
470
|
+
*
|
|
471
|
+
* @event dashboard-item-moved
|
|
472
|
+
*/
|
|
473
|
+
|
|
474
|
+
/**
|
|
475
|
+
* Fired when an item was resized
|
|
476
|
+
*
|
|
477
|
+
* @event dashboard-item-resized
|
|
478
|
+
*/
|
|
479
|
+
|
|
480
|
+
/**
|
|
481
|
+
* Fired when an item was removed
|
|
482
|
+
*
|
|
483
|
+
* @event dashboard-item-removed
|
|
484
|
+
*/
|
|
485
|
+
}
|
|
486
|
+
|
|
487
|
+
defineCustomElement(Dashboard);
|
|
488
|
+
|
|
489
|
+
export { Dashboard };
|