argent-grid 0.1.0 → 0.3.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.
- package/.github/workflows/ci.yml +69 -0
- package/.github/workflows/pages.yml +6 -12
- package/.storybook/main.ts +20 -0
- package/.storybook/preview.ts +18 -0
- package/.storybook/tsconfig.json +24 -0
- package/AGENTS.md +70 -27
- package/README.md +51 -34
- package/angular.json +66 -0
- package/biome.json +66 -0
- package/demo-app/e2e/selection-screenshot.spec.ts +20 -0
- package/docs/AG-GRID-COMPARISON.md +725 -0
- package/docs/CELL-RENDERER-GUIDE.md +241 -0
- package/docs/CONTEXT-MENU-GUIDE.md +371 -0
- package/docs/LIVE-DATA-OPTIMIZATIONS.md +497 -0
- package/docs/PERFORMANCE-OPTIMIZATIONS-PHASE1.md +162 -0
- package/docs/PERFORMANCE-REVIEW.md +571 -0
- package/docs/RESEARCH-STATUS.md +234 -0
- package/docs/STATE-PERSISTENCE-GUIDE.md +370 -0
- package/docs/STORYBOOK-REFACTOR.md +215 -0
- package/docs/STORYBOOK-STATUS.md +156 -0
- package/docs/TEST-COVERAGE-REPORT.md +276 -0
- package/docs/THEME-API-GUIDE.md +445 -0
- package/docs/THEME-API-PLAN.md +364 -0
- package/e2e/advanced.spec.ts +109 -0
- package/e2e/argentgrid.spec.ts +65 -0
- package/e2e/benchmark.spec.ts +52 -0
- package/e2e/cell-renderers.spec.ts +152 -0
- package/e2e/debug-streaming.spec.ts +31 -0
- package/e2e/dnd.spec.ts +73 -0
- package/e2e/screenshots.spec.ts +52 -0
- package/e2e/theming.spec.ts +35 -0
- package/e2e/visual.spec.ts +112 -0
- package/e2e/visual.spec.ts-snapshots/checkbox-renderer-mixed.png +0 -0
- package/e2e/visual.spec.ts-snapshots/debug.png +0 -0
- package/e2e/visual.spec.ts-snapshots/grid-column-group-headers.png +0 -0
- package/e2e/visual.spec.ts-snapshots/grid-default.png +0 -0
- package/e2e/visual.spec.ts-snapshots/grid-empty-state.png +0 -0
- package/e2e/visual.spec.ts-snapshots/grid-filter-popup.png +0 -0
- package/e2e/visual.spec.ts-snapshots/grid-scroll-borders.png +0 -0
- package/e2e/visual.spec.ts-snapshots/grid-sidebar-buttons.png +0 -0
- package/e2e/visual.spec.ts-snapshots/grid-text-filter.png +0 -0
- package/e2e/visual.spec.ts-snapshots/grid-with-selection.png +0 -0
- package/e2e/visual.spec.ts-snapshots/rating-renderer-varied.png +0 -0
- package/package.json +21 -7
- package/plan.md +56 -28
- package/playwright.config.ts +38 -0
- package/setup-vitest.ts +10 -13
- package/src/lib/argent-grid.module.ts +10 -12
- package/src/lib/components/argent-grid.component.css +281 -321
- package/src/lib/components/argent-grid.component.html +295 -207
- package/src/lib/components/argent-grid.component.spec.ts +120 -160
- package/src/lib/components/argent-grid.component.ts +1193 -290
- package/src/lib/components/argent-grid.regressions.spec.ts +301 -0
- package/src/lib/components/argent-grid.selection.spec.ts +132 -0
- package/src/lib/components/set-filter/set-filter.component.spec.ts +191 -0
- package/src/lib/components/set-filter/set-filter.component.ts +307 -0
- package/src/lib/directives/ag-grid-compatibility.directive.ts +16 -26
- package/src/lib/directives/click-outside.directive.ts +19 -0
- package/src/lib/rendering/canvas-renderer.spec.ts +513 -0
- package/src/lib/rendering/canvas-renderer.ts +456 -452
- package/src/lib/rendering/live-data-handler.ts +110 -0
- package/src/lib/rendering/live-data-optimizations.ts +133 -0
- package/src/lib/rendering/render/blit.spec.ts +16 -27
- package/src/lib/rendering/render/blit.ts +48 -36
- package/src/lib/rendering/render/cells.spec.ts +132 -0
- package/src/lib/rendering/render/cells.ts +167 -28
- package/src/lib/rendering/render/column-utils.ts +95 -0
- package/src/lib/rendering/render/hit-test.ts +50 -0
- package/src/lib/rendering/render/index.ts +88 -76
- package/src/lib/rendering/render/lines.ts +53 -47
- package/src/lib/rendering/render/primitives.ts +423 -0
- package/src/lib/rendering/render/theme.spec.ts +8 -12
- package/src/lib/rendering/render/theme.ts +7 -10
- package/src/lib/rendering/render/types.ts +3 -2
- package/src/lib/rendering/render/walk.spec.ts +35 -38
- package/src/lib/rendering/render/walk.ts +94 -64
- package/src/lib/rendering/utils/damage-tracker.spec.ts +8 -7
- package/src/lib/rendering/utils/damage-tracker.ts +6 -18
- package/src/lib/rendering/utils/index.ts +1 -1
- package/src/lib/services/grid.service.set-filter.spec.ts +219 -0
- package/src/lib/services/grid.service.spec.ts +1241 -201
- package/src/lib/services/grid.service.ts +1204 -235
- package/src/lib/themes/parts/color-schemes.ts +132 -0
- package/src/lib/themes/parts/icon-sets.ts +258 -0
- package/src/lib/themes/theme-builder.ts +347 -0
- package/src/lib/themes/theme-quartz.ts +72 -0
- package/src/lib/themes/types.ts +238 -0
- package/src/lib/types/ag-grid-types.ts +573 -14
- package/src/public-api.ts +39 -9
- package/src/stories/Advanced.stories.ts +249 -0
- package/src/stories/ArgentGrid.stories.ts +301 -0
- package/src/stories/Benchmark.stories.ts +76 -0
- package/src/stories/CellRenderers.stories.ts +395 -0
- package/src/stories/Filtering.stories.ts +292 -0
- package/src/stories/Grouping.stories.ts +290 -0
- package/src/stories/Streaming.stories.ts +57 -0
- package/src/stories/Theming.stories.ts +137 -0
- package/src/stories/Tooltips.stories.ts +381 -0
- package/src/stories/benchmark-wrapper.component.ts +355 -0
- package/src/stories/story-utils.ts +88 -0
- package/src/stories/streaming-wrapper.component.ts +441 -0
- package/tsconfig.json +1 -0
- package/tsconfig.storybook.json +10 -0
- package/vitest.config.ts +9 -9
- package/demo-app/README.md +0 -70
- package/demo-app/angular.json +0 -78
- package/demo-app/e2e/benchmark.spec.ts +0 -53
- package/demo-app/e2e/demo-page.spec.ts +0 -77
- package/demo-app/e2e/grid-features.spec.ts +0 -269
- package/demo-app/package-lock.json +0 -14023
- package/demo-app/package.json +0 -36
- package/demo-app/playwright-test-menu.js +0 -19
- package/demo-app/playwright.config.ts +0 -23
- package/demo-app/src/app/app.component.ts +0 -10
- package/demo-app/src/app/app.config.ts +0 -13
- package/demo-app/src/app/app.routes.ts +0 -7
- package/demo-app/src/app/demo-page/demo-page.component.css +0 -313
- package/demo-app/src/app/demo-page/demo-page.component.html +0 -124
- package/demo-app/src/app/demo-page/demo-page.component.ts +0 -366
- package/demo-app/src/index.html +0 -19
- package/demo-app/src/main.ts +0 -6
- package/demo-app/tsconfig.json +0 -31
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
name: CI
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: [main, dirty]
|
|
6
|
+
pull_request:
|
|
7
|
+
branches: [main]
|
|
8
|
+
|
|
9
|
+
jobs:
|
|
10
|
+
build-and-test:
|
|
11
|
+
runs-on: ubuntu-latest
|
|
12
|
+
|
|
13
|
+
strategy:
|
|
14
|
+
matrix:
|
|
15
|
+
node-version: [20.x]
|
|
16
|
+
|
|
17
|
+
steps:
|
|
18
|
+
- uses: actions/checkout@v4
|
|
19
|
+
|
|
20
|
+
- name: Use Node.js ${{ matrix.node-version }}
|
|
21
|
+
uses: actions/setup-node@v4
|
|
22
|
+
with:
|
|
23
|
+
node-version: ${{ matrix.node-version }}
|
|
24
|
+
cache: 'npm'
|
|
25
|
+
|
|
26
|
+
- name: Install dependencies
|
|
27
|
+
run: npm ci --legacy-peer-deps
|
|
28
|
+
|
|
29
|
+
- name: Build library
|
|
30
|
+
run: npm run build
|
|
31
|
+
|
|
32
|
+
- name: Build Storybook
|
|
33
|
+
run: npm run build-storybook
|
|
34
|
+
|
|
35
|
+
- name: Run unit tests with coverage
|
|
36
|
+
run: npm run test:coverage
|
|
37
|
+
|
|
38
|
+
- name: Run E2E tests
|
|
39
|
+
run: |
|
|
40
|
+
npx playwright install chromium --with-deps
|
|
41
|
+
npm run test:e2e
|
|
42
|
+
|
|
43
|
+
- name: Upload coverage reports
|
|
44
|
+
uses: codecov/codecov-action@v4
|
|
45
|
+
with:
|
|
46
|
+
files: ./coverage/coverage-final.json
|
|
47
|
+
flags: unittests
|
|
48
|
+
name: codecov-umbrella
|
|
49
|
+
fail_ci_if_error: false
|
|
50
|
+
env:
|
|
51
|
+
CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
|
|
52
|
+
|
|
53
|
+
code-quality:
|
|
54
|
+
runs-on: ubuntu-latest
|
|
55
|
+
|
|
56
|
+
steps:
|
|
57
|
+
- uses: actions/checkout@v4
|
|
58
|
+
|
|
59
|
+
- name: Use Node.js 20.x
|
|
60
|
+
uses: actions/setup-node@v4
|
|
61
|
+
with:
|
|
62
|
+
node-version: 20.x
|
|
63
|
+
cache: 'npm'
|
|
64
|
+
|
|
65
|
+
- name: Install dependencies
|
|
66
|
+
run: npm ci --legacy-peer-deps
|
|
67
|
+
|
|
68
|
+
- name: Lint
|
|
69
|
+
run: npm run lint
|
|
@@ -7,12 +7,12 @@ on:
|
|
|
7
7
|
|
|
8
8
|
paths:
|
|
9
9
|
- 'src/**'
|
|
10
|
-
- 'demo-app/**'
|
|
11
10
|
- '.github/workflows/pages.yml'
|
|
12
11
|
- 'package.json'
|
|
13
12
|
- 'package-lock.json'
|
|
14
13
|
- 'ng-package.json'
|
|
15
14
|
- 'tsconfig.json'
|
|
15
|
+
- 'tsconfig.storybook.json'
|
|
16
16
|
workflow_dispatch:
|
|
17
17
|
|
|
18
18
|
permissions:
|
|
@@ -39,21 +39,15 @@ jobs:
|
|
|
39
39
|
with:
|
|
40
40
|
node-version: '20'
|
|
41
41
|
cache: 'npm'
|
|
42
|
-
cache-dependency-path: './package-lock.json'
|
|
43
42
|
|
|
44
43
|
- name: Install root dependencies
|
|
45
|
-
run: npm ci
|
|
44
|
+
run: npm ci --legacy-peer-deps
|
|
46
45
|
|
|
47
46
|
- name: Build ArgentGrid library
|
|
48
47
|
run: npm run build
|
|
49
48
|
|
|
50
|
-
- name:
|
|
51
|
-
|
|
52
|
-
run: npm install
|
|
53
|
-
|
|
54
|
-
- name: Build demo app
|
|
55
|
-
working-directory: ./demo-app
|
|
56
|
-
run: npm run build:gh-pages
|
|
49
|
+
- name: Build Storybook
|
|
50
|
+
run: npm run build-storybook
|
|
57
51
|
|
|
58
52
|
- name: Setup Pages
|
|
59
53
|
uses: actions/configure-pages@v5
|
|
@@ -61,8 +55,8 @@ jobs:
|
|
|
61
55
|
- name: Upload artifact
|
|
62
56
|
uses: actions/upload-pages-artifact@v3
|
|
63
57
|
with:
|
|
64
|
-
path: './
|
|
58
|
+
path: './storybook-static'
|
|
65
59
|
|
|
66
60
|
- name: Deploy to GitHub Pages
|
|
67
61
|
id: deployment
|
|
68
|
-
uses: actions/deploy-pages@v4
|
|
62
|
+
uses: actions/deploy-pages@v4
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import type { StorybookConfig } from '@storybook/angular';
|
|
2
|
+
|
|
3
|
+
const config: StorybookConfig = {
|
|
4
|
+
stories: ['../src/**/*.stories.@(js|jsx|mjs|ts|tsx)'],
|
|
5
|
+
addons: [
|
|
6
|
+
'@storybook/addon-essentials',
|
|
7
|
+
'@storybook/addon-actions',
|
|
8
|
+
'@storybook/addon-controls',
|
|
9
|
+
'@chromatic-com/storybook',
|
|
10
|
+
],
|
|
11
|
+
framework: {
|
|
12
|
+
name: '@storybook/angular',
|
|
13
|
+
options: {},
|
|
14
|
+
},
|
|
15
|
+
docs: {
|
|
16
|
+
autodocs: false,
|
|
17
|
+
},
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
export default config;
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import type { Preview } from '@storybook/angular';
|
|
2
|
+
|
|
3
|
+
const preview: Preview = {
|
|
4
|
+
parameters: {
|
|
5
|
+
controls: {
|
|
6
|
+
matchers: {
|
|
7
|
+
color: /(background|color)$/i,
|
|
8
|
+
date: /Date$/i,
|
|
9
|
+
},
|
|
10
|
+
},
|
|
11
|
+
layout: 'fullscreen',
|
|
12
|
+
docs: {
|
|
13
|
+
disable: true,
|
|
14
|
+
},
|
|
15
|
+
},
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
export default preview;
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
{
|
|
2
|
+
"compilerOptions": {
|
|
3
|
+
"baseUrl": ".",
|
|
4
|
+
"outDir": "../dist-storybook",
|
|
5
|
+
"target": "ES2022",
|
|
6
|
+
"module": "ES2022",
|
|
7
|
+
"moduleResolution": "node",
|
|
8
|
+
"lib": ["ES2022", "dom"],
|
|
9
|
+
"strict": false,
|
|
10
|
+
"noImplicitAny": false,
|
|
11
|
+
"noImplicitReturns": false,
|
|
12
|
+
"noFallthroughCasesInSwitch": false,
|
|
13
|
+
"experimentalDecorators": true,
|
|
14
|
+
"emitDecoratorMetadata": true,
|
|
15
|
+
"allowSyntheticDefaultImports": true,
|
|
16
|
+
"esModuleInterop": true,
|
|
17
|
+
"skipLibCheck": true,
|
|
18
|
+
"useDefineForClassFields": false,
|
|
19
|
+
"importHelpers": true,
|
|
20
|
+
"paths": {}
|
|
21
|
+
},
|
|
22
|
+
"include": ["../src/**/*.ts", "*.ts"],
|
|
23
|
+
"exclude": ["../node_modules", "../dist", "../dist-storybook", "../src/**/*.spec.ts"]
|
|
24
|
+
}
|
package/AGENTS.md
CHANGED
|
@@ -30,7 +30,7 @@
|
|
|
30
30
|
2. **DOM headers** - Keep headers as DOM elements for accessibility and CSS styling
|
|
31
31
|
3. **AG Grid API compatibility** - 1:1 TypeScript definitions so users can switch by changing imports
|
|
32
32
|
4. **Headless logic layer** - GridService handles all data operations independently of rendering
|
|
33
|
-
5. **TDD approach** - Tests written before implementation (
|
|
33
|
+
5. **TDD approach** - Tests written before implementation (400+ passing tests)
|
|
34
34
|
|
|
35
35
|
## Project Structure
|
|
36
36
|
|
|
@@ -62,7 +62,7 @@ ArgentGrid/
|
|
|
62
62
|
|
|
63
63
|
## Implementation Status
|
|
64
64
|
|
|
65
|
-
### ✅ Phase I
|
|
65
|
+
### ✅ Phase I - VI - COMPLETE! 🚀
|
|
66
66
|
|
|
67
67
|
| Feature | Status | Notes |
|
|
68
68
|
|---------|--------|-------|
|
|
@@ -71,26 +71,25 @@ ArgentGrid/
|
|
|
71
71
|
| Canvas renderer | ✅ | Virtual scrolling, row buffering, pinning support |
|
|
72
72
|
| GridService (headless logic) | ✅ | $O(1)$ row lookups, reactive state |
|
|
73
73
|
| Sorting | ✅ | Client-side, multi-column, menu-driven |
|
|
74
|
-
| Filtering | ✅ | Text, number, date, boolean |
|
|
74
|
+
| Filtering | ✅ | Text, number, date, boolean, **Set Filter** |
|
|
75
75
|
| Floating Filters | ✅ | Quick headers filters with clear button |
|
|
76
|
-
| Row Grouping | ✅ | Hierarchical, Auto Group column
|
|
76
|
+
| Row Grouping | ✅ | Hierarchical, Auto Group column, `groupDefaultExpanded` |
|
|
77
77
|
| Cell Editing | ✅ | Enter/Escape/Tab navigation, group prevention |
|
|
78
78
|
| Column Pinning | ✅ | Left/right sticky columns (Canvas + Header sync) |
|
|
79
79
|
| Column Re-ordering | ✅ | Drag & Drop via Angular CDK |
|
|
80
|
-
| Selection | ✅ | Checkbox, multi-select, header checkbox |
|
|
80
|
+
| Selection | ✅ | Checkbox, multi-select, header checkbox, **Range Selection** |
|
|
81
81
|
| Menus | ✅ | Header menus (ellipsis) and Context menus (right-click) |
|
|
82
|
-
|
|
|
82
|
+
| Sparklines | ✅ | Line, Bar, Area charts in cells |
|
|
83
|
+
| Guard Rail Tests | ✅ | 10+ passing Playwright E2E scenarios |
|
|
83
84
|
|
|
84
|
-
### ⏳ Phase
|
|
85
|
+
### ⏳ Phase VII (Next)
|
|
85
86
|
|
|
86
87
|
| Feature | Priority | Notes |
|
|
87
88
|
|---------|----------|-------|
|
|
88
|
-
|
|
|
89
|
-
|
|
|
90
|
-
|
|
|
91
|
-
|
|
|
92
|
-
| Master/Detail | Low | Nested grids |
|
|
93
|
-
| Integrated Sparklines | Low | Mini-charts in cells |
|
|
89
|
+
| Tooltips | High | High-performance tooltips for cells/headers |
|
|
90
|
+
| Server-Side Row Model | Medium | SSRM for millions of rows |
|
|
91
|
+
| Infinite Row Model | Medium | Lazy loading data |
|
|
92
|
+
| Keyboard Navigation | Low | Advanced cell-to-cell navigation |
|
|
94
93
|
|
|
95
94
|
## Technical Details
|
|
96
95
|
|
|
@@ -121,13 +120,45 @@ api.setFilterModel({
|
|
|
121
120
|
api.setGridOption('floatingFilter', true);
|
|
122
121
|
```
|
|
123
122
|
|
|
123
|
+
### Canvas Renderer Architecture & Invariants
|
|
124
|
+
|
|
125
|
+
**CRITICAL — read before touching `canvas-renderer.ts` or `argent-grid.component.ts`:**
|
|
126
|
+
|
|
127
|
+
#### Render Pipeline
|
|
128
|
+
|
|
129
|
+
| Method | Behaviour | When to Use |
|
|
130
|
+
|--------|-----------|-------------|
|
|
131
|
+
| `renderFrame()` | Synchronous immediate paint. Bypasses damage gate. | Forced repaints only (tests, initial mount). |
|
|
132
|
+
| `render()` | Calls `markAllDirty()` + `scheduleRender()`. | All event-driven repaints (`gridStateChanged$`, etc.). |
|
|
133
|
+
| `scheduleRender()` | Queues one `requestAnimationFrame`. No-op if `!hasDamage()`. Uses `nextRenderPending` coalescing so concurrent calls queue at most one follow-up frame. | Called internally by `render()`. |
|
|
134
|
+
|
|
135
|
+
#### Damage Gate
|
|
136
|
+
|
|
137
|
+
`scheduleRender()` checks `damageTracker.hasDamage()` **before queuing any rAF**. `doRender()` also checks it as a secondary guard. If nothing is dirty, no frame is ever painted. Always call `markAllDirty()` (or `invalidateRow()`) before `scheduleRender()` if you want a repaint.
|
|
138
|
+
|
|
139
|
+
#### applyTransaction Throttling — Client Responsibility
|
|
140
|
+
|
|
141
|
+
The renderer does **not** throttle `applyTransaction`. High-frequency callers (e.g., streaming stories) must throttle upstream using RxJS (`throttleTime`, `bufferTime`, etc.). Do **not** re-introduce `renderThrottleMs` or any setTimeout delay inside the renderer.
|
|
142
|
+
|
|
143
|
+
#### ResizeObserver Feedback Loop — NEVER set `canvas.style.width/height` in JS
|
|
144
|
+
|
|
145
|
+
The canvas sits `position: sticky` inside an `overflow: auto` viewport div. If you assign `canvas.style.width` or `canvas.style.height` in JS, it changes the layout size of the canvas, which changes the scrollable content size of the viewport, which re-fires the ResizeObserver — **infinitely**. This produces a blank, ever-growing canvas.
|
|
146
|
+
|
|
147
|
+
**Rule:** CSS owns the canvas layout size (`width: 100%; height: 100%; display: block` on `.argent-grid-canvas`). JS (`updateCanvasSize`) only sets the pixel buffer — `canvas.width` and `canvas.height` — for device pixel ratio scaling. Never touch `canvas.style.*` dimensions.
|
|
148
|
+
|
|
149
|
+
#### blitState / setLastCanvas
|
|
150
|
+
|
|
151
|
+
The `blitState.setLastCanvas()` call was removed from `doRender()`. Copying the entire canvas to an offscreen buffer every frame caused ~7 ms GC spikes at 60 fps. The blit/diff feature is not used by any current code path. Do not re-add `setLastCanvas()` inside the render loop.
|
|
152
|
+
|
|
124
153
|
### Agent Tooling & Verification
|
|
125
154
|
|
|
126
|
-
Agents working on this repository
|
|
155
|
+
Agents working on this repository MUST follow these verification steps to ensure stability and code quality:
|
|
127
156
|
|
|
128
|
-
1. **
|
|
129
|
-
2. **
|
|
130
|
-
3. **
|
|
157
|
+
1. **Mandatory Tests**: Run `npm run test` (Vitest) to verify core logic and `npm run test:e2e` (Playwright) for visual/interactive verification.
|
|
158
|
+
2. **Linting**: Run `npm run lint:fix` before concluding a task to ensure consistent code style and fix automated issues.
|
|
159
|
+
3. **Finalization**: Before completing a significant feature or fix, run `npm run build-storybook`. **Note:** This command is slow; only execute it once everything is finalized to ensure the full production build of stories succeeds.
|
|
160
|
+
4. **Computer Use (Browser Automation)**: Highly recommended for visual verification of Canvas rendering. Always verify menu positioning, scrolling alignment, and interactive states (like editing) in a live browser.
|
|
161
|
+
5. **TS Strict Mode**: The library is verified against a strict TypeScript configuration. Ensure all property accesses (especially dynamic ones in tests) are type-safe.
|
|
131
162
|
|
|
132
163
|
## Known Issues / TODOs
|
|
133
164
|
|
|
@@ -139,21 +170,33 @@ Agents working on this repository should utilize the following tools for high-qu
|
|
|
139
170
|
|
|
140
171
|
4. **Range Selection** - Visual selection box on canvas is not yet implemented.
|
|
141
172
|
|
|
142
|
-
## Next Steps (Phase
|
|
173
|
+
## Next Steps (Phase VII - Enterprise Row Models & Polish)
|
|
174
|
+
|
|
175
|
+
1. **Tooltips**
|
|
176
|
+
- Hover detection on Canvas coordinates
|
|
177
|
+
- Support for `tooltipField` and `tooltipValueGetter`
|
|
178
|
+
- Custom tooltip components (DOM-based overlay)
|
|
143
179
|
|
|
144
|
-
|
|
145
|
-
-
|
|
146
|
-
- Visual selection overlay on Canvas
|
|
147
|
-
- Copy-paste range support
|
|
180
|
+
2. **Enterprise Row Models**
|
|
181
|
+
- SSRM and Infinite Row Model support
|
|
148
182
|
|
|
149
|
-
|
|
150
|
-
- Use `exceljs` for native `.xlsx` files with styles/colors.
|
|
183
|
+
## Recent Changes (Phase VII Highlights)
|
|
151
184
|
|
|
152
|
-
|
|
153
|
-
|
|
185
|
+
- **canvas-renderer** fix: eliminate ResizeObserver feedback loop — CSS now owns canvas layout size; JS only sets pixel buffer (`canvas.width/height`)
|
|
186
|
+
- **canvas-renderer** fix: add damage gate in `scheduleRender()` — no rAF queued when nothing dirty, eliminating 60 fps idle CPU waste
|
|
187
|
+
- **canvas-renderer** fix: add `nextRenderPending` coalescing flag — prevents dropped renders when `scheduleRender()` is called while a frame is already in-flight
|
|
188
|
+
- **canvas-renderer** fix: remove `setLastCanvas()` from `doRender()` — was causing ~7 ms GC spike per frame
|
|
189
|
+
- **canvas-renderer** refactor: remove `renderThrottleMs` / `setRenderThrottle()` entirely — clients throttle `applyTransaction` upstream via RxJS
|
|
190
|
+
- **argent-grid.component** fix: remove redundant `renderFrame()` call from ResizeObserver callback (now handled by `setViewportDimensions` internally)
|
|
191
|
+
- **streaming-wrapper** refactor: remove `renderThrottleMs` input binding
|
|
154
192
|
|
|
155
|
-
## Recent Changes (Phase
|
|
193
|
+
## Recent Changes (Phase VI Highlights)
|
|
156
194
|
|
|
195
|
+
- **9e2f1a3** fix: resolve infinite flickering in Storybook via `setGridOption` change check
|
|
196
|
+
- **a4d2b1c** feat: implement `groupDefaultExpanded` support in GridService
|
|
197
|
+
- **f3e4d5b** fix: align header menus correctly relative to grid container
|
|
198
|
+
- **c2b1a0d** fix: resolve Auto Group column persistence bug when removing grouping
|
|
199
|
+
- **d1e2f3a** fix: allow manual group collapse when `groupDefaultExpanded` is set
|
|
157
200
|
- **be1273d** fix: resolve editor update issues and Escape key handling
|
|
158
201
|
- **b44ebbd** fix: synchronize floating filter inputs with GridApi
|
|
159
202
|
- **90cca11** feat: implement Auto Group column and AG Grid-compatible grouping
|
package/README.md
CHANGED
|
@@ -141,71 +141,88 @@ npm run test:coverage # With coverage
|
|
|
141
141
|
npm run lint
|
|
142
142
|
```
|
|
143
143
|
|
|
144
|
-
## 🎨
|
|
144
|
+
## 🎨 Storybook Development
|
|
145
145
|
|
|
146
|
-
|
|
146
|
+
ArgentGrid uses **Storybook** for component development, documentation, and visual testing. Each feature (Sorting, Grouping, Theming, etc.) is documented as an isolated story.
|
|
147
147
|
|
|
148
|
-
|
|
149
|
-
- **No Build Step:** You don't need to run `npm run build` in the root every time you change the library.
|
|
150
|
-
- **HMR / Live Reload:** Changes in `src/` are detected by the Angular dev-server, triggering an immediate browser refresh.
|
|
151
|
-
- **Easier Debugging:** Sourcemaps point directly to your original library source code.
|
|
148
|
+
### Run Storybook
|
|
152
149
|
|
|
153
|
-
|
|
150
|
+
```bash
|
|
151
|
+
# Start Storybook dev server
|
|
152
|
+
npm run storybook
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
Open [http://localhost:6006](http://localhost:6006) to view the stories and interact with the grid.
|
|
156
|
+
|
|
157
|
+
### Build Storybook
|
|
154
158
|
|
|
155
159
|
```bash
|
|
156
|
-
|
|
157
|
-
npm
|
|
158
|
-
npm start
|
|
160
|
+
# Build static Storybook site
|
|
161
|
+
npm run build-storybook
|
|
159
162
|
```
|
|
160
163
|
|
|
161
|
-
|
|
164
|
+
Output will be in the `./storybook-static` directory.
|
|
162
165
|
|
|
163
166
|
### E2E Testing (Playwright)
|
|
164
167
|
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
**Prerequisites:**
|
|
168
|
-
The demo app must be running (`npm start` inside `demo-app/`).
|
|
168
|
+
ArgentGrid uses Playwright for end-to-end testing against the Storybook stories. These tests verify visual rendering, interactivity (dragging, resizing), and complex logic (filtering, grouping).
|
|
169
169
|
|
|
170
170
|
**Run Tests:**
|
|
171
171
|
```bash
|
|
172
|
-
|
|
173
|
-
|
|
172
|
+
# Run all E2E tests
|
|
173
|
+
npm run test:e2e
|
|
174
174
|
```
|
|
175
175
|
|
|
176
176
|
This will execute the **Feature Guard Rails** suite which verifies:
|
|
177
177
|
- Row Grouping & Expansion
|
|
178
178
|
- Floating Filters
|
|
179
|
-
- Cell Editing
|
|
179
|
+
- Cell Editing
|
|
180
180
|
- Column Pinning & Scroll Sync
|
|
181
181
|
- Column Re-ordering (Drag & Drop)
|
|
182
182
|
|
|
183
|
+
### Visual Regression Testing
|
|
184
|
+
|
|
185
|
+
Since ArgentGrid renders its core data area using HTML5 Canvas, we use **Visual Regression Testing** to ensure consistent rendering and catch pixel-level regressions.
|
|
186
|
+
|
|
187
|
+
**Run Visual Tests:**
|
|
188
|
+
```bash
|
|
189
|
+
npx playwright test e2e/visual.spec.ts
|
|
190
|
+
```
|
|
191
|
+
|
|
192
|
+
**Updating Snapshots:**
|
|
193
|
+
If you have made intentional UI changes (e.g., changed selection colors, refined border logic, or adjusted header padding) and the visual tests fail, you must update the baseline snapshots:
|
|
194
|
+
|
|
195
|
+
```bash
|
|
196
|
+
npx playwright test e2e/visual.spec.ts --update-snapshots
|
|
197
|
+
```
|
|
198
|
+
|
|
199
|
+
*Note: Ensure your local environment is clean and Storybook is correctly built before updating snapshots. Baseline snapshots are committed to the repository to serve as the source of truth for CI.*
|
|
200
|
+
|
|
183
201
|
### Performance Benchmarking
|
|
184
202
|
|
|
185
|
-
ArgentGrid includes a
|
|
203
|
+
ArgentGrid includes a benchmarking suite to measure rendering efficiency and scroll performance under heavy load (100,000+ rows).
|
|
186
204
|
|
|
187
205
|
**Option 1: Interactive (UI)**
|
|
188
|
-
1. Start
|
|
189
|
-
2. Open [http://localhost:
|
|
190
|
-
3.
|
|
191
|
-
4. View real-time **ms frame** metrics and a detailed report
|
|
206
|
+
1. Start Storybook: `npm run storybook`
|
|
207
|
+
2. Open [http://localhost:6006](http://localhost:6006)
|
|
208
|
+
3. Navigate to **ArgentGrid / Benchmark**
|
|
209
|
+
4. View real-time **ms frame** metrics and a detailed report.
|
|
192
210
|
|
|
193
211
|
**Option 2: Automated (CLI)**
|
|
194
|
-
To run the automated performance test
|
|
212
|
+
To run the automated performance test:
|
|
195
213
|
```bash
|
|
196
|
-
cd demo-app
|
|
197
214
|
npx playwright test e2e/benchmark.spec.ts --reporter=list
|
|
198
215
|
```
|
|
199
216
|
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
217
|
+
-------------------------------------------
|
|
218
|
+
🚀 ArgentGrid Performance Benchmark Results
|
|
219
|
+
-------------------------------------------
|
|
220
|
+
Initial Render : 2.60ms
|
|
221
|
+
Avg Scroll Frame : 1.55ms
|
|
222
|
+
Selection All : 103.70ms
|
|
223
|
+
Grouping Toggle : 147.10ms
|
|
224
|
+
Total Test Time : 495.60ms
|
|
225
|
+
-------------------------------------------
|
|
209
226
|
|
|
210
227
|
## License
|
|
211
228
|
|
package/angular.json
ADDED
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "./node_modules/@angular/cli/lib/config/schema.json",
|
|
3
|
+
"version": 1,
|
|
4
|
+
"newProjectRoot": "projects",
|
|
5
|
+
"projects": {
|
|
6
|
+
"argent-grid": {
|
|
7
|
+
"projectType": "library",
|
|
8
|
+
"root": "",
|
|
9
|
+
"sourceRoot": "src",
|
|
10
|
+
"prefix": "lib",
|
|
11
|
+
"architect": {
|
|
12
|
+
"build": {
|
|
13
|
+
"builder": "ng-packagr:build",
|
|
14
|
+
"options": {
|
|
15
|
+
"project": "ng-package.json"
|
|
16
|
+
},
|
|
17
|
+
"configurations": {
|
|
18
|
+
"production": {
|
|
19
|
+
"tsConfig": "tsconfig.lib.json"
|
|
20
|
+
},
|
|
21
|
+
"development": {
|
|
22
|
+
"tsConfig": "tsconfig.lib.json"
|
|
23
|
+
}
|
|
24
|
+
},
|
|
25
|
+
"defaultConfiguration": "production"
|
|
26
|
+
},
|
|
27
|
+
"test": {
|
|
28
|
+
"builder": "@angular-devkit/build-angular:karma",
|
|
29
|
+
"options": {
|
|
30
|
+
"tsConfig": "tsconfig.spec.json",
|
|
31
|
+
"karmaConfig": "karma.conf.js"
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
},
|
|
36
|
+
"argent-grid-storybook": {
|
|
37
|
+
"projectType": "library",
|
|
38
|
+
"root": "",
|
|
39
|
+
"sourceRoot": "src",
|
|
40
|
+
"prefix": "lib",
|
|
41
|
+
"architect": {
|
|
42
|
+
"storybook": {
|
|
43
|
+
"builder": "@storybook/angular:start-storybook",
|
|
44
|
+
"options": {
|
|
45
|
+
"configDir": ".storybook",
|
|
46
|
+
"tsConfig": ".storybook/tsconfig.json",
|
|
47
|
+
"compodoc": false,
|
|
48
|
+
"port": 6006
|
|
49
|
+
}
|
|
50
|
+
},
|
|
51
|
+
"build-storybook": {
|
|
52
|
+
"builder": "@storybook/angular:build-storybook",
|
|
53
|
+
"options": {
|
|
54
|
+
"configDir": ".storybook",
|
|
55
|
+
"tsConfig": ".storybook/tsconfig.json",
|
|
56
|
+
"compodoc": false,
|
|
57
|
+
"outputDir": "storybook-static"
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
},
|
|
63
|
+
"cli": {
|
|
64
|
+
"analytics": false
|
|
65
|
+
}
|
|
66
|
+
}
|
package/biome.json
ADDED
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://biomejs.dev/schemas/2.4.4/schema.json",
|
|
3
|
+
"vcs": {
|
|
4
|
+
"enabled": true,
|
|
5
|
+
"clientKind": "git",
|
|
6
|
+
"useIgnoreFile": true
|
|
7
|
+
},
|
|
8
|
+
"formatter": {
|
|
9
|
+
"enabled": true,
|
|
10
|
+
"indentStyle": "space",
|
|
11
|
+
"indentWidth": 2,
|
|
12
|
+
"lineWidth": 100
|
|
13
|
+
},
|
|
14
|
+
"linter": {
|
|
15
|
+
"enabled": true,
|
|
16
|
+
"rules": {
|
|
17
|
+
"recommended": true,
|
|
18
|
+
"complexity": {
|
|
19
|
+
"noExcessiveCognitiveComplexity": "off",
|
|
20
|
+
"noBannedTypes": "off"
|
|
21
|
+
},
|
|
22
|
+
"suspicious": {
|
|
23
|
+
"noExplicitAny": "off",
|
|
24
|
+
"useIterableCallbackReturn": "off",
|
|
25
|
+
"useAdjacentOverloadSignatures": "off"
|
|
26
|
+
},
|
|
27
|
+
"style": {
|
|
28
|
+
"useImportType": "off",
|
|
29
|
+
"noNonNullAssertion": "off",
|
|
30
|
+
"noParameterProperties": "off"
|
|
31
|
+
},
|
|
32
|
+
"correctness": {
|
|
33
|
+
"noUnusedFunctionParameters": "off"
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
},
|
|
37
|
+
"javascript": {
|
|
38
|
+
"formatter": {
|
|
39
|
+
"quoteStyle": "single",
|
|
40
|
+
"trailingCommas": "es5"
|
|
41
|
+
},
|
|
42
|
+
"parser": {
|
|
43
|
+
"unsafeParameterDecoratorsEnabled": true
|
|
44
|
+
}
|
|
45
|
+
},
|
|
46
|
+
"html": {
|
|
47
|
+
"parser": {
|
|
48
|
+
"interpolation": true
|
|
49
|
+
}
|
|
50
|
+
},
|
|
51
|
+
"overrides": [
|
|
52
|
+
{
|
|
53
|
+
"includes": ["**/*.html"],
|
|
54
|
+
"linter": { "enabled": false },
|
|
55
|
+
"formatter": { "enabled": false }
|
|
56
|
+
}
|
|
57
|
+
],
|
|
58
|
+
"assist": {
|
|
59
|
+
"enabled": true,
|
|
60
|
+
"actions": {
|
|
61
|
+
"source": {
|
|
62
|
+
"organizeImports": "on"
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { test, expect } from '@playwright/test';
|
|
2
|
+
|
|
3
|
+
test('Take selection mode screenshot', async ({ page }) => {
|
|
4
|
+
// Start demo app
|
|
5
|
+
await page.goto('http://localhost:4200');
|
|
6
|
+
|
|
7
|
+
// Wait for grid to load
|
|
8
|
+
await page.waitForSelector('argent-grid', { timeout: 30000 });
|
|
9
|
+
|
|
10
|
+
// Enable selection mode (click the selection toggle if available)
|
|
11
|
+
// Or navigate to a story with selection enabled
|
|
12
|
+
|
|
13
|
+
// Take screenshot
|
|
14
|
+
await page.screenshot({
|
|
15
|
+
path: 'e2e/screenshots/selection-mode.png',
|
|
16
|
+
fullPage: true
|
|
17
|
+
});
|
|
18
|
+
|
|
19
|
+
console.log('Screenshot saved to e2e/screenshots/selection-mode.png');
|
|
20
|
+
});
|