@alaarab/ogrid-angular 2.1.3 → 2.1.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 (32) hide show
  1. package/dist/esm/index.js +4606 -30
  2. package/dist/types/components/base-datagrid-table.component.d.ts +8 -8
  3. package/package.json +4 -4
  4. package/dist/esm/components/base-column-chooser.component.js +0 -78
  5. package/dist/esm/components/base-column-header-filter.component.js +0 -281
  6. package/dist/esm/components/base-datagrid-table.component.js +0 -648
  7. package/dist/esm/components/base-inline-cell-editor.component.js +0 -253
  8. package/dist/esm/components/base-ogrid.component.js +0 -36
  9. package/dist/esm/components/base-pagination-controls.component.js +0 -72
  10. package/dist/esm/components/base-popover-cell-editor.component.js +0 -114
  11. package/dist/esm/components/empty-state.component.js +0 -58
  12. package/dist/esm/components/grid-context-menu.component.js +0 -153
  13. package/dist/esm/components/inline-cell-editor-template.js +0 -107
  14. package/dist/esm/components/marching-ants-overlay.component.js +0 -164
  15. package/dist/esm/components/ogrid-layout.component.js +0 -188
  16. package/dist/esm/components/sidebar.component.js +0 -274
  17. package/dist/esm/components/status-bar.component.js +0 -71
  18. package/dist/esm/services/column-reorder.service.js +0 -180
  19. package/dist/esm/services/datagrid-editing.service.js +0 -52
  20. package/dist/esm/services/datagrid-interaction.service.js +0 -667
  21. package/dist/esm/services/datagrid-layout.service.js +0 -151
  22. package/dist/esm/services/datagrid-state.service.js +0 -591
  23. package/dist/esm/services/ogrid.service.js +0 -746
  24. package/dist/esm/services/virtual-scroll.service.js +0 -91
  25. package/dist/esm/styles/ogrid-theme-vars.js +0 -53
  26. package/dist/esm/types/columnTypes.js +0 -1
  27. package/dist/esm/types/dataGridTypes.js +0 -1
  28. package/dist/esm/types/index.js +0 -1
  29. package/dist/esm/utils/dataGridViewModel.js +0 -6
  30. package/dist/esm/utils/debounce.js +0 -68
  31. package/dist/esm/utils/index.js +0 -8
  32. package/dist/esm/utils/latestRef.js +0 -41
