@alaarab/ogrid-angular 2.1.3 → 2.1.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/esm/index.js +4606 -30
- package/dist/types/components/base-datagrid-table.component.d.ts +8 -8
- package/package.json +4 -4
- package/dist/esm/components/base-column-chooser.component.js +0 -78
- package/dist/esm/components/base-column-header-filter.component.js +0 -281
- package/dist/esm/components/base-datagrid-table.component.js +0 -648
- package/dist/esm/components/base-inline-cell-editor.component.js +0 -253
- package/dist/esm/components/base-ogrid.component.js +0 -36
- package/dist/esm/components/base-pagination-controls.component.js +0 -72
- package/dist/esm/components/base-popover-cell-editor.component.js +0 -114
- package/dist/esm/components/empty-state.component.js +0 -58
- package/dist/esm/components/grid-context-menu.component.js +0 -153
- package/dist/esm/components/inline-cell-editor-template.js +0 -107
- package/dist/esm/components/marching-ants-overlay.component.js +0 -164
- package/dist/esm/components/ogrid-layout.component.js +0 -188
- package/dist/esm/components/sidebar.component.js +0 -274
- package/dist/esm/components/status-bar.component.js +0 -71
- package/dist/esm/services/column-reorder.service.js +0 -180
- package/dist/esm/services/datagrid-editing.service.js +0 -52
- package/dist/esm/services/datagrid-interaction.service.js +0 -667
- package/dist/esm/services/datagrid-layout.service.js +0 -151
- package/dist/esm/services/datagrid-state.service.js +0 -591
- package/dist/esm/services/ogrid.service.js +0 -746
- package/dist/esm/services/virtual-scroll.service.js +0 -91
- package/dist/esm/styles/ogrid-theme-vars.js +0 -53
- package/dist/esm/types/columnTypes.js +0 -1
- package/dist/esm/types/dataGridTypes.js +0 -1
- package/dist/esm/types/index.js +0 -1
- package/dist/esm/utils/dataGridViewModel.js +0 -6
- package/dist/esm/utils/debounce.js +0 -68
- package/dist/esm/utils/index.js +0 -8
- package/dist/esm/utils/latestRef.js +0 -41
|
@@ -1,91 +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 { Injectable, signal, computed, DestroyRef, inject } from '@angular/core';
|
|
8
|
-
import { computeVisibleRange, computeTotalHeight, getScrollTopForRow, } from '@alaarab/ogrid-core';
|
|
9
|
-
/** Threshold below which virtual scrolling is a no-op (all rows rendered). */
|
|
10
|
-
const PASSTHROUGH_THRESHOLD = 100;
|
|
11
|
-
/**
|
|
12
|
-
* Manages virtual scrolling state using Angular signals.
|
|
13
|
-
* Port of React's useVirtualScroll hook.
|
|
14
|
-
*
|
|
15
|
-
* Uses core's pure-TS `computeVisibleRange` and `getScrollTopForRow` utilities.
|
|
16
|
-
* The UI layer (Angular Material / PrimeNG) provides the scrollable container
|
|
17
|
-
* and calls `onScroll()` / sets `containerHeight`.
|
|
18
|
-
*/
|
|
19
|
-
let VirtualScrollService = class VirtualScrollService {
|
|
20
|
-
constructor() {
|
|
21
|
-
this.destroyRef = inject(DestroyRef);
|
|
22
|
-
// --- Input signals (set by consuming component) ---
|
|
23
|
-
this.totalRows = signal(0);
|
|
24
|
-
this.config = signal({ rowHeight: 36 });
|
|
25
|
-
this.containerHeight = signal(0);
|
|
26
|
-
// --- Internal state ---
|
|
27
|
-
this.scrollTop = signal(0);
|
|
28
|
-
// Scrollable container reference for programmatic scrolling
|
|
29
|
-
this.containerEl = null;
|
|
30
|
-
// --- Derived computed signals ---
|
|
31
|
-
this.rowHeight = computed(() => this.config().rowHeight ?? 36);
|
|
32
|
-
this.overscan = computed(() => this.config().overscan ?? 5);
|
|
33
|
-
this.enabled = computed(() => this.config().enabled !== false);
|
|
34
|
-
/** Whether virtual scrolling is actually active (enabled + enough rows). */
|
|
35
|
-
this.isActive = computed(() => this.enabled() && this.totalRows() >= PASSTHROUGH_THRESHOLD);
|
|
36
|
-
/** The visible range of rows with spacer offsets. */
|
|
37
|
-
this.visibleRange = computed(() => {
|
|
38
|
-
if (!this.isActive()) {
|
|
39
|
-
// Passthrough: render all rows
|
|
40
|
-
return {
|
|
41
|
-
startIndex: 0,
|
|
42
|
-
endIndex: Math.max(0, this.totalRows() - 1),
|
|
43
|
-
offsetTop: 0,
|
|
44
|
-
offsetBottom: 0,
|
|
45
|
-
};
|
|
46
|
-
}
|
|
47
|
-
return computeVisibleRange(this.scrollTop(), this.rowHeight(), this.containerHeight(), this.totalRows(), this.overscan());
|
|
48
|
-
});
|
|
49
|
-
/** Total scrollable height in pixels. */
|
|
50
|
-
this.totalHeight = computed(() => computeTotalHeight(this.totalRows(), this.rowHeight()));
|
|
51
|
-
this.destroyRef.onDestroy(() => {
|
|
52
|
-
this.containerEl = null;
|
|
53
|
-
});
|
|
54
|
-
}
|
|
55
|
-
/**
|
|
56
|
-
* Set the scrollable container element.
|
|
57
|
-
* Used for programmatic scrolling (scrollToRow).
|
|
58
|
-
*/
|
|
59
|
-
setContainer(el) {
|
|
60
|
-
this.containerEl = el;
|
|
61
|
-
}
|
|
62
|
-
/**
|
|
63
|
-
* Call this from the container's scroll event handler.
|
|
64
|
-
*/
|
|
65
|
-
onScroll(event) {
|
|
66
|
-
const target = event.target;
|
|
67
|
-
this.scrollTop.set(target.scrollTop);
|
|
68
|
-
}
|
|
69
|
-
/**
|
|
70
|
-
* Scroll to a specific row index.
|
|
71
|
-
* @param index - The row index to scroll to.
|
|
72
|
-
* @param align - Where to position the row: 'start' (top), 'center', or 'end' (bottom). Default: 'start'.
|
|
73
|
-
*/
|
|
74
|
-
scrollToRow(index, align = 'start') {
|
|
75
|
-
const container = this.containerEl;
|
|
76
|
-
if (!container)
|
|
77
|
-
return;
|
|
78
|
-
const targetScrollTop = getScrollTopForRow(index, this.rowHeight(), this.containerHeight(), align);
|
|
79
|
-
container.scrollTo({ top: targetScrollTop, behavior: 'auto' });
|
|
80
|
-
}
|
|
81
|
-
/**
|
|
82
|
-
* Update the virtual scroll configuration.
|
|
83
|
-
*/
|
|
84
|
-
updateConfig(updates) {
|
|
85
|
-
this.config.update((prev) => ({ ...prev, ...updates }));
|
|
86
|
-
}
|
|
87
|
-
};
|
|
88
|
-
VirtualScrollService = __decorate([
|
|
89
|
-
Injectable()
|
|
90
|
-
], VirtualScrollService);
|
|
91
|
-
export { VirtualScrollService };
|
|
@@ -1,53 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Shared OGrid CSS theme variables (light + dark mode).
|
|
3
|
-
* Used by all Angular UI packages (Material, PrimeNG, Radix) to avoid duplication.
|
|
4
|
-
*/
|
|
5
|
-
export const OGRID_THEME_VARS_CSS = `
|
|
6
|
-
/* ─── OGrid Theme Variables ─── */
|
|
7
|
-
:root {
|
|
8
|
-
--ogrid-bg: #ffffff;
|
|
9
|
-
--ogrid-fg: rgba(0, 0, 0, 0.87);
|
|
10
|
-
--ogrid-fg-secondary: rgba(0, 0, 0, 0.6);
|
|
11
|
-
--ogrid-fg-muted: rgba(0, 0, 0, 0.5);
|
|
12
|
-
--ogrid-border: rgba(0, 0, 0, 0.12);
|
|
13
|
-
--ogrid-header-bg: rgba(0, 0, 0, 0.04);
|
|
14
|
-
--ogrid-hover-bg: rgba(0, 0, 0, 0.04);
|
|
15
|
-
--ogrid-selected-row-bg: #e6f0fb;
|
|
16
|
-
--ogrid-active-cell-bg: rgba(0, 0, 0, 0.02);
|
|
17
|
-
--ogrid-range-bg: rgba(33, 115, 70, 0.12);
|
|
18
|
-
--ogrid-accent: #0078d4;
|
|
19
|
-
--ogrid-selection-color: #217346;
|
|
20
|
-
--ogrid-loading-overlay: rgba(255, 255, 255, 0.7);
|
|
21
|
-
}
|
|
22
|
-
@media (prefers-color-scheme: dark) {
|
|
23
|
-
:root:not([data-theme="light"]) {
|
|
24
|
-
--ogrid-bg: #1e1e1e;
|
|
25
|
-
--ogrid-fg: rgba(255, 255, 255, 0.87);
|
|
26
|
-
--ogrid-fg-secondary: rgba(255, 255, 255, 0.6);
|
|
27
|
-
--ogrid-fg-muted: rgba(255, 255, 255, 0.5);
|
|
28
|
-
--ogrid-border: rgba(255, 255, 255, 0.12);
|
|
29
|
-
--ogrid-header-bg: rgba(255, 255, 255, 0.06);
|
|
30
|
-
--ogrid-hover-bg: rgba(255, 255, 255, 0.08);
|
|
31
|
-
--ogrid-selected-row-bg: #1a3a5c;
|
|
32
|
-
--ogrid-active-cell-bg: rgba(255, 255, 255, 0.06);
|
|
33
|
-
--ogrid-range-bg: rgba(46, 160, 67, 0.15);
|
|
34
|
-
--ogrid-accent: #4da6ff;
|
|
35
|
-
--ogrid-selection-color: #2ea043;
|
|
36
|
-
--ogrid-loading-overlay: rgba(0, 0, 0, 0.7);
|
|
37
|
-
}
|
|
38
|
-
}
|
|
39
|
-
[data-theme="dark"] {
|
|
40
|
-
--ogrid-bg: #1e1e1e;
|
|
41
|
-
--ogrid-fg: rgba(255, 255, 255, 0.87);
|
|
42
|
-
--ogrid-fg-secondary: rgba(255, 255, 255, 0.6);
|
|
43
|
-
--ogrid-fg-muted: rgba(255, 255, 255, 0.5);
|
|
44
|
-
--ogrid-border: rgba(255, 255, 255, 0.12);
|
|
45
|
-
--ogrid-header-bg: rgba(255, 255, 255, 0.06);
|
|
46
|
-
--ogrid-hover-bg: rgba(255, 255, 255, 0.08);
|
|
47
|
-
--ogrid-selected-row-bg: #1a3a5c;
|
|
48
|
-
--ogrid-active-cell-bg: rgba(255, 255, 255, 0.06);
|
|
49
|
-
--ogrid-range-bg: rgba(46, 160, 67, 0.15);
|
|
50
|
-
--ogrid-accent: #4da6ff;
|
|
51
|
-
--ogrid-selection-color: #2ea043;
|
|
52
|
-
--ogrid-loading-overlay: rgba(0, 0, 0, 0.7);
|
|
53
|
-
}`;
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export {};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export { toUserLike, isInSelectionRange, normalizeSelectionRange } from '@alaarab/ogrid-core';
|
package/dist/esm/types/index.js
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export { toUserLike, isInSelectionRange, normalizeSelectionRange } from './dataGridTypes';
|
|
@@ -1,6 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* View model helpers for Angular DataGridTable.
|
|
3
|
-
* Pure functions live in @alaarab/ogrid-core. This file re-exports them.
|
|
4
|
-
*/
|
|
5
|
-
// Re-export everything from core's dataGridViewModel
|
|
6
|
-
export { getHeaderFilterConfig, getCellRenderDescriptor, resolveCellDisplayContent, resolveCellStyle, buildInlineEditorProps, buildPopoverEditorProps, } from '@alaarab/ogrid-core';
|
|
@@ -1,68 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Debounce utilities for Angular using signals.
|
|
3
|
-
* Provides functional parity with React's useDebounce and useDebouncedCallback.
|
|
4
|
-
*/
|
|
5
|
-
import { signal, effect } from '@angular/core';
|
|
6
|
-
/**
|
|
7
|
-
* Creates a debounced signal that updates after the specified delay when the source value changes.
|
|
8
|
-
*
|
|
9
|
-
* @param source - The signal to debounce
|
|
10
|
-
* @param delayMs - Delay in milliseconds
|
|
11
|
-
* @returns A signal containing the debounced value
|
|
12
|
-
*
|
|
13
|
-
* @example
|
|
14
|
-
* ```typescript
|
|
15
|
-
* const searchQuery = signal('');
|
|
16
|
-
* const debouncedQuery = createDebouncedSignal(searchQuery, 300);
|
|
17
|
-
*
|
|
18
|
-
* effect(() => {
|
|
19
|
-
* console.log('Debounced search:', debouncedQuery());
|
|
20
|
-
* });
|
|
21
|
-
* ```
|
|
22
|
-
*/
|
|
23
|
-
export function createDebouncedSignal(source, delayMs) {
|
|
24
|
-
const debouncedValue = signal(source());
|
|
25
|
-
effect((onCleanup) => {
|
|
26
|
-
const currentValue = source();
|
|
27
|
-
const timeoutId = setTimeout(() => {
|
|
28
|
-
debouncedValue.set(currentValue);
|
|
29
|
-
}, delayMs);
|
|
30
|
-
onCleanup(() => clearTimeout(timeoutId));
|
|
31
|
-
});
|
|
32
|
-
return debouncedValue;
|
|
33
|
-
}
|
|
34
|
-
/**
|
|
35
|
-
* Creates a debounced function that delays invoking the provided function
|
|
36
|
-
* until after `delayMs` milliseconds have elapsed since the last time it was invoked.
|
|
37
|
-
*
|
|
38
|
-
* @param fn - The function to debounce
|
|
39
|
-
* @param delayMs - Delay in milliseconds
|
|
40
|
-
* @returns A debounced version of the function
|
|
41
|
-
*
|
|
42
|
-
* @example
|
|
43
|
-
* ```typescript
|
|
44
|
-
* const saveData = (value: string) => {
|
|
45
|
-
* console.log('Saving:', value);
|
|
46
|
-
* };
|
|
47
|
-
*
|
|
48
|
-
* const debouncedSave = createDebouncedCallback(saveData, 500);
|
|
49
|
-
*
|
|
50
|
-
* // Multiple rapid calls will only trigger once after 500ms
|
|
51
|
-
* debouncedSave('hello');
|
|
52
|
-
* debouncedSave('world'); // Only this will execute after 500ms
|
|
53
|
-
* ```
|
|
54
|
-
*/
|
|
55
|
-
export function createDebouncedCallback(fn, delayMs) {
|
|
56
|
-
let timeoutId = null;
|
|
57
|
-
return ((...args) => {
|
|
58
|
-
if (timeoutId !== null) {
|
|
59
|
-
clearTimeout(timeoutId);
|
|
60
|
-
}
|
|
61
|
-
timeoutId = setTimeout(() => {
|
|
62
|
-
fn(...args);
|
|
63
|
-
timeoutId = null;
|
|
64
|
-
}, delayMs);
|
|
65
|
-
});
|
|
66
|
-
}
|
|
67
|
-
// Re-export simple debounce from core
|
|
68
|
-
export { debounce } from '@alaarab/ogrid-core';
|
package/dist/esm/utils/index.js
DELETED
|
@@ -1,8 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Shared utilities for Angular DataGridTable view layer.
|
|
3
|
-
*/
|
|
4
|
-
export { getHeaderFilterConfig, getCellRenderDescriptor, resolveCellDisplayContent, resolveCellStyle, buildInlineEditorProps, buildPopoverEditorProps, } from './dataGridViewModel';
|
|
5
|
-
// Debounce utilities
|
|
6
|
-
export { createDebouncedSignal, createDebouncedCallback, debounce, } from './debounce';
|
|
7
|
-
// Latest ref utilities
|
|
8
|
-
export { createLatestCallback, } from './latestRef';
|
|
@@ -1,41 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Latest ref utility for Angular using signals.
|
|
3
|
-
* Provides functional parity with React's useLatestRef.
|
|
4
|
-
*/
|
|
5
|
-
/**
|
|
6
|
-
* Creates a stable wrapper function that always calls the latest version of the provided function.
|
|
7
|
-
* Useful for event handlers and callbacks where you want a stable reference but need to call
|
|
8
|
-
* the latest implementation.
|
|
9
|
-
*
|
|
10
|
-
* @param fn - Signal containing the function to wrap
|
|
11
|
-
* @returns A stable function that always invokes the latest version
|
|
12
|
-
*
|
|
13
|
-
* @example
|
|
14
|
-
* ```typescript
|
|
15
|
-
* class MyService {
|
|
16
|
-
* readonly onSave = signal<(value: string) => void>((val) => console.log('Default:', val));
|
|
17
|
-
* readonly stableOnSave = createLatestCallback(this.onSave);
|
|
18
|
-
*
|
|
19
|
-
* constructor() {
|
|
20
|
-
* // Setup event listener with stable reference
|
|
21
|
-
* effect((onCleanup) => {
|
|
22
|
-
* // stableOnSave never changes, so this effect only runs once
|
|
23
|
-
* const callback = () => this.stableOnSave('data');
|
|
24
|
-
* window.addEventListener('click', callback);
|
|
25
|
-
* onCleanup(() => window.removeEventListener('click', callback));
|
|
26
|
-
* });
|
|
27
|
-
* }
|
|
28
|
-
*
|
|
29
|
-
* updateHandler(newFn: (value: string) => void) {
|
|
30
|
-
* // Even though we change the function, the callback reference stays stable
|
|
31
|
-
* this.onSave.set(newFn);
|
|
32
|
-
* }
|
|
33
|
-
* }
|
|
34
|
-
* ```
|
|
35
|
-
*/
|
|
36
|
-
export function createLatestCallback(fn) {
|
|
37
|
-
// Return a stable function that always calls the current value of the signal
|
|
38
|
-
return ((...args) => {
|
|
39
|
-
return fn()(...args);
|
|
40
|
-
});
|
|
41
|
-
}
|