|
1 | 1 | import { LitElement, html } from 'lit'; |
2 | 2 | import { property, query } from 'lit/decorators.js'; |
3 | | -import { styleMap } from 'lit/directives/style-map.js'; |
| 3 | +import { type StyleInfo, styleMap } from 'lit/directives/style-map.js'; |
4 | 4 | import { themes } from '../../theming/theming-decorator.js'; |
5 | 5 | import { |
6 | 6 | type MutationControllerParams, |
|
9 | 9 | import { registerComponent } from '../common/definitions/register.js'; |
10 | 10 | import type { Constructor } from '../common/mixins/constructor.js'; |
11 | 11 | import { EventEmitterMixin } from '../common/mixins/event-emitter.js'; |
| 12 | +import { asNumber } from '../common/util.js'; |
12 | 13 | import { addFullscreenController } from './controllers/fullscreen.js'; |
| 14 | +import { createSerializer } from './serializer.js'; |
13 | 15 | import { all } from './themes/container.js'; |
14 | 16 | import { styles as shared } from './themes/shared/tile-manager.common.css.js'; |
15 | 17 | import { styles } from './themes/tile-manager.base.css.js'; |
@@ -45,8 +47,13 @@ export default class IgcTileManagerComponent extends EventEmitterMixin< |
45 | 47 | registerComponent(IgcTileManagerComponent, IgcTileComponent); |
46 | 48 | } |
47 | 49 |
|
| 50 | + private _internalStyles: StyleInfo = {}; |
| 51 | + |
48 | 52 | private positionedTiles: IgcTileComponent[] = []; |
49 | | - private _columnCount = 10; |
| 53 | + private _columnCount = 0; |
| 54 | + private _minColWidth?: string; |
| 55 | + private _minRowHeight?: string; |
| 56 | + private _serializer = createSerializer(this); |
50 | 57 |
|
51 | 58 | /** @private @hidden @internal */ |
52 | 59 | public draggedItem: IgcTileComponent | null = null; |
@@ -106,35 +113,61 @@ export default class IgcTileManagerComponent extends EventEmitterMixin< |
106 | 113 |
|
107 | 114 | /** |
108 | 115 | * Determines whether the tiles slide or swap on drop. |
109 | | - * @attr |
| 116 | + * @attr drag-mode |
110 | 117 | */ |
111 | | - @property() |
| 118 | + @property({ attribute: 'drag-mode' }) |
112 | 119 | public dragMode: 'slide' | 'swap' = 'slide'; |
113 | 120 |
|
114 | | - @property({ type: Number }) |
| 121 | + /** |
| 122 | + * Sets the number of columns for the tile manager. |
| 123 | + * Setting value <= than zero will trigger a responsive layout. |
| 124 | + * |
| 125 | + * @attr column-count |
| 126 | + * @default 0 |
| 127 | + */ |
| 128 | + @property({ type: Number, attribute: 'column-count' }) |
115 | 129 | public set columnCount(value: number) { |
116 | | - const oldValue = this._columnCount; |
117 | | - |
118 | | - if (value <= 0 || value === undefined) { |
119 | | - this._columnCount = 10; |
120 | | - } else { |
121 | | - this._columnCount = value; |
122 | | - } |
123 | | - |
124 | | - if (oldValue !== this._columnCount) { |
125 | | - this.requestUpdate('columnCount', oldValue); |
126 | | - } |
| 130 | + this._columnCount = Math.max(0, asNumber(value)); |
| 131 | + Object.assign(this._internalStyles, { |
| 132 | + '--ig-column-count': this._columnCount || undefined, |
| 133 | + }); |
127 | 134 | } |
128 | 135 |
|
129 | 136 | public get columnCount(): number { |
130 | 137 | return this._columnCount; |
131 | 138 | } |
132 | 139 |
|
133 | | - @property({ type: Number }) |
134 | | - public minColumnWidth = 200; |
| 140 | + /** |
| 141 | + * Sets the minimum width for a column unit in the tile manager. |
| 142 | + * @attr min-column-width |
| 143 | + */ |
| 144 | + @property({ attribute: 'min-column-width' }) |
| 145 | + public set minColumnWidth(value: string | undefined) { |
| 146 | + this._minColWidth = value ?? undefined; |
| 147 | + Object.assign(this._internalStyles, { |
| 148 | + '--ig-min-col-width': this._minColWidth, |
| 149 | + }); |
| 150 | + } |
| 151 | + |
| 152 | + public get minColumnWidth(): string | undefined { |
| 153 | + return this._minColWidth; |
| 154 | + } |
135 | 155 |
|
136 | | - @property({ type: Number }) |
137 | | - public minRowHeight = 40; |
| 156 | + /** |
| 157 | + * Sets the minimum height for a row unit in the tile manager. |
| 158 | + * @attr min-row-height |
| 159 | + */ |
| 160 | + @property({ attribute: 'min-row-height' }) |
| 161 | + public set minRowHeight(value: string | undefined) { |
| 162 | + this._minRowHeight = value ?? undefined; |
| 163 | + Object.assign(this._internalStyles, { |
| 164 | + '--ig-min-row-height': this._minRowHeight, |
| 165 | + }); |
| 166 | + } |
| 167 | + |
| 168 | + public get minRowHeight(): string | undefined { |
| 169 | + return this._minRowHeight; |
| 170 | + } |
138 | 171 |
|
139 | 172 | /** |
140 | 173 | * Gets the tiles sorted by their position in the layout. |
@@ -226,65 +259,18 @@ export default class IgcTileManagerComponent extends EventEmitterMixin< |
226 | 259 | } |
227 | 260 | } |
228 | 261 |
|
229 | | - public saveLayout() { |
230 | | - // TODO: serialize fullscreen when added |
231 | | - const tilesData = this.tiles.map((tile) => { |
232 | | - const tileStyles = window.getComputedStyle(tile); |
233 | | - |
234 | | - return { |
235 | | - colSpan: tile.colSpan, |
236 | | - colStart: tile.colStart, |
237 | | - disableDrag: tile.disableDrag, |
238 | | - disableResize: tile.disableResize, |
239 | | - // TODO: Review. We are saving gridColumn and gridRow as they keep the size of the resized tiles. |
240 | | - gridColumn: tileStyles.gridColumn, |
241 | | - gridRow: tileStyles.gridRow, |
242 | | - maximized: tile.maximized, |
243 | | - position: tile.position, |
244 | | - rowSpan: tile.rowSpan, |
245 | | - rowStart: tile.rowStart, |
246 | | - tileId: tile.tileId, |
247 | | - }; |
248 | | - }); |
249 | | - |
250 | | - return JSON.stringify(tilesData); |
| 262 | + public saveLayout(): string { |
| 263 | + return this._serializer.saveAsJSON(); |
251 | 264 | } |
252 | 265 |
|
253 | | - public loadLayout(data: string) { |
254 | | - const tilesData = JSON.parse(data); |
255 | | - |
256 | | - tilesData.forEach((tileInfo: any) => { |
257 | | - const existingTile = this._tiles.find( |
258 | | - (tile) => tile.tileId === tileInfo.tileId |
259 | | - ); |
260 | | - |
261 | | - if (existingTile) { |
262 | | - existingTile.colSpan = tileInfo.colSpan; |
263 | | - existingTile.colStart = tileInfo.colStart; |
264 | | - existingTile.disableDrag = tileInfo.disableDrag; |
265 | | - existingTile.disableResize = tileInfo.disableResize; |
266 | | - existingTile.maximized = tileInfo.maximized; |
267 | | - existingTile.position = tileInfo.position; |
268 | | - existingTile.rowSpan = tileInfo.rowSpan; |
269 | | - existingTile.rowStart = tileInfo.rowStart; |
270 | | - |
271 | | - // TODO: Review. We are saving gridColumn and gridRow as they keep the size of the resized tiles. |
272 | | - existingTile.style.gridColumn = tileInfo.gridColumn; |
273 | | - existingTile.style.gridRow = tileInfo.gridRow; |
274 | | - } |
275 | | - }); |
| 266 | + public loadLayout(data: string): void { |
| 267 | + this._serializer.loadFromJSON(data); |
276 | 268 | } |
277 | 269 |
|
278 | 270 | protected override render() { |
279 | | - const styles = { |
280 | | - '--ig-column-count': `${this.columnCount}`, |
281 | | - '--ig-min-col-width': `${this.minColumnWidth}px`, |
282 | | - '--ig-min-row-height': `${this.minRowHeight}px`, |
283 | | - }; |
284 | | - |
285 | 271 | return html` |
286 | 272 | <div |
287 | | - style=${styleMap(styles)} |
| 273 | + style=${styleMap(this._internalStyles)} |
288 | 274 | part="base" |
289 | 275 | @tileDragStart=${this.handleTileDragStart} |
290 | 276 | @tileDragEnd=${this.handleTileDragEnd} |
|
0 commit comments