@@ -1,107 +0,0 @@
1
- /**
2
- * Shared inline cell editor template used by all Angular UI packages.
3
- * The template is identical across Material, PrimeNG, and Radix implementations.
4
- */
5
- export const INLINE_CELL_EDITOR_TEMPLATE = `
6
- @switch (editorType) {
7
- @case ('text') {
8
- <input
9
- #inputEl
10
- type="text"
11
- [value]="localValue()"
12
- (input)="localValue.set($any($event.target).value)"
13
- (keydown)="onTextKeyDown($event)"
14
- (blur)="onTextBlur()"
15
- [style]="getInputStyle()"
16
- />
17
- }
18
- @case ('richSelect') {
19
- <div #richSelectWrapper
20
- style="width:100%;height:100%;display:flex;align-items:center;padding:6px 10px;box-sizing:border-box;min-width:0;position:relative">
21
- <input
22
- #richSelectInput
23
- type="text"
24
- [value]="searchText()"
25
- (input)="onRichSelectSearch($any($event.target).value)"
26
- (keydown)="onRichSelectKeyDown($event)"
27
- placeholder="Search..."
28
- style="width:100%;padding:0;border:none;background:transparent;color:inherit;font:inherit;font-size:13px;outline:none;min-width:0"
29
- />
30
- <div #richSelectDropdown role="listbox"
31
- style="position:absolute;top:100%;left:0;right:0;max-height:200px;overflow-y:auto;background:var(--ogrid-bg, #fff);border:1px solid var(--ogrid-border, rgba(0,0,0,0.12));z-index:10;box-shadow:0 4px 16px rgba(0,0,0,0.2)">
32
- @for (opt of filteredOptions(); track opt; let i = $index) {
33
- <div role="option"
34
- [attr.aria-selected]="i === highlightedIndex()"
35
- (click)="commitValue(opt)"
36
- [style]="i === highlightedIndex() ? 'padding:6px 8px;cursor:pointer;color:var(--ogrid-fg, #242424);background:var(--ogrid-bg-hover, #e8f0fe)' : 'padding:6px 8px;cursor:pointer;color:var(--ogrid-fg, #242424)'">
37
- {{ getDisplayText(opt) }}
38
- </div>
39
- }
40
- @if (filteredOptions().length === 0) {
41
- <div style="padding:6px 8px;color:var(--ogrid-muted, #999)">No matches</div>
42
- }
43
- </div>
44
- </div>
45
- }
46
- @case ('select') {
47
- <div #selectWrapper tabindex="0"
48
- style="width:100%;height:100%;display:flex;align-items:center;padding:6px 10px;box-sizing:border-box;min-width:0;position:relative"
49
- (keydown)="onCustomSelectKeyDown($event)">
50
- <div style="display:flex;align-items:center;justify-content:space-between;width:100%;cursor:pointer;font-size:13px;color:inherit">
51
- <span>{{ getDisplayText(value) }}</span>
52
- <span style="margin-left:4px;font-size:10px;opacity:0.5">&#9662;</span>
53
- </div>
54
- <div #selectDropdown role="listbox"
55
- style="position:absolute;top:100%;left:0;right:0;max-height:200px;overflow-y:auto;background:var(--ogrid-bg, #fff);border:1px solid var(--ogrid-border, rgba(0,0,0,0.12));z-index:10;box-shadow:0 4px 16px rgba(0,0,0,0.2)">
56
- @for (opt of selectOptions(); track opt; let i = $index) {
57
- <div role="option"
58
- [attr.aria-selected]="i === highlightedIndex()"
59
- (click)="commitValue(opt)"
60
- [style]="i === highlightedIndex() ? 'padding:6px 8px;cursor:pointer;color:var(--ogrid-fg, #242424);background:var(--ogrid-bg-hover, #e8f0fe)' : 'padding:6px 8px;cursor:pointer;color:var(--ogrid-fg, #242424)'">
61
- {{ getDisplayText(opt) }}
62
- </div>
63
- }
64
- </div>
65
- </div>
66
- }
67
- @case ('checkbox') {
68
- <div style="display:flex;align-items:center;justify-content:center;width:100%;height:100%">
69
- <input
70
- type="checkbox"
71
- [checked]="!!localValue()"
72
- (change)="commitValue($any($event.target).checked)"
73
- (keydown)="onCheckboxKeyDown($event)"
74
- />
75
- </div>
76
- }
77
- @case ('date') {
78
- <input
79
- #inputEl
80
- type="date"
81
- [value]="localValue()"
82
- (change)="commitValue($any($event.target).value)"
83
- (keydown)="onTextKeyDown($event)"
84
- (blur)="onTextBlur()"
85
- [style]="getInputStyle()"
86
- />
87
- }
88
- @default {
89
- <input
90
- #inputEl
91
- type="text"
92
- [value]="localValue()"
93
- (input)="localValue.set($any($event.target).value)"
94
- (keydown)="onTextKeyDown($event)"
95
- (blur)="onTextBlur()"
96
- [style]="getInputStyle()"
97
- />
98
- }
99
- }
100
- `;
101
- export const INLINE_CELL_EDITOR_STYLES = `
102
- :host {
103
- display: block;
104
- width: 100%;
105
- height: 100%;
106
- }
107
- `;
@@ -1,164 +0,0 @@
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 { Component, Input, signal, DestroyRef, inject, ChangeDetectionStrategy } from '@angular/core';
8
- import { measureRange, injectGlobalStyles } from '@alaarab/ogrid-core';
9
- let MarchingAntsOverlayComponent = class MarchingAntsOverlayComponent {
10
- constructor() {
11
- this.destroyRef = inject(DestroyRef);
12
- this.selectionRange = null;
13
- this.copyRange = null;
14
- this.cutRange = null;
15
- this.colOffset = 0;
16
- this.columnSizingVersion = 0;
17
- this.items = [];
18
- this.visibleColumns = undefined;
19
- this.columnOrder = undefined;
20
- this.selRect = signal(null);
21
- this.clipRect = signal(null);
22
- this.rafId = 0;
23
- this.resizeObserver = null;
24
- injectGlobalStyles('ogrid-marching-ants-keyframes', '@keyframes ogrid-marching-ants{to{stroke-dashoffset:-8}}');
25
- this.destroyRef.onDestroy(() => {
26
- if (this.rafId)
27
- cancelAnimationFrame(this.rafId);
28
- if (this.resizeObserver)
29
- this.resizeObserver.disconnect();
30
- });
31
- }
32
- ngOnChanges(_changes) {
33
- this.recalculate();
34
- }
35
- recalculate() {
36
- const container = this.containerEl;
37
- const selRange = this.selectionRange;
38
- const clipRange = this.copyRange ?? this.cutRange;
39
- const colOff = this.colOffset;
40
- void this.columnSizingVersion; // Track column resize changes
41
- void this.items; // Track data changes (sorting)
42
- void this.visibleColumns; // Track column visibility changes
43
- void this.columnOrder; // Track column reordering
44
- if (this.resizeObserver) {
45
- this.resizeObserver.disconnect();
46
- this.resizeObserver = null;
47
- }
48
- if (!selRange && !clipRange) {
49
- this.selRect.set(null);
50
- this.clipRect.set(null);
51
- return;
52
- }
53
- const measureAll = () => {
54
- if (!container) {
55
- this.selRect.set(null);
56
- this.clipRect.set(null);
57
- return;
58
- }
59
- this.selRect.set(selRange ? measureRange(container, selRange, colOff) : null);
60
- this.clipRect.set(clipRange ? measureRange(container, clipRange, colOff) : null);
61
- };
62
- if (this.rafId)
63
- cancelAnimationFrame(this.rafId);
64
- this.rafId = requestAnimationFrame(measureAll);
65
- if (container) {
66
- this.resizeObserver = new ResizeObserver(measureAll);
67
- this.resizeObserver.observe(container);
68
- }
69
- }
70
- clipRangeMatchesSel() {
71
- const selRange = this.selectionRange;
72
- const clipRange = this.copyRange ?? this.cutRange;
73
- return selRange != null && clipRange != null &&
74
- selRange.startRow === clipRange.startRow &&
75
- selRange.startCol === clipRange.startCol &&
76
- selRange.endRow === clipRange.endRow &&
77
- selRange.endCol === clipRange.endCol;
78
- }
79
- max0(n) {
80
- return Math.max(0, n);
81
- }
82
- };
83
- __decorate([
84
- Input({ required: true })
85
- ], MarchingAntsOverlayComponent.prototype, "containerEl", void 0);
86
- __decorate([
87
- Input()
88
- ], MarchingAntsOverlayComponent.prototype, "selectionRange", void 0);
89
- __decorate([
90
- Input()
91
- ], MarchingAntsOverlayComponent.prototype, "copyRange", void 0);
92
- __decorate([
93
- Input()
94
- ], MarchingAntsOverlayComponent.prototype, "cutRange", void 0);
95
- __decorate([
96
- Input()
97
- ], MarchingAntsOverlayComponent.prototype, "colOffset", void 0);
98
- __decorate([
99
- Input()
100
- ], MarchingAntsOverlayComponent.prototype, "columnSizingVersion", void 0);
101
- __decorate([
102
- Input()
103
- ], MarchingAntsOverlayComponent.prototype, "items", void 0);
104
- __decorate([
105
- Input()
106
- ], MarchingAntsOverlayComponent.prototype, "visibleColumns", void 0);
107
- __decorate([
108
- Input()
109
- ], MarchingAntsOverlayComponent.prototype, "columnOrder", void 0);
110
- MarchingAntsOverlayComponent = __decorate([
111
- Component({
112
- selector: 'ogrid-marching-ants-overlay',
113
- standalone: true,
114
- changeDetection: ChangeDetectionStrategy.OnPush,
115
- styles: [`
116
- .ogrid-marching-ants-svg { position: absolute; pointer-events: none; overflow: visible; }
117
- .ogrid-marching-ants-svg--selection { z-index: 4; }
118
- .ogrid-marching-ants-svg--clip { z-index: 5; }
119
- `],
120
- template: `
121
- @if (selRect() && !clipRangeMatchesSel()) {
122
- <svg
123
- class="ogrid-marching-ants-svg ogrid-marching-ants-svg--selection"
124
- [style.top.px]="selRect()!.top"
125
- [style.left.px]="selRect()!.left"
126
- [style.width.px]="selRect()!.width"
127
- [style.height.px]="selRect()!.height"
128
- aria-hidden="true"
129
- >
130
- <rect
131
- x="1" y="1"
132
- [attr.width]="max0(selRect()!.width - 2)"
133
- [attr.height]="max0(selRect()!.height - 2)"
134
- fill="none"
135
- stroke="var(--ogrid-selection, #217346)"
136
- stroke-width="2"
137
- />
138
- </svg>
139
- }
140
- @if (clipRect()) {
141
- <svg
142
- class="ogrid-marching-ants-svg ogrid-marching-ants-svg--clip"
143
- [style.top.px]="clipRect()!.top"
144
- [style.left.px]="clipRect()!.left"
145
- [style.width.px]="clipRect()!.width"
146
- [style.height.px]="clipRect()!.height"
147
- aria-hidden="true"
148
- >
149
- <rect
150
- x="1" y="1"
151
- [attr.width]="max0(clipRect()!.width - 2)"
152
- [attr.height]="max0(clipRect()!.height - 2)"
153
- fill="none"
154
- stroke="var(--ogrid-selection, #217346)"
155
- stroke-width="2"
156
- stroke-dasharray="4 4"
157
- style="animation: ogrid-marching-ants 0.5s linear infinite"
158
- />
159
- </svg>
160
- }
161
- `,
162
- })
163
- ], MarchingAntsOverlayComponent);
164
- export { MarchingAntsOverlayComponent };
@@ -1,188 +0,0 @@
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 { Component, Input, ViewEncapsulation, ChangeDetectionStrategy } from '@angular/core';
8
- import { SideBarComponent } from './sidebar.component';
9
- import { GRID_BORDER_RADIUS } from '@alaarab/ogrid-core';
10
- import { OGRID_THEME_VARS_CSS } from '../styles/ogrid-theme-vars';
11
- let OGridLayoutComponent = class OGridLayoutComponent {
12
- constructor() {
13
- this.hasToolbar = false;
14
- this.hasToolbarBelow = false;
15
- this.hasPagination = false;
16
- this.sideBar = null;
17
- this.fullScreen = false;
18
- this.isFullScreen = false;
19
- this.borderRadius = GRID_BORDER_RADIUS;
20
- this.escListener = null;
21
- }
22
- get rootClass() {
23
- const base = (this.className ?? '') + ' ogrid-layout-root';
24
- return this.isFullScreen ? base + ' ogrid-layout-root--fullscreen' : base;
25
- }
26
- toggleFullScreen() {
27
- this.isFullScreen = !this.isFullScreen;
28
- if (this.isFullScreen) {
29
- this.escListener = (e) => {
30
- if (e.key === 'Escape') {
31
- this.isFullScreen = false;
32
- this.removeEscListener();
33
- }
34
- };
35
- document.addEventListener('keydown', this.escListener);
36
- }
37
- else {
38
- this.removeEscListener();
39
- }
40
- }
41
- removeEscListener() {
42
- if (this.escListener) {
43
- document.removeEventListener('keydown', this.escListener);
44
- this.escListener = null;
45
- }
46
- }
47
- };
48
- __decorate([
49
- Input()
50
- ], OGridLayoutComponent.prototype, "className", void 0);
51
- __decorate([
52
- Input()
53
- ], OGridLayoutComponent.prototype, "hasToolbar", void 0);
54
- __decorate([
55
- Input()
56
- ], OGridLayoutComponent.prototype, "hasToolbarBelow", void 0);
57
- __decorate([
58
- Input()
59
- ], OGridLayoutComponent.prototype, "hasPagination", void 0);
60
- __decorate([
61
- Input()
62
- ], OGridLayoutComponent.prototype, "sideBar", void 0);
63
- __decorate([
64
- Input()
65
- ], OGridLayoutComponent.prototype, "fullScreen", void 0);
66
- OGridLayoutComponent = __decorate([
67
- Component({
68
- selector: 'ogrid-layout',
69
- standalone: true,
70
- encapsulation: ViewEncapsulation.None,
71
- changeDetection: ChangeDetectionStrategy.OnPush,
72
- imports: [SideBarComponent],
73
- styles: [OGRID_THEME_VARS_CSS, `
74
- :host { display: block; height: 100%; }
75
- .ogrid-layout-root { display: flex; flex-direction: column; height: 100%; }
76
- .ogrid-layout-root--fullscreen {
77
- position: fixed; inset: 0; z-index: 9999;
78
- background: var(--ogrid-bg, #ffffff);
79
- }
80
- .ogrid-layout-container {
81
- border: 1px solid var(--ogrid-border, rgba(0, 0, 0, 0.12));
82
- overflow: hidden; display: flex; flex-direction: column;
83
- flex: 1; min-height: 0; background: var(--ogrid-bg, #ffffff);
84
- color: var(--ogrid-fg, rgba(0, 0, 0, 0.87));
85
- }
86
- .ogrid-layout-root--fullscreen .ogrid-layout-container {
87
- border: none; border-radius: 0 !important;
88
- }
89
- .ogrid-layout-toolbar {
90
- display: flex; justify-content: space-between; align-items: center;
91
- padding: 6px 12px; background: var(--ogrid-header-bg, rgba(0, 0, 0, 0.04));
92
- gap: 8px; flex-wrap: wrap; min-height: 0;
93
- }
94
- .ogrid-layout-toolbar--has-below { border-bottom: none; }
95
- .ogrid-layout-toolbar--no-below { border-bottom: 1px solid var(--ogrid-border, rgba(0, 0, 0, 0.12)); }
96
- .ogrid-layout-toolbar-left { display: flex; align-items: center; gap: 8px; }
97
- .ogrid-layout-toolbar-right { display: flex; align-items: center; gap: 8px; }
98
- .ogrid-layout-toolbar-below {
99
- border-bottom: 1px solid var(--ogrid-border, rgba(0, 0, 0, 0.12));
100
- padding: 6px 12px; background: var(--ogrid-header-bg, rgba(0, 0, 0, 0.04));
101
- }
102
- .ogrid-layout-grid-area { width: 100%; min-width: 0; min-height: 0; flex: 1; display: flex; }
103
- .ogrid-layout-grid-content { flex: 1; min-width: 0; min-height: 0; display: flex; flex-direction: column; overflow: hidden; }
104
- .ogrid-layout-footer {
105
- border-top: 1px solid var(--ogrid-border, rgba(0, 0, 0, 0.12));
106
- background: var(--ogrid-header-bg, rgba(0, 0, 0, 0.04)); padding: 6px 12px;
107
- }
108
- .ogrid-fullscreen-btn {
109
- background: none; border: 1px solid var(--ogrid-border, rgba(0, 0, 0, 0.12));
110
- border-radius: 4px; padding: 4px 6px; cursor: pointer;
111
- display: flex; align-items: center; justify-content: center;
112
- color: var(--ogrid-fg, rgba(0, 0, 0, 0.87));
113
- }
114
- .ogrid-fullscreen-btn:hover { background: var(--ogrid-hover-bg, rgba(0, 0, 0, 0.04)); }
115
- `],
116
- template: `
117
- <div [class]="rootClass">
118
- <div class="ogrid-layout-container" [style.border-radius.px]="borderRadius">
119
- <!-- Toolbar strip -->
120
- @if (hasToolbar || fullScreen) {
121
- <div
122
- class="ogrid-layout-toolbar"
123
- [class.ogrid-layout-toolbar--has-below]="hasToolbarBelow"
124
- [class.ogrid-layout-toolbar--no-below]="!hasToolbarBelow"
125
- >
126
- <div class="ogrid-layout-toolbar-left">
127
- <ng-content select="[toolbar]"></ng-content>
128
- </div>
129
- <div class="ogrid-layout-toolbar-right">
130
- <ng-content select="[toolbarEnd]"></ng-content>
131
- @if (fullScreen) {
132
- <button type="button" class="ogrid-fullscreen-btn"
133
- [attr.title]="isFullScreen ? 'Exit fullscreen' : 'Fullscreen'"
134
- [attr.aria-label]="isFullScreen ? 'Exit fullscreen' : 'Fullscreen'"
135
- (click)="toggleFullScreen()">
136
- @if (isFullScreen) {
137
- <svg width="16" height="16" viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round">
138
- <polyline points="4 10 0 10 0 14"></polyline>
139
- <polyline points="12 6 16 6 16 2"></polyline>
140
- <line x1="0" y1="10" x2="4" y2="6"></line>
141
- <line x1="16" y1="6" x2="12" y2="10"></line>
142
- </svg>
143
- } @else {
144
- <svg width="16" height="16" viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round">
145
- <polyline points="10 2 14 2 14 6"></polyline>
146
- <polyline points="6 14 2 14 2 10"></polyline>
147
- <line x1="14" y1="2" x2="10" y2="6"></line>
148
- <line x1="2" y1="14" x2="6" y2="10"></line>
149
- </svg>
150
- }
151
- </button>
152
- }
153
- </div>
154
- </div>
155
- }
156
-
157
- <!-- Secondary toolbar row -->
158
- @if (hasToolbarBelow) {
159
- <div class="ogrid-layout-toolbar-below">
160
- <ng-content select="[toolbarBelow]"></ng-content>
161
- </div>
162
- }
163
-
164
- <!-- Grid area -->
165
- <div class="ogrid-layout-grid-area">
166
- @if (sideBar && sideBar.position === 'left') {
167
- <ogrid-sidebar [sideBarProps]="sideBar"></ogrid-sidebar>
168
- }
169
- <div class="ogrid-layout-grid-content">
170
- <ng-content></ng-content>
171
- </div>
172
- @if (sideBar && sideBar.position !== 'left') {
173
- <ogrid-sidebar [sideBarProps]="sideBar"></ogrid-sidebar>
174
- }
175
- </div>
176
-
177
- <!-- Footer strip (pagination) -->
178
- @if (hasPagination) {
179
- <div class="ogrid-layout-footer">
180
- <ng-content select="[pagination]"></ng-content>
181
- </div>
182
- }
183
- </div>
184
- </div>
185
- `,
186
- })
187
- ], OGridLayoutComponent);
188
- export { OGridLayoutComponent };