@omegagrid/dashboard 0.10.2 → 0.10.4

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.
Files changed (41) hide show
  1. package/dist/constants.d.ts +49 -0
  2. package/dist/constants.d.ts.map +1 -0
  3. package/dist/constants.js +14 -0
  4. package/dist/constants.js.map +1 -0
  5. package/dist/index.d.ts +5 -0
  6. package/dist/index.d.ts.map +1 -0
  7. package/dist/index.js +5 -0
  8. package/dist/index.js.map +1 -0
  9. package/dist/model/dashboardItemModel.d.ts +20 -0
  10. package/dist/model/dashboardItemModel.d.ts.map +1 -0
  11. package/dist/model/dashboardItemModel.js +34 -0
  12. package/dist/model/dashboardItemModel.js.map +1 -0
  13. package/dist/model/dashboardModel.d.ts +27 -0
  14. package/dist/model/dashboardModel.d.ts.map +1 -0
  15. package/dist/model/dashboardModel.js +277 -0
  16. package/dist/model/dashboardModel.js.map +1 -0
  17. package/dist/model/index.d.ts +3 -0
  18. package/dist/model/index.d.ts.map +1 -0
  19. package/dist/model/index.js +3 -0
  20. package/dist/model/index.js.map +1 -0
  21. package/dist/types.d.ts +40 -0
  22. package/dist/types.d.ts.map +1 -0
  23. package/dist/types.js +2 -0
  24. package/dist/types.js.map +1 -0
  25. package/dist/ui/dashboard.d.ts +56 -0
  26. package/dist/ui/dashboard.d.ts.map +1 -0
  27. package/dist/ui/dashboard.js +405 -0
  28. package/dist/ui/dashboard.js.map +1 -0
  29. package/dist/ui/dashboard.style.d.ts +2 -0
  30. package/dist/ui/dashboard.style.d.ts.map +1 -0
  31. package/dist/ui/dashboard.style.js +60 -0
  32. package/dist/ui/dashboard.style.js.map +1 -0
  33. package/dist/ui/dashboardItem.d.ts +44 -0
  34. package/dist/ui/dashboardItem.d.ts.map +1 -0
  35. package/dist/ui/dashboardItem.js +195 -0
  36. package/dist/ui/dashboardItem.js.map +1 -0
  37. package/dist/ui/index.d.ts +3 -0
  38. package/dist/ui/index.d.ts.map +1 -0
  39. package/dist/ui/index.js +3 -0
  40. package/dist/ui/index.js.map +1 -0
  41. package/package.json +3 -3
