@dragonworks/ngx-dashboard 20.0.6 → 20.1.0

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 (78) hide show
  1. package/fesm2022/dragonworks-ngx-dashboard.mjs +2250 -0
  2. package/fesm2022/dragonworks-ngx-dashboard.mjs.map +1 -0
  3. package/index.d.ts +727 -0
  4. package/package.json +45 -34
  5. package/ng-package.json +0 -7
  6. package/src/lib/__tests__/dashboard-component-widget-state-integration.spec.ts +0 -537
  7. package/src/lib/cell/__tests__/cell-resize.component.spec.ts +0 -442
  8. package/src/lib/cell/__tests__/cell.component.spec.ts +0 -541
  9. package/src/lib/cell/cell-context-menu.component.ts +0 -138
  10. package/src/lib/cell/cell-context-menu.service.ts +0 -36
  11. package/src/lib/cell/cell.component.html +0 -37
  12. package/src/lib/cell/cell.component.scss +0 -198
  13. package/src/lib/cell/cell.component.ts +0 -375
  14. package/src/lib/dashboard/dashboard.component.html +0 -18
  15. package/src/lib/dashboard/dashboard.component.scss +0 -17
  16. package/src/lib/dashboard/dashboard.component.ts +0 -187
  17. package/src/lib/dashboard-editor/dashboard-editor.component.html +0 -57
  18. package/src/lib/dashboard-editor/dashboard-editor.component.scss +0 -87
  19. package/src/lib/dashboard-editor/dashboard-editor.component.ts +0 -219
  20. package/src/lib/dashboard-viewer/__tests__/dashboard-viewer.component.spec.ts +0 -258
  21. package/src/lib/dashboard-viewer/dashboard-viewer.component.html +0 -20
  22. package/src/lib/dashboard-viewer/dashboard-viewer.component.scss +0 -50
  23. package/src/lib/dashboard-viewer/dashboard-viewer.component.ts +0 -70
  24. package/src/lib/drop-zone/__tests__/drop-zone.component.spec.ts +0 -465
  25. package/src/lib/drop-zone/drop-zone.component.html +0 -20
  26. package/src/lib/drop-zone/drop-zone.component.scss +0 -67
  27. package/src/lib/drop-zone/drop-zone.component.ts +0 -122
  28. package/src/lib/internal-widgets/unknown-widget/unknown-widget.component.ts +0 -72
  29. package/src/lib/models/cell-data.ts +0 -13
  30. package/src/lib/models/cell-dialog.ts +0 -7
  31. package/src/lib/models/cell-id.ts +0 -85
  32. package/src/lib/models/cell-position.ts +0 -15
  33. package/src/lib/models/dashboard-data.dto.ts +0 -44
  34. package/src/lib/models/dashboard-data.utils.ts +0 -49
  35. package/src/lib/models/drag-data.ts +0 -6
  36. package/src/lib/models/index.ts +0 -11
  37. package/src/lib/models/reserved-space.ts +0 -24
  38. package/src/lib/models/widget-factory.ts +0 -33
  39. package/src/lib/models/widget-id.ts +0 -70
  40. package/src/lib/models/widget.ts +0 -21
  41. package/src/lib/providers/cell-settings-dialog/cell-settings-dialog.component.ts +0 -127
  42. package/src/lib/providers/cell-settings-dialog/cell-settings-dialog.provider.ts +0 -15
  43. package/src/lib/providers/cell-settings-dialog/cell-settings-dialog.tokens.ts +0 -20
  44. package/src/lib/providers/cell-settings-dialog/default-cell-settings-dialog.provider.ts +0 -32
  45. package/src/lib/providers/cell-settings-dialog/index.ts +0 -3
  46. package/src/lib/providers/index.ts +0 -1
  47. package/src/lib/services/__tests__/dashboard-bridge.service.spec.ts +0 -220
  48. package/src/lib/services/__tests__/dashboard-viewport.service.spec.ts +0 -362
  49. package/src/lib/services/dashboard-bridge.service.ts +0 -155
  50. package/src/lib/services/dashboard-viewport.service.ts +0 -148
  51. package/src/lib/services/dashboard.service.ts +0 -62
  52. package/src/lib/store/__tests__/dashboard-store-collision-detection.spec.ts +0 -756
  53. package/src/lib/store/__tests__/dashboard-store-computed-properties.spec.ts +0 -974
  54. package/src/lib/store/__tests__/dashboard-store-drag-drop.spec.ts +0 -279
  55. package/src/lib/store/__tests__/dashboard-store-export-import.spec.ts +0 -780
  56. package/src/lib/store/__tests__/dashboard-store-grid-config.spec.ts +0 -128
  57. package/src/lib/store/__tests__/dashboard-store-query-methods.spec.ts +0 -229
  58. package/src/lib/store/__tests__/dashboard-store-resize-operations.spec.ts +0 -652
  59. package/src/lib/store/__tests__/dashboard-store-widget-management.spec.ts +0 -461
  60. package/src/lib/store/__tests__/dashboard-store-widget-state-preservation.spec.ts +0 -369
  61. package/src/lib/store/dashboard-store.ts +0 -239
  62. package/src/lib/store/features/drag-drop.feature.ts +0 -140
  63. package/src/lib/store/features/grid-config.feature.ts +0 -43
  64. package/src/lib/store/features/resize.feature.ts +0 -140
  65. package/src/lib/store/features/utils/collision.utils.ts +0 -89
  66. package/src/lib/store/features/utils/grid-query-internal.utils.ts +0 -37
  67. package/src/lib/store/features/utils/resize.utils.ts +0 -165
  68. package/src/lib/store/features/widget-management.feature.ts +0 -158
  69. package/src/lib/styles/_dashboard-grid-vars.scss +0 -11
  70. package/src/lib/widget-list/__tests__/widget-list-bridge-integration.spec.ts +0 -137
  71. package/src/lib/widget-list/widget-list.component.html +0 -22
  72. package/src/lib/widget-list/widget-list.component.scss +0 -154
  73. package/src/lib/widget-list/widget-list.component.ts +0 -106
  74. package/src/public-api.ts +0 -21
  75. package/src/test-setup.ts +0 -10
  76. package/tsconfig.lib.json +0 -15
  77. package/tsconfig.lib.prod.json +0 -11
  78. package/tsconfig.spec.json +0 -14
@@ -1,72 +0,0 @@
1
- import {
2
- Component,
3
- ChangeDetectionStrategy,
4
- signal,
5
- computed,
6
- } from '@angular/core';
7
- import { MatIconModule } from '@angular/material/icon';
8
- import { MatTooltipModule } from '@angular/material/tooltip';
9
- import { Widget, WidgetMetadata } from '../../models';
10
-
11
- export interface UnknownWidgetState {
12
- originalWidgetTypeid: string;
13
- }
14
-
15
- @Component({
16
- selector: 'lib-unknown-widget',
17
- imports: [MatIconModule, MatTooltipModule],
18
- template: `
19
- <div class="unknown-widget-container" [matTooltip]="tooltipText()">
20
- <mat-icon class="unknown-widget-icon">error_outline</mat-icon>
21
- </div>
22
- `,
23
- styles: [
24
- `
25
- .unknown-widget-container {
26
- display: flex;
27
- align-items: center;
28
- justify-content: center;
29
- width: 100%;
30
- height: 100%;
31
- background-color: var(--mat-sys-error);
32
- border-radius: 8px;
33
- container-type: size;
34
- }
35
-
36
- .unknown-widget-icon {
37
- color: var(--mat-sys-on-error);
38
- font-size: clamp(12px, 75cqmin, 68px);
39
- width: clamp(12px, 75cqmin, 68px);
40
- height: clamp(12px, 75cqmin, 68px);
41
- }
42
- `,
43
- ],
44
- changeDetection: ChangeDetectionStrategy.OnPush,
45
- })
46
- export class UnknownWidgetComponent implements Widget {
47
- static metadata: WidgetMetadata = {
48
- widgetTypeid: '__internal/unknown-widget',
49
- name: 'Unknown Widget',
50
- description: 'Fallback widget for unknown widget types',
51
- svgIcon:
52
- '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 -960 960 960" fill="currentColor"><path d="M480-280q17 0 28.5-11.5T520-320q0-17-11.5-28.5T480-360q-17 0-28.5 11.5T440-320q0 17 11.5 28.5T480-280Zm-40-160h80v-240h-80v240Zm40 360q-83 0-156-31.5T197-197q-54-54-85.5-127T80-480q0-83 31.5-156T197-763q54-54 127-85.5T480-880q83 0 156 31.5T763-763q54 54 85.5 127T880-480q0 83-31.5 156T763-197q-54 54-127 85.5T480-80Z"/></svg>',
53
- };
54
-
55
- readonly state = signal<UnknownWidgetState>({
56
- originalWidgetTypeid: 'unknown',
57
- });
58
-
59
- readonly tooltipText = computed(() => `${this.state().originalWidgetTypeid}`);
60
-
61
- dashboardSetState(state?: unknown): void {
62
- if (state && typeof state === 'object' && 'originalWidgetTypeid' in state) {
63
- this.state.set(state as UnknownWidgetState);
64
- }
65
- }
66
-
67
- dashboardGetState(): UnknownWidgetState {
68
- return this.state();
69
- }
70
-
71
- // No edit dialog for error widgets - method intentionally not implemented
72
- }
@@ -1,13 +0,0 @@
1
- // cell-data.ts
2
- import { WidgetFactory } from './widget-factory';
3
- import { CellId } from './cell-id';
4
- import { WidgetId } from './widget-id';
5
- import { CellPosition } from './cell-position';
6
-
7
- export interface CellData extends CellPosition {
8
- widgetId: WidgetId; // Unique identifier for the widget instance
9
- cellId: CellId; // Current grid position (updates when widget moves)
10
- flat?: boolean;
11
- widgetFactory: WidgetFactory;
12
- widgetState: unknown;
13
- }
@@ -1,7 +0,0 @@
1
- /**
2
- * Data structure for cell display settings
3
- */
4
- export interface CellDisplayData {
5
- id: string;
6
- flat: boolean | undefined;
7
- }
@@ -1,85 +0,0 @@
1
- /**
2
- * Branded type for cell identifiers to ensure type safety when working with grid coordinates.
3
- * This prevents accidentally mixing up row/column numbers with cell IDs.
4
- */
5
- export type CellId = number & { __brand: 'CellId' };
6
-
7
- /**
8
- * Maximum number of columns supported by the grid.
9
- * This determines the encoding scheme for cell coordinates.
10
- */
11
- const MAX_COLUMNS = 1024;
12
-
13
- /**
14
- * Utility functions for working with CellId branded type.
15
- */
16
- export const CellIdUtils = {
17
- /**
18
- * Creates a CellId from row and column coordinates.
19
- * @param row - The row number (1-based)
20
- * @param col - The column number (1-based)
21
- * @returns A branded CellId that encodes both coordinates
22
- * @throws Error if row or col is less than 1, or if col exceeds MAX_COLUMNS
23
- */
24
- create(row: number, col: number): CellId {
25
- if (row < 1 || col < 1) {
26
- throw new Error(
27
- `Invalid cell coordinates: row=${row}, col=${col}. Both must be >= 1`,
28
- );
29
- }
30
- if (col >= MAX_COLUMNS) {
31
- throw new Error(`Column ${col} exceeds maximum of ${MAX_COLUMNS - 1}`);
32
- }
33
- return (row * MAX_COLUMNS + col) as CellId;
34
- },
35
-
36
- /**
37
- * Decodes a CellId back into row and column coordinates.
38
- * @param cellId - The CellId to decode
39
- * @returns A tuple of [row, col] coordinates (1-based)
40
- */
41
- decode(cellId: CellId): [number, number] {
42
- const id = cellId as number;
43
- const row = Math.floor(id / MAX_COLUMNS);
44
- const col = id % MAX_COLUMNS;
45
- return [row, col];
46
- },
47
-
48
- /**
49
- * Gets the row coordinate from a CellId.
50
- * @param cellId - The CellId to extract row from
51
- * @returns The row number (1-based)
52
- */
53
- getRow(cellId: CellId): number {
54
- return Math.floor((cellId as number) / MAX_COLUMNS);
55
- },
56
-
57
- /**
58
- * Gets the column coordinate from a CellId.
59
- * @param cellId - The CellId to extract column from
60
- * @returns The column number (1-based)
61
- */
62
- getCol(cellId: CellId): number {
63
- return (cellId as number) % MAX_COLUMNS;
64
- },
65
-
66
- /**
67
- * Creates a string representation of a CellId for debugging/display purposes.
68
- * @param cellId - The CellId to convert to string
69
- * @returns A string in the format "row-col"
70
- */
71
- toString(cellId: CellId): string {
72
- const [row, col] = this.decode(cellId);
73
- return `${row}-${col}`;
74
- },
75
-
76
- /**
77
- * Checks if two CellIds are equal.
78
- * @param a - First CellId
79
- * @param b - Second CellId
80
- * @returns True if the CellIds represent the same cell
81
- */
82
- equals(a: CellId, b: CellId): boolean {
83
- return a === b;
84
- },
85
- };
@@ -1,15 +0,0 @@
1
- // cell-position.ts
2
- import { CellId } from './cell-id';
3
- import { WidgetId } from './widget-id';
4
-
5
- export interface CellPosition {
6
- row: number;
7
- col: number;
8
- rowSpan: number;
9
- colSpan: number;
10
- }
11
-
12
- export interface CellComponentPosition extends CellPosition {
13
- cellId: CellId; // Current position
14
- widgetId: WidgetId; // Widget instance identifier
15
- }
@@ -1,44 +0,0 @@
1
- // dashboard-data.dto.ts
2
- /**
3
- * Serializable data format for dashboard export/import functionality.
4
- * This format can be safely converted to/from JSON for persistence.
5
- * Corresponds to the persistent state from the dashboard store features.
6
- */
7
- export interface DashboardDataDto {
8
- /** Version for future compatibility and migration support */
9
- version: string;
10
-
11
- /** Unique dashboard identifier managed by the client */
12
- dashboardId: string;
13
-
14
- /** Grid dimensions */
15
- rows: number;
16
- columns: number;
17
- gutterSize: string;
18
-
19
- /** Array of serializable cell data */
20
- cells: CellDataDto[];
21
- }
22
-
23
- /**
24
- * Serializable version of CellData that can be safely JSON stringified.
25
- * Converts non-serializable types (CellId, WidgetFactory) to serializable equivalents.
26
- */
27
- export interface CellDataDto {
28
- /** Grid position */
29
- row: number;
30
- col: number;
31
-
32
- /** Cell span */
33
- rowSpan: number;
34
- colSpan: number;
35
-
36
- /** Display settings */
37
- flat?: boolean;
38
-
39
- /** Widget type identifier for factory lookup during import */
40
- widgetTypeid: string;
41
-
42
- /** Raw widget state (must be JSON serializable) */
43
- widgetState: unknown;
44
- }
@@ -1,49 +0,0 @@
1
- import { DashboardDataDto } from './dashboard-data.dto';
2
-
3
- /**
4
- * Creates an empty dashboard configuration with the specified dimensions.
5
- * This is a convenience function for creating a basic dashboard without any cells.
6
- *
7
- * @param dashboardId - Unique identifier for the dashboard (managed by client)
8
- * @param rows - Number of rows in the dashboard grid
9
- * @param columns - Number of columns in the dashboard grid
10
- * @param gutterSize - CSS size for the gutter between cells (default: '0.5em')
11
- * @returns A DashboardDataDto configured with the specified dimensions and no cells
12
- *
13
- * @example
14
- * // Create an 8x16 dashboard with default gutter
15
- * const dashboard = createEmptyDashboard('my-dashboard-1', 8, 16);
16
- *
17
- * @example
18
- * // Create a 5x10 dashboard with custom gutter
19
- * const dashboard = createEmptyDashboard('my-dashboard-2', 5, 10, '0.5rem');
20
- */
21
- export function createEmptyDashboard(
22
- dashboardId: string,
23
- rows: number,
24
- columns: number,
25
- gutterSize = '0.5em'
26
- ): DashboardDataDto {
27
- return {
28
- version: '1.0.0',
29
- dashboardId,
30
- rows,
31
- columns,
32
- gutterSize,
33
- cells: [],
34
- };
35
- }
36
-
37
- /**
38
- * Creates a default dashboard configuration with standard dimensions.
39
- * This provides a reasonable starting point for most use cases.
40
- *
41
- * @param dashboardId - Unique identifier for the dashboard (managed by client)
42
- * @returns A DashboardDataDto with 8 rows, 16 columns, and 0.5em gutter
43
- *
44
- * @example
45
- * const dashboard = createDefaultDashboard('my-dashboard-id');
46
- */
47
- export function createDefaultDashboard(dashboardId: string): DashboardDataDto {
48
- return createEmptyDashboard(dashboardId, 8, 16, '0.5em');
49
- }
@@ -1,6 +0,0 @@
1
- import { CellComponentPosition } from './cell-position';
2
- import { WidgetMetadata } from './widget';
3
-
4
- export type DragData =
5
- | { kind: 'cell'; content: CellComponentPosition }
6
- | { kind: 'widget'; content: WidgetMetadata };
@@ -1,11 +0,0 @@
1
- export * from './cell-id';
2
- export * from './widget-id';
3
- export * from './cell-data';
4
- export * from './cell-position';
5
- export * from './cell-dialog';
6
- export * from './dashboard-data.dto';
7
- export * from './dashboard-data.utils';
8
- export * from './drag-data';
9
- export * from './reserved-space';
10
- export * from './widget';
11
- export * from './widget-factory';
@@ -1,24 +0,0 @@
1
- /**
2
- * Defines space that should be reserved around the dashboard component
3
- * when calculating viewport constraints.
4
- */
5
- export interface ReservedSpace {
6
- /** Space reserved at the top (e.g., toolbar height) */
7
- top: number;
8
- /** Space reserved on the right (e.g., padding, widget list) */
9
- right: number;
10
- /** Space reserved at the bottom (e.g., padding) */
11
- bottom: number;
12
- /** Space reserved on the left (e.g., padding) */
13
- left: number;
14
- }
15
-
16
- /**
17
- * Default reserved space when none is specified
18
- */
19
- export const DEFAULT_RESERVED_SPACE: ReservedSpace = {
20
- top: 0,
21
- right: 0,
22
- bottom: 0,
23
- left: 0
24
- };
@@ -1,33 +0,0 @@
1
- // widget-factory.ts
2
- import { ComponentRef, ViewContainerRef } from '@angular/core';
3
- import {
4
- Widget,
5
- WidgetComponentClass,
6
- } from './widget';
7
-
8
- export interface WidgetFactory<
9
- T extends Widget = Widget
10
- > {
11
- widgetTypeid: string; // application wide unique ID
12
- name: string;
13
- description: string;
14
- svgIcon: string; // SVG markup as string
15
- createInstance(container: ViewContainerRef, state?: unknown): ComponentRef<T>;
16
- }
17
-
18
- export function createFactoryFromComponent<T extends Widget>(
19
- component: WidgetComponentClass<T>
20
- ): WidgetFactory {
21
- return {
22
- ...component.metadata,
23
-
24
- createInstance(
25
- container: ViewContainerRef,
26
- state?: unknown
27
- ): ComponentRef<T> {
28
- const ref = container.createComponent(component);
29
- ref.instance.dashboardSetState?.(state);
30
- return ref;
31
- },
32
- };
33
- }
@@ -1,70 +0,0 @@
1
- /**
2
- * Branded type for widget identifiers to ensure type safety when working with widget instances.
3
- * This prevents accidentally mixing up widget IDs with other string values.
4
- */
5
- export type WidgetId = string & { __brand: 'WidgetId' };
6
-
7
- /**
8
- * Utility functions for working with WidgetId branded type.
9
- * WidgetIds are UUIDs that uniquely identify widget instances throughout their lifecycle,
10
- * independent of their position on the dashboard grid.
11
- */
12
- export const WidgetIdUtils = {
13
- /**
14
- * Generates a new unique WidgetId.
15
- * Uses crypto.randomUUID() when available, falls back to timestamp-based ID for older browsers.
16
- * @returns A new unique WidgetId
17
- */
18
- generate(): WidgetId {
19
- if (typeof crypto !== 'undefined' && crypto.randomUUID) {
20
- return crypto.randomUUID() as WidgetId;
21
- }
22
- // Fallback for older browsers
23
- return `widget-${Date.now()}-${Math.random().toString(36).substr(2, 9)}` as WidgetId;
24
- },
25
-
26
- /**
27
- * Validates if a string is a valid WidgetId format.
28
- * @param id - The string to validate
29
- * @returns True if the string is a valid WidgetId format
30
- */
31
- validate(id: string): id is WidgetId {
32
- // UUID v4 format or fallback format
33
- return (
34
- /^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i.test(id) ||
35
- /^widget-\d+-[a-z0-9]{9}$/i.test(id)
36
- );
37
- },
38
-
39
- /**
40
- * Converts a WidgetId to a string for use as map keys or serialization.
41
- * @param id - The WidgetId to convert
42
- * @returns The string representation of the WidgetId
43
- */
44
- toString(id: WidgetId): string {
45
- return id;
46
- },
47
-
48
- /**
49
- * Creates a WidgetId from a string, validating the format.
50
- * @param str - The string to convert to WidgetId
51
- * @returns A WidgetId
52
- * @throws Error if the string is not a valid WidgetId format
53
- */
54
- fromString(str: string): WidgetId {
55
- if (!this.validate(str)) {
56
- throw new Error(`Invalid WidgetId format: ${str}`);
57
- }
58
- return str as WidgetId;
59
- },
60
-
61
- /**
62
- * Checks if two WidgetIds are equal.
63
- * @param a - First WidgetId
64
- * @param b - Second WidgetId
65
- * @returns True if the WidgetIds are the same
66
- */
67
- equals(a: WidgetId, b: WidgetId): boolean {
68
- return a === b;
69
- },
70
- };
@@ -1,21 +0,0 @@
1
- // widget.ts
2
- import { Type } from '@angular/core';
3
-
4
- export interface Widget {
5
- dashboardGetState?(): unknown;
6
- dashboardSetState?(state?: unknown): void;
7
- dashboardEditState?(): void;
8
- }
9
-
10
- export interface WidgetMetadata {
11
- widgetTypeid: string; // application wide unique ID
12
- name: string; // to used in GUI
13
- description: string; // short description for tooltip / GUI
14
- svgIcon: string; // SVG markup as string
15
- }
16
-
17
- export interface WidgetComponentClass<
18
- T extends Widget = Widget
19
- > extends Type<T> {
20
- metadata: WidgetMetadata;
21
- }
@@ -1,127 +0,0 @@
1
- import { Component, Inject } from '@angular/core';
2
- import { CommonModule } from '@angular/common';
3
- import { FormsModule } from '@angular/forms';
4
- import {
5
- MAT_DIALOG_DATA,
6
- MatDialogRef,
7
- MatDialogModule,
8
- } from '@angular/material/dialog';
9
- import { MatButtonModule } from '@angular/material/button';
10
- import { MatRadioModule } from '@angular/material/radio';
11
- import { CellDisplayData } from '../../models/cell-dialog';
12
-
13
- @Component({
14
- selector: 'lib-cell-settings-dialog',
15
- standalone: true,
16
- imports: [
17
- CommonModule,
18
- FormsModule,
19
- MatDialogModule,
20
- MatButtonModule,
21
- MatRadioModule,
22
- ],
23
- template: `
24
- <h2 mat-dialog-title>Cell Display Settings</h2>
25
- <mat-dialog-content>
26
- <p class="cell-info">Cell ID: <strong>{{ data.id }}</strong></p>
27
-
28
- <div class="radio-group">
29
- <mat-radio-group [(ngModel)]="selectedMode" name="displayMode">
30
- <mat-radio-button value="normal">
31
- <div class="radio-option">
32
- <div class="option-title">Normal</div>
33
- <div class="option-description">Standard cell display with full content visibility</div>
34
- </div>
35
- </mat-radio-button>
36
-
37
- <mat-radio-button value="flat">
38
- <div class="radio-option">
39
- <div class="option-title">Flat</div>
40
- <div class="option-description">Simplified display with reduced visual emphasis</div>
41
- </div>
42
- </mat-radio-button>
43
- </mat-radio-group>
44
- </div>
45
- </mat-dialog-content>
46
- <mat-dialog-actions align="end">
47
- <button mat-button (click)="onCancel()">Cancel</button>
48
- <button
49
- mat-flat-button
50
- (click)="save()"
51
- [disabled]="selectedMode === currentMode">
52
- Apply
53
- </button>
54
- </mat-dialog-actions>
55
- `,
56
- styles: [
57
- `
58
- mat-dialog-content {
59
- display: block;
60
- overflow-y: auto;
61
- overflow-x: hidden;
62
- padding-top: 0.5rem;
63
- }
64
-
65
- .cell-info {
66
- margin: 0 0 1.5rem 0;
67
- padding-bottom: 1rem;
68
- }
69
-
70
- .radio-group {
71
- width: 100%;
72
- }
73
-
74
- mat-radio-group {
75
- display: block;
76
- }
77
-
78
- mat-radio-button {
79
- width: 100%;
80
- display: block;
81
- margin-bottom: 1rem;
82
- }
83
-
84
- mat-radio-button:last-child {
85
- margin-bottom: 0;
86
- }
87
-
88
- .radio-option {
89
- margin-left: 0.75rem;
90
- padding: 0.25rem 0;
91
- }
92
-
93
- .option-title {
94
- display: block;
95
- margin-bottom: 0.25rem;
96
- }
97
-
98
- .option-description {
99
- display: block;
100
- }
101
- `,
102
- ],
103
- })
104
- export class CellSettingsDialogComponent {
105
- selectedMode: 'normal' | 'flat';
106
- currentMode: 'normal' | 'flat';
107
-
108
- constructor(
109
- @Inject(MAT_DIALOG_DATA) public data: CellDisplayData,
110
- private dialogRef: MatDialogRef<CellSettingsDialogComponent>
111
- ) {
112
- this.currentMode = data.flat ? 'flat' : 'normal';
113
- this.selectedMode = this.currentMode;
114
- }
115
-
116
- onCancel(): void {
117
- this.dialogRef.close();
118
- }
119
-
120
- save(): void {
121
- const newData: CellDisplayData = {
122
- ...this.data,
123
- flat: this.selectedMode === 'flat'
124
- };
125
- this.dialogRef.close(newData);
126
- }
127
- }
@@ -1,15 +0,0 @@
1
- import { CellDisplayData } from '../../models/cell-dialog';
2
-
3
- /**
4
- * Abstract provider for cell settings dialogs.
5
- * Implement this to provide custom dialog solutions.
6
- */
7
- export abstract class CellSettingsDialogProvider {
8
- /**
9
- * Open a settings dialog for the given cell.
10
- * Returns a promise that resolves to the new settings, or undefined if cancelled.
11
- */
12
- abstract openCellSettings(
13
- data: CellDisplayData
14
- ): Promise<CellDisplayData | undefined>;
15
- }
@@ -1,20 +0,0 @@
1
- import { InjectionToken } from '@angular/core';
2
- import { CellSettingsDialogProvider } from './cell-settings-dialog.provider';
3
- import { DefaultCellSettingsDialogProvider } from './default-cell-settings-dialog.provider';
4
-
5
- /**
6
- * Injection token for the cell dialog provider.
7
- * Use this to provide your custom dialog implementation.
8
- *
9
- * @example
10
- * ```typescript
11
- * providers: [
12
- * { provide: CELL_SETTINGS_DIALOG_PROVIDER, useClass: MyCellSettingsDialogProvider }
13
- * ]
14
- * ```
15
- */
16
- export const CELL_SETTINGS_DIALOG_PROVIDER =
17
- new InjectionToken<CellSettingsDialogProvider>('CellSettingsDialogProvider', {
18
- providedIn: 'root',
19
- factory: () => new DefaultCellSettingsDialogProvider(),
20
- });
@@ -1,32 +0,0 @@
1
- import { Injectable, inject } from '@angular/core';
2
- import { MatDialog } from '@angular/material/dialog';
3
- import { firstValueFrom } from 'rxjs';
4
- import { CellDisplayData } from '../../models/cell-dialog';
5
- import { CellSettingsDialogProvider } from './cell-settings-dialog.provider';
6
- import { CellSettingsDialogComponent } from './cell-settings-dialog.component';
7
-
8
- /**
9
- * Default cell dialog provider that uses Material Design dialogs.
10
- * Provides a modern, accessible dialog experience for cell settings.
11
- */
12
- @Injectable({
13
- providedIn: 'root',
14
- })
15
- export class DefaultCellSettingsDialogProvider extends CellSettingsDialogProvider {
16
- private dialog = inject(MatDialog);
17
-
18
- async openCellSettings(
19
- data: CellDisplayData
20
- ): Promise<CellDisplayData | undefined> {
21
- const dialogRef = this.dialog.open(CellSettingsDialogComponent, {
22
- data,
23
- width: '400px',
24
- maxWidth: '90vw',
25
- disableClose: false,
26
- autoFocus: false,
27
- });
28
-
29
- const result = await firstValueFrom(dialogRef.afterClosed());
30
- return result;
31
- }
32
- }
@@ -1,3 +0,0 @@
1
- export { CellSettingsDialogProvider } from './cell-settings-dialog.provider';
2
- export { DefaultCellSettingsDialogProvider } from './default-cell-settings-dialog.provider';
3
- export { CELL_SETTINGS_DIALOG_PROVIDER } from './cell-settings-dialog.tokens';
@@ -1 +0,0 @@
1
- export * from './cell-settings-dialog';