@@ -0,0 +1,56 @@
1
+ import { ComponentFactory, ComponentStore, Layout, OmegaComponent, Rect, Container, Size } from '@omegagrid/core';
2
+ import { DashboardItemModel, DashboardModel } from '../model';
3
+ import { DashboardSource } from '../types';
4
+ import { DashboardItem } from './dashboardItem';
5
+ export declare class DashboardEvent extends Event {
6
+ readonly item: DashboardItem;
7
+ readonly model: DashboardItemModel;
8
+ constructor(type: string, args: Partial<DashboardEvent>);
9
+ }
10
+ export declare class Dashboard extends OmegaComponent implements Layout {
11
+ static styles: import("lit").CSSResultGroup[];
12
+ model: DashboardModel;
13
+ designMode: boolean;
14
+ noGrid: boolean;
15
+ createComponent: ComponentFactory;
16
+ items: NodeList;
17
+ container: Container;
18
+ content: HTMLDivElement;
19
+ placeholder: HTMLDivElement;
20
+ gridCanvas: HTMLCanvasElement;
21
+ private _currentItem;
22
+ private _previewPositions;
23
+ private _autoScrollInterval;
24
+ private _autoScrollSpeed;
25
+ private _isResizing;
26
+ readonly components: ComponentStore<HTMLElement & Layout>;
27
+ private _baseSize;
28
+ get baseSize(): Size;
29
+ startMove(item: DashboardItem): void;
30
+ startResize(item: DashboardItem): void;
31
+ stopMove(): void;
32
+ get scrollOffset(): number;
33
+ offsetToXCoord(offset: number): number;
34
+ offsetToYCoord(offset: number): number;
35
+ updatePreviewPositions(): void;
36
+ previewLayout(rect: Rect): void;
37
+ checkAutoScroll(item: DashboardItem): void;
38
+ checkResizeExpansion(item: DashboardItem): void;
39
+ startAutoScroll(): void;
40
+ stopAutoScroll(): void;
41
+ expandContentArea(): void;
42
+ _onItemMove: (e: DashboardEvent) => void;
43
+ _onItemResize: (e: DashboardEvent) => void;
44
+ constructor();
45
+ calculateItemLocation(item: Rect): Rect;
46
+ showPlaceholder(rect: Rect): void;
47
+ hidePlaceholder(): void;
48
+ setSourceData(source: DashboardSource): void;
49
+ setItemPosition(elm: HTMLElement, rect: Rect): void;
50
+ fixCollisions(): void;
51
+ layout(): void;
52
+ drawGrid(): Promise<void>;
53
+ updated(): void;
54
+ render: () => import("lit-html").TemplateResult<1> | "";
55
+ }
56
+ //# sourceMappingURL=dashboard.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dashboard.d.ts","sourceRoot":"","sources":["../../src/ui/dashboard.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,cAAc,EAAE,MAAM,EAAE,cAAc,EAAO,IAAI,EAAE,SAAS,EAAE,IAAI,EAAE,MAAM,iBAAiB,CAAC;AAKvH,OAAO,EAAE,kBAAkB,EAAE,cAAc,EAAE,MAAM,UAAU,CAAC;AAC9D,OAAO,EAAE,eAAe,EAAE,MAAM,UAAU,CAAC;AAC3C,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAEhD,qBAAa,cAAe,SAAQ,KAAK;IAExC,QAAQ,CAAC,IAAI,EAAE,aAAa,CAAC;IAC7B,QAAQ,CAAC,KAAK,EAAE,kBAAkB,CAAC;gBAEvB,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,CAAC,cAAc,CAAC;CAIvD;AAED,qBACa,SAAU,SAAQ,cAAe,YAAW,MAAM;IAE9D,MAAM,CAAC,MAAM,iCAAkC;IAG/C,KAAK,EAAE,cAAc,CAAC;IAGtB,UAAU,UAAS;IAGnB,MAAM,UAAS;IAGf,eAAe,EAAE,gBAAgB,CAAC;IAGlC,KAAK,EAAE,QAAQ,CAAC;IAGhB,SAAS,EAAE,SAAS,CAAC;IAGrB,OAAO,EAAE,cAAc,CAAC;IAGxB,WAAW,EAAE,cAAc,CAAC;IAG5B,UAAU,EAAE,iBAAiB,CAAC;IAE9B,OAAO,CAAC,YAAY,CAAgB;IACpC,OAAO,CAAC,iBAAiB,CAAS;IAClC,OAAO,CAAC,mBAAmB,CAAgB;IAC3C,OAAO,CAAC,gBAAgB,CAAkB;IAC1C,OAAO,CAAC,WAAW,CAAS;IAE5B,QAAQ,CAAC,UAAU,uCAEjB;IAEF,OAAO,CAAC,SAAS,CAAO;IACxB,IAAI,QAAQ,SAYX;IAED,SAAS,CAAC,IAAI,EAAE,aAAa;IAO7B,WAAW,CAAC,IAAI,EAAE,aAAa;IAO/B,QAAQ;IAUR,IAAI,YAAY,WAEf;IAED,cAAc,CAAC,MAAM,EAAE,MAAM;IAI7B,cAAc,CAAC,MAAM,EAAE,MAAM;IAI7B,sBAAsB;IAOtB,aAAa,CAAC,IAAI,EAAE,IAAI;IAQxB,eAAe,CAAC,IAAI,EAAE,aAAa;IAuCnC,oBAAoB,CAAC,IAAI,EAAE,aAAa;IAsCxC,eAAe;IAiDf,cAAc;IAQd,iBAAiB;IA8CjB,WAAW,GAAI,GAAG,cAAc,UAS/B;IAED,aAAa,GAAI,GAAG,cAAc,UASjC;;IAYD,qBAAqB,CAAC,IAAI,EAAE,IAAI,GAAI,IAAI;IAWxC,eAAe,CAAC,IAAI,EAAE,IAAI;IAK1B,eAAe;IAIf,aAAa,CAAC,MAAM,EAAE,eAAe;IAMrC,eAAe,CAAC,GAAG,EAAE,WAAW,EAAE,IAAI,EAAE,IAAI;IAM5C,aAAa;IAMb,MAAM;IAcA,QAAQ;IAyCd,OAAO;IAIP,MAAM,kDAgBC;CAEP"}
@@ -0,0 +1,405 @@
1
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
2
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
3
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
4
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
5
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
6
+ };
7
+ import { ComponentStore, OmegaComponent, dom } from '@omegagrid/core';
8
+ import { html } from 'lit';
9
+ import { customElement, property, query, queryAll } from 'lit/decorators.js';
10
+ import { map } from 'lit/directives/map.js';
11
+ import { style } from './dashboard.style';
12
+ import { DashboardModel } from '../model';
13
+ export class DashboardEvent extends Event {
14
+ constructor(type, args) {
15
+ super(`dashboard.${type}`, { bubbles: true, composed: true });
16
+ Object.assign(this, args);
17
+ }
18
+ }
19
+ let Dashboard = class Dashboard extends OmegaComponent {
20
+ get baseSize() {
21
+ if (this._baseSize)
22
+ return this._baseSize;
23
+ const { columns, columnWidth, rows, rowHeight, gap } = this.model.options;
24
+ this._baseSize = {
25
+ w: columnWidth || (columns ? (this.container.clientWidth - ((columns + 1) * gap)) / columns : null),
26
+ h: rowHeight || (rows ? (this.container.clientHeight - ((rows + 1) * gap)) / rows : null),
27
+ };
28
+ if (this._baseSize.w == null)
29
+ this._baseSize.w = this._baseSize.h;
30
+ if (this._baseSize.h == null)
31
+ this._baseSize.h = this._baseSize.w;
32
+ return this._baseSize;
33
+ }
34
+ startMove(item) {
35
+ this._currentItem = item;
36
+ this._currentItem.classList.toggle('active', true);
37
+ this.classList.toggle('moving', true);
38
+ this._isResizing = false;
39
+ }
40
+ startResize(item) {
41
+ this._currentItem = item;
42
+ this._currentItem.classList.toggle('active', true);
43
+ this.classList.toggle('moving', true);
44
+ this._isResizing = true;
45
+ }
46
+ stopMove() {
47
+ if (!this._currentItem)
48
+ return;
49
+ this._currentItem.classList.toggle('active', false);
50
+ this._currentItem = null;
51
+ this.classList.toggle('moving', false);
52
+ this.hidePlaceholder();
53
+ this.updatePreviewPositions();
54
+ this.stopAutoScroll();
55
+ }
56
+ get scrollOffset() {
57
+ return this.container?.verticalSlider?.value || 0;
58
+ }
59
+ offsetToXCoord(offset) {
60
+ return Math.max(0, Math.floor(offset / (this.baseSize.w + this.model.options.gap)));
61
+ }
62
+ offsetToYCoord(offset) {
63
+ return Math.max(0, Math.floor(offset / (this.baseSize.h + this.model.options.gap)));
64
+ }
65
+ updatePreviewPositions() {
66
+ if (!this._previewPositions)
67
+ return;
68
+ this.model.updatePositions(this._previewPositions);
69
+ this._previewPositions = null;
70
+ this.layout();
71
+ }
72
+ previewLayout(rect) {
73
+ this._previewPositions = this.model.calculatePositions(this._currentItem.model, rect);
74
+ this._previewPositions.forEach((rect, i) => {
75
+ const item = this.items[i];
76
+ if (item && item != this._currentItem)
77
+ this.setItemPosition(item, rect);
78
+ });
79
+ }
80
+ checkAutoScroll(item) {
81
+ if (!this.container)
82
+ return;
83
+ // For resize, also expand content area preemptively so there's space to scroll into
84
+ if (this._isResizing) {
85
+ this.checkResizeExpansion(item);
86
+ }
87
+ const threshold = 50; // pixels from edge to trigger scroll
88
+ const scrollSpeed = 5; // pixels per frame
89
+ const containerRect = this.container.getBoundingClientRect();
90
+ const itemRect = item.getBoundingClientRect();
91
+ let scrollX = 0;
92
+ let scrollY = 0;
93
+ // Check horizontal scrolling
94
+ if (itemRect.right > containerRect.right - threshold) {
95
+ scrollX = scrollSpeed;
96
+ }
97
+ else if (itemRect.left < containerRect.left + threshold) {
98
+ scrollX = -scrollSpeed;
99
+ }
100
+ // Check vertical scrolling
101
+ if (itemRect.bottom > containerRect.bottom - threshold) {
102
+ scrollY = scrollSpeed;
103
+ }
104
+ else if (itemRect.top < containerRect.top + threshold) {
105
+ scrollY = -scrollSpeed;
106
+ }
107
+ this._autoScrollSpeed = { x: scrollX, y: scrollY };
108
+ if ((scrollX !== 0 || scrollY !== 0) && !this._autoScrollInterval) {
109
+ this.startAutoScroll();
110
+ }
111
+ else if (scrollX === 0 && scrollY === 0 && this._autoScrollInterval) {
112
+ this.stopAutoScroll();
113
+ }
114
+ }
115
+ checkResizeExpansion(item) {
116
+ if (!this.container || !this.model)
117
+ return;
118
+ const baseSize = this.baseSize;
119
+ const gap = this.model.options.gap;
120
+ // Item edges in content coordinates - offsetTop is already content-relative
121
+ const itemBottom = item.offsetTop + item.offsetHeight;
122
+ const itemRight = item.offsetLeft + item.offsetWidth;
123
+ const currentContentHeight = this.content.offsetHeight;
124
+ const currentContentWidth = this.content.offsetWidth;
125
+ // Threshold: expand when item is within 1 grid cell of the content edge
126
+ const thresholdY = baseSize.h + gap;
127
+ const thresholdX = baseSize.w + gap;
128
+ let newHeight = currentContentHeight;
129
+ let newWidth = currentContentWidth;
130
+ let needsUpdate = false;
131
+ if (itemBottom > currentContentHeight - thresholdY) {
132
+ newHeight = currentContentHeight + 5 * (baseSize.h + gap);
133
+ needsUpdate = true;
134
+ }
135
+ if (itemRight > currentContentWidth - thresholdX) {
136
+ newWidth = currentContentWidth + 5 * (baseSize.w + gap);
137
+ needsUpdate = true;
138
+ }
139
+ if (needsUpdate) {
140
+ dom.setSize(this.content, { w: newWidth, h: newHeight });
141
+ this.model.size.w = Math.max(this.model.size.w, Math.ceil((newWidth - gap) / (baseSize.w + gap)));
142
+ this.model.size.h = Math.max(this.model.size.h, Math.ceil((newHeight - gap) / (baseSize.h + gap)));
143
+ this.drawGrid();
144
+ }
145
+ }
146
+ startAutoScroll() {
147
+ if (this._autoScrollInterval)
148
+ return;
149
+ this._autoScrollInterval = window.setInterval(() => {
150
+ if (!this.container)
151
+ return;
152
+ const { x, y } = this._autoScrollSpeed;
153
+ // Scroll vertically
154
+ if (y !== 0 && this.container.verticalSlider) {
155
+ const currentScroll = this.container.verticalSlider.value;
156
+ const maxScroll = this.container.verticalSlider.maxValue;
157
+ // Expand content area if scrolling down near the bottom
158
+ if (y > 0 && currentScroll >= maxScroll * 0.85) {
159
+ this.expandContentArea();
160
+ // After expanding, continue scrolling
161
+ const newMaxScroll = this.container.verticalSlider.maxValue;
162
+ this.container.scrollVerticalTo(Math.min(newMaxScroll, currentScroll + y));
163
+ }
164
+ else {
165
+ const newScroll = Math.max(0, Math.min(maxScroll, currentScroll + y));
166
+ this.container.scrollVerticalTo(newScroll);
167
+ }
168
+ }
169
+ // Scroll horizontally
170
+ if (x !== 0 && this.container.horizontalSlider) {
171
+ const currentScroll = this.container.horizontalSlider.value;
172
+ const maxScroll = this.container.horizontalSlider.maxValue;
173
+ // Expand content area if scrolling right near the edge
174
+ if (x > 0 && currentScroll >= maxScroll * 0.85) {
175
+ this.expandContentArea();
176
+ // After expanding, continue scrolling
177
+ const newMaxScroll = this.container.horizontalSlider.maxValue;
178
+ this.container.scrollHorizontalTo(Math.min(newMaxScroll, currentScroll + x));
179
+ }
180
+ else {
181
+ const newScroll = Math.max(0, Math.min(maxScroll, currentScroll + x));
182
+ this.container.scrollHorizontalTo(newScroll);
183
+ }
184
+ }
185
+ // During resize, update item size with new scroll offset so placeholder follows smoothly
186
+ if (this._isResizing && this._currentItem) {
187
+ this._currentItem.updateResize();
188
+ }
189
+ }, 16); // ~60fps
190
+ }
191
+ stopAutoScroll() {
192
+ if (this._autoScrollInterval) {
193
+ window.clearInterval(this._autoScrollInterval);
194
+ this._autoScrollInterval = null;
195
+ }
196
+ this._autoScrollSpeed = { x: 0, y: 0 };
197
+ }
198
+ expandContentArea() {
199
+ if (!this.model || !this._currentItem)
200
+ return;
201
+ // Calculate how much space we need based on current item position
202
+ const topOffset = this.scrollOffset;
203
+ const itemBottom = this._currentItem.offsetTop + this._currentItem.offsetHeight + topOffset;
204
+ const itemRight = this._currentItem.offsetLeft + this._currentItem.offsetWidth;
205
+ const currentContentHeight = this.content.offsetHeight;
206
+ const currentContentWidth = this.content.offsetWidth;
207
+ // Expand by 2 grid cells if needed
208
+ const expandRows = 2;
209
+ const expandCols = 2;
210
+ const baseSize = this.baseSize;
211
+ const gap = this.model.options.gap;
212
+ let newHeight = currentContentHeight;
213
+ let newWidth = currentContentWidth;
214
+ // Check if we need more height - only expand, never shrink
215
+ if (itemBottom > currentContentHeight - gap * 2) {
216
+ newHeight = Math.max(currentContentHeight, currentContentHeight + expandRows * (baseSize.h + gap));
217
+ }
218
+ // Check if we need more width - only expand, never shrink
219
+ if (itemRight > currentContentWidth - gap * 2) {
220
+ newWidth = Math.max(currentContentWidth, currentContentWidth + expandCols * (baseSize.w + gap));
221
+ }
222
+ // Only update if size actually changed
223
+ if (newHeight !== currentContentHeight || newWidth !== currentContentWidth) {
224
+ dom.setSize(this.content, { w: newWidth, h: newHeight });
225
+ // Update model size to match new content dimensions
226
+ const newModelWidth = Math.ceil((newWidth - gap) / (baseSize.w + gap));
227
+ const newModelHeight = Math.ceil((newHeight - gap) / (baseSize.h + gap));
228
+ // Only update if model size increased
229
+ this.model.size.w = Math.max(this.model.size.w, newModelWidth);
230
+ this.model.size.h = Math.max(this.model.size.h, newModelHeight);
231
+ this.drawGrid();
232
+ }
233
+ }
234
+ constructor() {
235
+ super();
236
+ this.designMode = false;
237
+ this.noGrid = false;
238
+ this._autoScrollInterval = null;
239
+ this._autoScrollSpeed = { x: 0, y: 0 };
240
+ this._isResizing = false;
241
+ this.components = new ComponentStore(id => this.createComponent ? this.createComponent(id) : null);
242
+ this._onItemMove = (e) => {
243
+ if (!e.item.moving)
244
+ return;
245
+ const topOffset = this.scrollOffset;
246
+ const x = this.offsetToXCoord(e.item.offsetLeft);
247
+ const y = this.offsetToYCoord(e.item.offsetTop + topOffset);
248
+ const rect = { x, y, w: e.item.model.w, h: e.item.model.h };
249
+ this.showPlaceholder(rect);
250
+ this.previewLayout(rect);
251
+ this.checkAutoScroll(e.item);
252
+ };
253
+ this._onItemResize = (e) => {
254
+ if (!e.item.resizing)
255
+ return;
256
+ const topOffset = this.scrollOffset;
257
+ const w = this.offsetToXCoord(e.item.offsetLeft + e.item.offsetWidth) - e.item.model.x + 1;
258
+ const h = this.offsetToYCoord(e.item.offsetTop + e.item.offsetHeight + topOffset) - e.item.model.y + 1;
259
+ const rect = { x: e.item.model.x, y: e.item.model.y, w, h };
260
+ this.showPlaceholder(rect);
261
+ this.previewLayout(rect);
262
+ this.checkAutoScroll(e.item);
263
+ };
264
+ this.render = () => this.model ? html `
265
+ <og-container>
266
+ <div slot="content">
267
+ ${this.designMode ? html `
268
+ ${this.noGrid ? '' : html `<canvas class="item-grid"></canvas>`}
269
+ <div class="item-placeholder"></div>
270
+ ` : null}
271
+ ${map(this.model.items, item => html `
272
+ <og-dashboard-item
273
+ ?designMode="${this.designMode}"
274
+ .model="${item}"
275
+ .components="${this.components}">
276
+ </og-dashboard-item>
277
+ `)}
278
+ </div>
279
+ </og-container>
280
+ ` : '';
281
+ this.addEventListener('dashboard.movestart', (e) => this.startMove(e.item));
282
+ this.addEventListener('dashboard.resizestart', (e) => this.startResize(e.item));
283
+ this.addEventListener('dashboard.movestop', () => this.stopMove());
284
+ this.addEventListener('dashboard.resizestop', () => this.stopMove());
285
+ this.addEventListener('dashboard.move', this._onItemMove);
286
+ this.addEventListener('dashboard.resize', this._onItemResize);
287
+ }
288
+ calculateItemLocation(item) {
289
+ const baseSize = this.baseSize;
290
+ const gap = this.model.options.gap;
291
+ return {
292
+ x: item.x * (baseSize.w + gap) + gap,
293
+ y: item.y * (baseSize.h + gap) + gap,
294
+ w: item.w * (baseSize.w + gap) - gap,
295
+ h: item.h * (baseSize.h + gap) - gap,
296
+ };
297
+ }
298
+ showPlaceholder(rect) {
299
+ dom.showElement(this.placeholder);
300
+ this.setItemPosition(this.placeholder, rect);
301
+ }
302
+ hidePlaceholder() {
303
+ dom.hideElement(this.placeholder);
304
+ }
305
+ setSourceData(source) {
306
+ this.components.clear();
307
+ this.model = new DashboardModel(source);
308
+ this.model.detectAndFixCollisions();
309
+ }
310
+ setItemPosition(elm, rect) {
311
+ const { x, y, w, h } = this.calculateItemLocation(rect);
312
+ dom.setSize(elm, { w, h });
313
+ dom.setPosition(elm, { l: x, t: y });
314
+ }
315
+ fixCollisions() {
316
+ if (!this.model)
317
+ return;
318
+ this.model.detectAndFixCollisions();
319
+ this.layout();
320
+ }
321
+ layout() {
322
+ this._baseSize = null;
323
+ if (!this.model)
324
+ return;
325
+ this.items?.forEach((item) => this.setItemPosition(item, item.model));
326
+ dom.setSize(this.content, {
327
+ w: this.model.size.w * (this.baseSize.w + this.model.options.gap) + this.model.options.gap,
328
+ h: this.model.size.h * (this.baseSize.h + this.model.options.gap) + this.model.options.gap
329
+ });
330
+ this.items?.forEach((item) => item.layout());
331
+ this.drawGrid();
332
+ }
333
+ async drawGrid() {
334
+ if (!this.gridCanvas)
335
+ return;
336
+ if (this.container.isUpdatePending)
337
+ await this.container.updateComplete;
338
+ const ctx = this.gridCanvas.getContext('2d');
339
+ if (!ctx)
340
+ return;
341
+ const gap = this.model.options.gap;
342
+ const baseSize = this.baseSize;
343
+ this.gridCanvas.style.width = '100%';
344
+ this.gridCanvas.style.height = '100%';
345
+ const width = this.gridCanvas.offsetWidth;
346
+ this.gridCanvas.width = width;
347
+ const height = this.gridCanvas.offsetHeight;
348
+ this.gridCanvas.height = height;
349
+ const columns = width / baseSize.w;
350
+ const rows = height / baseSize.h;
351
+ ctx.clearRect(0, 0, width, height);
352
+ ctx.strokeStyle = 'rgba(116,116,116,0.2)';
353
+ ctx.lineWidth = 1;
354
+ for (let i = 0; i <= columns; i++) {
355
+ const x = Math.round(i * (baseSize.w + gap) + gap / 2) + 0.5;
356
+ ctx.beginPath();
357
+ ctx.moveTo(x, 0);
358
+ ctx.lineTo(x, height);
359
+ ctx.stroke();
360
+ }
361
+ for (let i = 0; i <= rows; i++) {
362
+ const y = Math.round(i * (baseSize.h + gap) + gap / 2) + 0.5;
363
+ ctx.beginPath();
364
+ ctx.moveTo(0, y);
365
+ ctx.lineTo(width, y);
366
+ ctx.stroke();
367
+ }
368
+ }
369
+ updated() {
370
+ this.layout();
371
+ }
372
+ };
373
+ Dashboard.styles = [OmegaComponent.styles, style];
374
+ __decorate([
375
+ property({ type: Object })
376
+ ], Dashboard.prototype, "model", void 0);
377
+ __decorate([
378
+ property({ type: Boolean, reflect: true })
379
+ ], Dashboard.prototype, "designMode", void 0);
380
+ __decorate([
381
+ property({ type: Boolean })
382
+ ], Dashboard.prototype, "noGrid", void 0);
383
+ __decorate([
384
+ property({ type: Object })
385
+ ], Dashboard.prototype, "createComponent", void 0);
386
+ __decorate([
387
+ queryAll('og-dashboard-item')
388
+ ], Dashboard.prototype, "items", void 0);
389
+ __decorate([
390
+ query('og-container')
391
+ ], Dashboard.prototype, "container", void 0);
392
+ __decorate([
393
+ query('[slot="content"]')
394
+ ], Dashboard.prototype, "content", void 0);
395
+ __decorate([
396
+ query('.item-placeholder')
397
+ ], Dashboard.prototype, "placeholder", void 0);
398
+ __decorate([
399
+ query('.item-grid')
400
+ ], Dashboard.prototype, "gridCanvas", void 0);
401
+ Dashboard = __decorate([
402
+ customElement('og-dashboard')
403
+ ], Dashboard);
404
+ export { Dashboard };
405
+ //# sourceMappingURL=dashboard.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dashboard.js","sourceRoot":"","sources":["../../src/ui/dashboard.ts"],"names":[],"mappings":"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","sourcesContent":["import { ComponentFactory, ComponentStore, Layout, OmegaComponent, dom, Rect, Container, Size } from '@omegagrid/core';\nimport { html } from 'lit';\nimport { customElement, property, query, queryAll } from 'lit/decorators.js';\nimport { map } from 'lit/directives/map.js';\nimport { style } from './dashboard.style';\nimport { DashboardItemModel, DashboardModel } from '../model';\nimport { DashboardSource } from '../types';\nimport { DashboardItem } from './dashboardItem';\n\nexport class DashboardEvent extends Event {\n\n\treadonly item: DashboardItem;\n\treadonly model: DashboardItemModel;\n\n\tconstructor(type: string, args: Partial<DashboardEvent>) {\n\t\tsuper(`dashboard.${type}`, {bubbles: true, composed: true});\n\t\tObject.assign(this, args);\n\t}\n}\n\n@customElement('og-dashboard')\nexport class Dashboard extends OmegaComponent implements Layout {\n\n\tstatic styles = [OmegaComponent.styles, style];\n\n\t@property({type: Object})\n\tmodel: DashboardModel;\n\n\t@property({type: Boolean, reflect: true})\n\tdesignMode = false;\n\n\t@property({type: Boolean})\n\tnoGrid = false;\n\n\t@property({type: Object})\n\tcreateComponent: ComponentFactory;\n\n\t@queryAll('og-dashboard-item')\n\titems: NodeList;\n\n\t@query('og-container')\n\tcontainer: Container;\n\n\t@query('[slot=\"content\"]')\n\tcontent: HTMLDivElement;\n\n\t@query('.item-placeholder')\n\tplaceholder: HTMLDivElement;\n\n\t@query('.item-grid')\n\tgridCanvas: HTMLCanvasElement;\n\n\tprivate _currentItem: DashboardItem;\n\tprivate _previewPositions: Rect[];\n\tprivate _autoScrollInterval: number = null;\n\tprivate _autoScrollSpeed = { x: 0, y: 0 };\n\tprivate _isResizing = false;\n\n\treadonly components = new ComponentStore<HTMLElement & Layout>(\n\t\tid => this.createComponent ? this.createComponent(id) as HTMLElement & Layout : null\n\t);\n\n\tprivate _baseSize: Size;\n\tget baseSize() {\n\t\tif (this._baseSize) return this._baseSize;\n\t\tconst { columns, columnWidth, rows, rowHeight, gap } = this.model.options;\n\n\t\tthis._baseSize = {\n\t\t\tw: columnWidth || (columns ? (this.container.clientWidth - ((columns + 1) * gap)) / columns : null),\n\t\t\th: rowHeight || (rows ? (this.container.clientHeight - ((rows + 1) * gap)) / rows : null),\n\t\t};\n\n\t\tif (this._baseSize.w == null) this._baseSize.w = this._baseSize.h;\n\t\tif (this._baseSize.h == null) this._baseSize.h = this._baseSize.w;\n\t\treturn this._baseSize;\n\t}\n\n\tstartMove(item: DashboardItem) {\n\t\tthis._currentItem = item;\n\t\tthis._currentItem.classList.toggle('active', true);\n\t\tthis.classList.toggle('moving', true);\n\t\tthis._isResizing = false;\n\t}\n\n\tstartResize(item: DashboardItem) {\n\t\tthis._currentItem = item;\n\t\tthis._currentItem.classList.toggle('active', true);\n\t\tthis.classList.toggle('moving', true);\n\t\tthis._isResizing = true;\n\t}\n\n\tstopMove() {\n\t\tif (!this._currentItem) return;\n\t\tthis._currentItem.classList.toggle('active', false);\n\t\tthis._currentItem = null;\n\t\tthis.classList.toggle('moving', false);\n\t\tthis.hidePlaceholder();\n\t\tthis.updatePreviewPositions();\n\t\tthis.stopAutoScroll();\n\t}\n\n\tget scrollOffset() {\n\t\treturn this.container?.verticalSlider?.value || 0;\n\t}\n\n\toffsetToXCoord(offset: number) {\n\t\treturn Math.max(0, Math.floor(offset / (this.baseSize.w + this.model.options.gap)));\n\t}\n\n\toffsetToYCoord(offset: number) {\n\t\treturn Math.max(0, Math.floor(offset / (this.baseSize.h + this.model.options.gap)));\n\t}\n\n\tupdatePreviewPositions() {\n\t\tif (!this._previewPositions) return;\n\t\tthis.model.updatePositions(this._previewPositions);\n\t\tthis._previewPositions = null;\n\t\tthis.layout();\n\t}\n\n\tpreviewLayout(rect: Rect) {\n\t\tthis._previewPositions = this.model.calculatePositions(this._currentItem.model, rect);\n\t\tthis._previewPositions.forEach((rect, i) => {\n\t\t\tconst item = this.items[i] as DashboardItem;\n\t\t\tif (item && item != this._currentItem) this.setItemPosition(item, rect);\n\t\t});\n\t}\n\n\tcheckAutoScroll(item: DashboardItem) {\n\t\tif (!this.container) return;\n\n\t\t// For resize, also expand content area preemptively so there's space to scroll into\n\t\tif (this._isResizing) {\n\t\t\tthis.checkResizeExpansion(item);\n\t\t}\n\n\t\tconst threshold = 50; // pixels from edge to trigger scroll\n\t\tconst scrollSpeed = 5; // pixels per frame\n\t\tconst containerRect = this.container.getBoundingClientRect();\n\t\tconst itemRect = item.getBoundingClientRect();\n\n\t\tlet scrollX = 0;\n\t\tlet scrollY = 0;\n\n\t\t// Check horizontal scrolling\n\t\tif (itemRect.right > containerRect.right - threshold) {\n\t\t\tscrollX = scrollSpeed;\n\t\t} else if (itemRect.left < containerRect.left + threshold) {\n\t\t\tscrollX = -scrollSpeed;\n\t\t}\n\n\t\t// Check vertical scrolling\n\t\tif (itemRect.bottom > containerRect.bottom - threshold) {\n\t\t\tscrollY = scrollSpeed;\n\t\t} else if (itemRect.top < containerRect.top + threshold) {\n\t\t\tscrollY = -scrollSpeed;\n\t\t}\n\n\t\tthis._autoScrollSpeed = { x: scrollX, y: scrollY };\n\n\t\tif ((scrollX !== 0 || scrollY !== 0) && !this._autoScrollInterval) {\n\t\t\tthis.startAutoScroll();\n\t\t} else if (scrollX === 0 && scrollY === 0 && this._autoScrollInterval) {\n\t\t\tthis.stopAutoScroll();\n\t\t}\n\t}\n\n\tcheckResizeExpansion(item: DashboardItem) {\n\t\tif (!this.container || !this.model) return;\n\n\t\tconst baseSize = this.baseSize;\n\t\tconst gap = this.model.options.gap;\n\n\t\t// Item edges in content coordinates - offsetTop is already content-relative\n\t\tconst itemBottom = item.offsetTop + item.offsetHeight;\n\t\tconst itemRight = item.offsetLeft + item.offsetWidth;\n\t\tconst currentContentHeight = this.content.offsetHeight;\n\t\tconst currentContentWidth = this.content.offsetWidth;\n\n\t\t// Threshold: expand when item is within 1 grid cell of the content edge\n\t\tconst thresholdY = baseSize.h + gap;\n\t\tconst thresholdX = baseSize.w + gap;\n\n\t\tlet newHeight = currentContentHeight;\n\t\tlet newWidth = currentContentWidth;\n\t\tlet needsUpdate = false;\n\n\t\tif (itemBottom > currentContentHeight - thresholdY) {\n\t\t\tnewHeight = currentContentHeight + 5 * (baseSize.h + gap);\n\t\t\tneedsUpdate = true;\n\t\t}\n\n\t\tif (itemRight > currentContentWidth - thresholdX) {\n\t\t\tnewWidth = currentContentWidth + 5 * (baseSize.w + gap);\n\t\t\tneedsUpdate = true;\n\t\t}\n\n\t\tif (needsUpdate) {\n\t\t\tdom.setSize(this.content, { w: newWidth, h: newHeight });\n\t\t\tthis.model.size.w = Math.max(this.model.size.w, Math.ceil((newWidth - gap) / (baseSize.w + gap)));\n\t\t\tthis.model.size.h = Math.max(this.model.size.h, Math.ceil((newHeight - gap) / (baseSize.h + gap)));\n\t\t\tthis.drawGrid();\n\t\t}\n\t}\n\n\tstartAutoScroll() {\n\t\tif (this._autoScrollInterval) return;\n\t\t\n\t\tthis._autoScrollInterval = window.setInterval(() => {\n\t\t\tif (!this.container) return;\n\n\t\t\tconst { x, y } = this._autoScrollSpeed;\n\n\t\t\t// Scroll vertically\n\t\t\tif (y !== 0 && this.container.verticalSlider) {\n\t\t\t\tconst currentScroll = this.container.verticalSlider.value;\n\t\t\t\tconst maxScroll = this.container.verticalSlider.maxValue;\n\t\t\t\t\n\t\t\t\t// Expand content area if scrolling down near the bottom\n\t\t\t\tif (y > 0 && currentScroll >= maxScroll * 0.85) {\n\t\t\t\t\tthis.expandContentArea();\n\t\t\t\t\t// After expanding, continue scrolling\n\t\t\t\t\tconst newMaxScroll = this.container.verticalSlider.maxValue;\n\t\t\t\t\tthis.container.scrollVerticalTo(Math.min(newMaxScroll, currentScroll + y));\n\t\t\t\t} else {\n\t\t\t\t\tconst newScroll = Math.max(0, Math.min(maxScroll, currentScroll + y));\n\t\t\t\t\tthis.container.scrollVerticalTo(newScroll);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Scroll horizontally\n\t\t\tif (x !== 0 && this.container.horizontalSlider) {\n\t\t\t\tconst currentScroll = this.container.horizontalSlider.value;\n\t\t\t\tconst maxScroll = this.container.horizontalSlider.maxValue;\n\t\t\t\t\n\t\t\t\t// Expand content area if scrolling right near the edge\n\t\t\t\tif (x > 0 && currentScroll >= maxScroll * 0.85) {\n\t\t\t\t\tthis.expandContentArea();\n\t\t\t\t\t// After expanding, continue scrolling\n\t\t\t\t\tconst newMaxScroll = this.container.horizontalSlider.maxValue;\n\t\t\t\t\tthis.container.scrollHorizontalTo(Math.min(newMaxScroll, currentScroll + x));\n\t\t\t\t} else {\n\t\t\t\t\tconst newScroll = Math.max(0, Math.min(maxScroll, currentScroll + x));\n\t\t\t\t\tthis.container.scrollHorizontalTo(newScroll);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// During resize, update item size with new scroll offset so placeholder follows smoothly\n\t\t\tif (this._isResizing && this._currentItem) {\n\t\t\t\tthis._currentItem.updateResize();\n\t\t\t}\n\t\t}, 16); // ~60fps\n\t}\n\n\tstopAutoScroll() {\n\t\tif (this._autoScrollInterval) {\n\t\t\twindow.clearInterval(this._autoScrollInterval);\n\t\t\tthis._autoScrollInterval = null;\n\t\t}\n\t\tthis._autoScrollSpeed = { x: 0, y: 0 };\n\t}\n\n\texpandContentArea() {\n\t\tif (!this.model || !this._currentItem) return;\n\n\t\t// Calculate how much space we need based on current item position\n\t\tconst topOffset = this.scrollOffset;\n\t\tconst itemBottom = this._currentItem.offsetTop + this._currentItem.offsetHeight + topOffset;\n\t\tconst itemRight = this._currentItem.offsetLeft + this._currentItem.offsetWidth;\n\n\t\tconst currentContentHeight = this.content.offsetHeight;\n\t\tconst currentContentWidth = this.content.offsetWidth;\n\n\t\t// Expand by 2 grid cells if needed\n\t\tconst expandRows = 2;\n\t\tconst expandCols = 2;\n\t\tconst baseSize = this.baseSize;\n\t\tconst gap = this.model.options.gap;\n\n\t\tlet newHeight = currentContentHeight;\n\t\tlet newWidth = currentContentWidth;\n\n\t\t// Check if we need more height - only expand, never shrink\n\t\tif (itemBottom > currentContentHeight - gap * 2) {\n\t\t\tnewHeight = Math.max(currentContentHeight, currentContentHeight + expandRows * (baseSize.h + gap));\n\t\t}\n\n\t\t// Check if we need more width - only expand, never shrink\n\t\tif (itemRight > currentContentWidth - gap * 2) {\n\t\t\tnewWidth = Math.max(currentContentWidth, currentContentWidth + expandCols * (baseSize.w + gap));\n\t\t}\n\n\t\t// Only update if size actually changed\n\t\tif (newHeight !== currentContentHeight || newWidth !== currentContentWidth) {\n\t\t\tdom.setSize(this.content, { w: newWidth, h: newHeight });\n\t\t\t\n\t\t\t// Update model size to match new content dimensions\n\t\t\tconst newModelWidth = Math.ceil((newWidth - gap) / (baseSize.w + gap));\n\t\t\tconst newModelHeight = Math.ceil((newHeight - gap) / (baseSize.h + gap));\n\t\t\t\n\t\t\t// Only update if model size increased\n\t\t\tthis.model.size.w = Math.max(this.model.size.w, newModelWidth);\n\t\t\tthis.model.size.h = Math.max(this.model.size.h, newModelHeight);\n\t\t\t\n\t\t\tthis.drawGrid();\n\t\t}\n\t}\n\n\t_onItemMove = (e: DashboardEvent) => {\n\t\tif (!e.item.moving) return;\n\t\tconst topOffset = this.scrollOffset;\n\t\tconst x = this.offsetToXCoord(e.item.offsetLeft);\n\t\tconst y = this.offsetToYCoord(e.item.offsetTop + topOffset);\n\t\tconst rect: Rect = {x, y, w: e.item.model.w, h: e.item.model.h};\n\t\tthis.showPlaceholder(rect);\n\t\tthis.previewLayout(rect);\n\t\tthis.checkAutoScroll(e.item);\n\t}\n\n\t_onItemResize = (e: DashboardEvent) => {\n\t\tif (!e.item.resizing) return;\n\t\tconst topOffset = this.scrollOffset;\n\t\tconst w = this.offsetToXCoord(e.item.offsetLeft + e.item.offsetWidth) - e.item.model.x + 1;\n\t\tconst h = this.offsetToYCoord(e.item.offsetTop + e.item.offsetHeight + topOffset) - e.item.model.y + 1;\n\t\tconst rect: Rect = {x: e.item.model.x, y: e.item.model.y, w, h};\n\t\tthis.showPlaceholder(rect);\n\t\tthis.previewLayout(rect);\n\t\tthis.checkAutoScroll(e.item);\n\t}\n\n\tconstructor() {\n\t\tsuper();\n\t\tthis.addEventListener('dashboard.movestart', (e: DashboardEvent) => this.startMove(e.item));\n\t\tthis.addEventListener('dashboard.resizestart', (e: DashboardEvent) => this.startResize(e.item));\n\t\tthis.addEventListener('dashboard.movestop', () => this.stopMove());\n\t\tthis.addEventListener('dashboard.resizestop', () => this.stopMove());\n\t\tthis.addEventListener('dashboard.move', this._onItemMove);\n\t\tthis.addEventListener('dashboard.resize', this._onItemResize);\n\t}\n\n\tcalculateItemLocation(item: Rect) : Rect {\n\t\tconst baseSize = this.baseSize;\n\t\tconst gap = this.model.options.gap;\n\t\treturn {\n\t\t\tx: item.x * (baseSize.w + gap) + gap,\n\t\t\ty: item.y * (baseSize.h + gap) + gap,\n\t\t\tw: item.w * (baseSize.w + gap) - gap,\n\t\t\th: item.h * (baseSize.h + gap) - gap,\n\t\t};\n\t}\n\n\tshowPlaceholder(rect: Rect) {\n\t\tdom.showElement(this.placeholder);\n\t\tthis.setItemPosition(this.placeholder, rect);\n\t}\n\n\thidePlaceholder() {\n\t\tdom.hideElement(this.placeholder);\n\t}\n\n\tsetSourceData(source: DashboardSource) {\n\t\tthis.components.clear();\n\t\tthis.model = new DashboardModel(source);\n\t\tthis.model.detectAndFixCollisions();\n\t}\n\n\tsetItemPosition(elm: HTMLElement, rect: Rect) {\n\t\tconst {x, y, w, h} = this.calculateItemLocation(rect);\n\t\tdom.setSize(elm, { w, h});\n\t\tdom.setPosition(elm, {l: x, t: y});\n\t}\n\n\tfixCollisions() {\n\t\tif (!this.model) return;\n\t\tthis.model.detectAndFixCollisions();\n\t\tthis.layout();\n\t}\n\n\tlayout() {\n\t\tthis._baseSize = null;\n\t\tif (!this.model) return;\n\t\tthis.items?.forEach((item: DashboardItem) => this.setItemPosition(item, item.model));\n\t\t\n\t\tdom.setSize(this.content, {\n\t\t\tw: this.model.size.w * (this.baseSize.w + this.model.options.gap) + this.model.options.gap,\n\t\t\th: this.model.size.h * (this.baseSize.h + this.model.options.gap) + this.model.options.gap\n\t\t});\n\n\t\tthis.items?.forEach((item: DashboardItem) => item.layout());\n\t\tthis.drawGrid();\n\t}\n\n\tasync drawGrid() {\n\t\tif (!this.gridCanvas) return;\n\t\tif (this.container.isUpdatePending) await this.container.updateComplete;\n\n\t\tconst ctx = this.gridCanvas.getContext('2d');\n\t\tif (!ctx) return;\n\n\t\tconst gap = this.model.options.gap;\n\t\tconst baseSize = this.baseSize;\n\t\t\n\t\tthis.gridCanvas.style.width = '100%';\n\t\tthis.gridCanvas.style.height = '100%';\n\t\tconst width = this.gridCanvas.offsetWidth;\n\t\tthis.gridCanvas.width = width;\n\t\tconst height = this.gridCanvas.offsetHeight;\n\t\tthis.gridCanvas.height = height;\n\t\tconst columns = width / baseSize.w;\n\t\tconst rows = height / baseSize.h;\n\n\n\t\tctx.clearRect(0, 0, width, height);\n\t\tctx.strokeStyle = 'rgba(116,116,116,0.2)';\n\t\tctx.lineWidth = 1;\n\n\t\tfor (let i = 0; i <= columns; i++) {\n\t\t\tconst x = Math.round(i * (baseSize.w + gap) + gap / 2) + 0.5;\n\t\t\tctx.beginPath();\n\t\t\tctx.moveTo(x, 0);\n\t\t\tctx.lineTo(x, height);\n\t\t\tctx.stroke();\n\t\t}\n\n\t\tfor (let i = 0; i <= rows; i++) {\n\t\t\tconst y = Math.round(i * (baseSize.h + gap) + gap / 2) + 0.5;\n\t\t\tctx.beginPath();\n\t\t\tctx.moveTo(0, y);\n\t\t\tctx.lineTo(width, y);\n\t\t\tctx.stroke();\n\t\t}\n\t}\n\n\tupdated() {\n\t\tthis.layout();\n\t}\n\t\n\trender = () => this.model ? html`\n\t\t<og-container>\n\t\t\t<div slot=\"content\">\n\t\t\t\t${this.designMode ? html`\n\t\t\t\t\t${this.noGrid ? '' : html`<canvas class=\"item-grid\"></canvas>`}\n\t\t\t\t\t<div class=\"item-placeholder\"></div>\n\t\t\t\t` : null}\n\t\t\t\t${map(this.model.items, item => html`\n\t\t\t\t\t<og-dashboard-item\n\t\t\t\t\t\t?designMode=\"${this.designMode}\"\n\t\t\t\t\t\t.model=\"${item}\" \n\t\t\t\t\t\t.components=\"${this.components}\">\n\t\t\t\t\t</og-dashboard-item>\n\t\t\t\t`)}\n\t\t\t</div>\n\t\t</og-container>\n\t` : '';\n\n}"]}
@@ -0,0 +1,2 @@
1
+ export declare const style: import("lit").CSSResult;
2
+ //# sourceMappingURL=dashboard.style.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dashboard.style.d.ts","sourceRoot":"","sources":["../../src/ui/dashboard.style.ts"],"names":[],"mappings":"AAEA,eAAO,MAAM,KAAK,yBAyDjB,CAAC"}
@@ -0,0 +1,60 @@
1
+ import { css } from 'lit';
2
+ export const style = css `
3
+ :host {
4
+ position: relative;
5
+ overflow: hidden;
6
+ }
7
+
8
+ og-container {
9
+ width: 100%;
10
+ height: 100%;
11
+ }
12
+
13
+ og-dashboard-item {
14
+ _border: 2px solid var(--og-accent-color);
15
+ z-index: 100;
16
+ transition: left 0.2s, top 0.2s;
17
+ }
18
+
19
+ og-dashboard-item.active {
20
+ transition: none;
21
+ }
22
+
23
+ :host([designMode]) og-dashboard-item {
24
+ cursor: move;
25
+ resize: both;
26
+ background-color: var(--og-accent-color);
27
+ color: var(--og-text-color-2);
28
+ }
29
+
30
+ :host([designMode].moving) og-dashboard-item {
31
+ opacity: 0.6;
32
+ }
33
+
34
+ :host([designMode]) og-dashboard-item.active {
35
+ border: none;
36
+ background-color: var(--og-accent-color);
37
+ resize: none;
38
+ }
39
+
40
+ :host([designMode].moving) og-dashboard-item.active {
41
+ opacity: 1;
42
+ }
43
+
44
+ .item-placeholder {
45
+ display: none;
46
+ border: 2px dotted var(--og-accent-color);
47
+ transition: left 0.2s, top 0.2s, width 0.2s, height 0.2s;
48
+ z-index: 99;
49
+ }
50
+
51
+ .item-grid {
52
+ z-index: 98;
53
+ position: absolute;
54
+ top: 0;
55
+ left: 0;
56
+ width: 100%;
57
+ height: 100%;
58
+ }
59
+ `;
60
+ //# sourceMappingURL=dashboard.style.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dashboard.style.js","sourceRoot":"","sources":["../../src/ui/dashboard.style.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,GAAG,EAAE,MAAM,KAAK,CAAC;AAE1B,MAAM,CAAC,MAAM,KAAK,GAAG,GAAG,CAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAyDvB,CAAC","sourcesContent":["import { css } from 'lit';\n\nexport const style = css`\n\t:host {\n\t\tposition: relative;\n\t\toverflow: hidden;\n\t}\n\n\tog-container {\n\t\twidth: 100%;\n\t\theight: 100%;\n\t}\n\n\tog-dashboard-item {\n\t\t_border: 2px solid var(--og-accent-color);\n\t\tz-index: 100;\n\t\ttransition: left 0.2s, top 0.2s;\n\t}\n\n\tog-dashboard-item.active {\n\t\ttransition: none;\n\t}\n\n\t:host([designMode]) og-dashboard-item {\n\t\tcursor: move;\n\t\tresize: both;\n\t\tbackground-color: var(--og-accent-color);\n\t\tcolor: var(--og-text-color-2);\n\t}\n\t\n\t:host([designMode].moving) og-dashboard-item {\n\t\topacity: 0.6;\n\t}\n\n\t:host([designMode]) og-dashboard-item.active {\n\t\tborder: none;\n\t\tbackground-color: var(--og-accent-color);\n\t\tresize: none;\n\t}\n\n\t:host([designMode].moving) og-dashboard-item.active {\n\t\topacity: 1;\n\t}\n\t\n\t.item-placeholder {\n\t\tdisplay: none;\n\t\tborder: 2px dotted var(--og-accent-color);\n\t\ttransition: left 0.2s, top 0.2s, width 0.2s, height 0.2s;\n\t\tz-index: 99;\n\t}\n\n\t.item-grid {\n\t\tz-index: 98;\n\t\tposition: absolute;\n\t\ttop: 0;\n\t\tleft: 0;\n\t\twidth: 100%;\n\t\theight: 100%;\n\t}\n`;"]}
@@ -0,0 +1,44 @@
1
+ import { ComponentStore, Layout, OmegaComponent, Overlay } from "@omegagrid/core";
2
+ import { DashboardItemModel } from "../model";
3
+ export declare class DashboardItem extends OmegaComponent implements Layout {
4
+ static styles: import("lit").CSSResultGroup[];
5
+ components: ComponentStore<HTMLElement & Layout>;
6
+ model: DashboardItemModel;
7
+ designMode: boolean;
8
+ container: HTMLDivElement;
9
+ overlay: Overlay;
10
+ private _parent;
11
+ private _mouseOffset;
12
+ private _movingOffset;
13
+ private _resizing;
14
+ private _elementOffset;
15
+ private _resizeObserver;
16
+ private _initialSize;
17
+ private _initialScrollOffset;
18
+ private _lastMouseEvent;
19
+ get mouseOffset(): {
20
+ top: number;
21
+ left: number;
22
+ };
23
+ get moving(): boolean;
24
+ get resizing(): boolean;
25
+ get component(): Promise<HTMLElement & Layout>;
26
+ constructor();
27
+ connectedCallback(): void;
28
+ disconnectedCallback(): void;
29
+ clearEvents(): void;
30
+ _onMouseUp: () => void;
31
+ _onMouseDown: (e: MouseEvent) => void;
32
+ _onMouseMove: (e: MouseEvent) => void;
33
+ _onMouseResize: (e: MouseEvent) => void;
34
+ /** Re-trigger resize calculation with current scroll offset (called from autoscroll interval) */
35
+ updateResize(): void;
36
+ private _applyResize;
37
+ _onResize: () => void;
38
+ layout(): Promise<void>;
39
+ showOverlay(text?: string, loader?: boolean): void;
40
+ hideOverlay(): void;
41
+ updated(): Promise<void>;
42
+ render: () => import("lit-html").TemplateResult<1>;
43
+ }
44
+ //# sourceMappingURL=dashboardItem.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dashboardItem.d.ts","sourceRoot":"","sources":["../../src/ui/dashboardItem.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAO,MAAM,EAAE,cAAc,EAAE,OAAO,EAAE,MAAM,iBAAiB,CAAC;AAGvF,OAAO,EAAE,kBAAkB,EAAE,MAAM,UAAU,CAAC;AAG9C,qBACa,aAAc,SAAQ,cAAe,YAAW,MAAM;IAElE,MAAM,CAAC,MAAM,iCAgBV;IAGH,UAAU,EAAE,cAAc,CAAC,WAAW,GAAG,MAAM,CAAC,CAAC;IAGjD,KAAK,EAAE,kBAAkB,CAAC;IAG1B,UAAU,UAAS;IAGnB,SAAS,EAAE,cAAc,CAAC;IAG1B,OAAO,EAAE,OAAO,CAAC;IAEjB,OAAO,CAAC,OAAO,CAAY;IAC3B,OAAO,CAAC,YAAY,CAAqC;IACzD,OAAO,CAAC,aAAa,CAAqC;IAC1D,OAAO,CAAC,SAAS,CAAS;IAC1B,OAAO,CAAC,cAAc,CAAqC;IAC3D,OAAO,CAAC,eAAe,CAAiB;IACxC,OAAO,CAAC,YAAY,CAAyC;IAC7D,OAAO,CAAC,oBAAoB,CAAK;IACjC,OAAO,CAAC,eAAe,CAAoB;IAE3C,IAAI,WAAW;aATa,MAAM;cAAQ,MAAM;MASF;IAC9C,IAAI,MAAM,YAAyC;IACnD,IAAI,QAAQ,YAA4B;IAGxC,IAAI,SAAS,kCAIZ;;IAcD,iBAAiB;IAMjB,oBAAoB;IAMpB,WAAW;IAMX,UAAU,aAYR;IAEF,YAAY,GAAI,GAAG,UAAU,UAoB3B;IAEF,YAAY,GAAI,GAAG,UAAU,UAO3B;IAEF,cAAc,GAAI,GAAG,UAAU,UAG7B;IAEF,iGAAiG;IACjG,YAAY;IAMZ,OAAO,CAAC,YAAY;IAYpB,SAAS,aAEP;IAEI,MAAM;IAKZ,WAAW,CAAC,IAAI,GAAE,MAAa,EAAE,MAAM,GAAE,OAAe;IASxD,WAAW;IAKL,OAAO;IAgBb,MAAM,6CAGJ;CAEF"}