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.
Files changed (122) hide show
  1. package/.github/workflows/ci.yml +69 -0
  2. package/.github/workflows/pages.yml +6 -12
  3. package/.storybook/main.ts +20 -0
  4. package/.storybook/preview.ts +18 -0
  5. package/.storybook/tsconfig.json +24 -0
  6. package/AGENTS.md +70 -27
  7. package/README.md +51 -34
  8. package/angular.json +66 -0
  9. package/biome.json +66 -0
  10. package/demo-app/e2e/selection-screenshot.spec.ts +20 -0
  11. package/docs/AG-GRID-COMPARISON.md +725 -0
  12. package/docs/CELL-RENDERER-GUIDE.md +241 -0
  13. package/docs/CONTEXT-MENU-GUIDE.md +371 -0
  14. package/docs/LIVE-DATA-OPTIMIZATIONS.md +497 -0
  15. package/docs/PERFORMANCE-OPTIMIZATIONS-PHASE1.md +162 -0
  16. package/docs/PERFORMANCE-REVIEW.md +571 -0
  17. package/docs/RESEARCH-STATUS.md +234 -0
  18. package/docs/STATE-PERSISTENCE-GUIDE.md +370 -0
  19. package/docs/STORYBOOK-REFACTOR.md +215 -0
  20. package/docs/STORYBOOK-STATUS.md +156 -0
  21. package/docs/TEST-COVERAGE-REPORT.md +276 -0
  22. package/docs/THEME-API-GUIDE.md +445 -0
  23. package/docs/THEME-API-PLAN.md +364 -0
  24. package/e2e/advanced.spec.ts +109 -0
  25. package/e2e/argentgrid.spec.ts +65 -0
  26. package/e2e/benchmark.spec.ts +52 -0
  27. package/e2e/cell-renderers.spec.ts +152 -0
  28. package/e2e/debug-streaming.spec.ts +31 -0
  29. package/e2e/dnd.spec.ts +73 -0
  30. package/e2e/screenshots.spec.ts +52 -0
  31. package/e2e/theming.spec.ts +35 -0
  32. package/e2e/visual.spec.ts +112 -0
  33. package/e2e/visual.spec.ts-snapshots/checkbox-renderer-mixed.png +0 -0
  34. package/e2e/visual.spec.ts-snapshots/debug.png +0 -0
  35. package/e2e/visual.spec.ts-snapshots/grid-column-group-headers.png +0 -0
  36. package/e2e/visual.spec.ts-snapshots/grid-default.png +0 -0
  37. package/e2e/visual.spec.ts-snapshots/grid-empty-state.png +0 -0
  38. package/e2e/visual.spec.ts-snapshots/grid-filter-popup.png +0 -0
  39. package/e2e/visual.spec.ts-snapshots/grid-scroll-borders.png +0 -0
  40. package/e2e/visual.spec.ts-snapshots/grid-sidebar-buttons.png +0 -0
  41. package/e2e/visual.spec.ts-snapshots/grid-text-filter.png +0 -0
  42. package/e2e/visual.spec.ts-snapshots/grid-with-selection.png +0 -0
  43. package/e2e/visual.spec.ts-snapshots/rating-renderer-varied.png +0 -0
  44. package/package.json +21 -7
  45. package/plan.md +56 -28
  46. package/playwright.config.ts +38 -0
  47. package/setup-vitest.ts +10 -13
  48. package/src/lib/argent-grid.module.ts +10 -12
  49. package/src/lib/components/argent-grid.component.css +281 -321
  50. package/src/lib/components/argent-grid.component.html +295 -207
  51. package/src/lib/components/argent-grid.component.spec.ts +120 -160
  52. package/src/lib/components/argent-grid.component.ts +1193 -290
  53. package/src/lib/components/argent-grid.regressions.spec.ts +301 -0
  54. package/src/lib/components/argent-grid.selection.spec.ts +132 -0
  55. package/src/lib/components/set-filter/set-filter.component.spec.ts +191 -0
  56. package/src/lib/components/set-filter/set-filter.component.ts +307 -0
  57. package/src/lib/directives/ag-grid-compatibility.directive.ts +16 -26
  58. package/src/lib/directives/click-outside.directive.ts +19 -0
  59. package/src/lib/rendering/canvas-renderer.spec.ts +513 -0
  60. package/src/lib/rendering/canvas-renderer.ts +456 -452
  61. package/src/lib/rendering/live-data-handler.ts +110 -0
  62. package/src/lib/rendering/live-data-optimizations.ts +133 -0
  63. package/src/lib/rendering/render/blit.spec.ts +16 -27
  64. package/src/lib/rendering/render/blit.ts +48 -36
  65. package/src/lib/rendering/render/cells.spec.ts +132 -0
  66. package/src/lib/rendering/render/cells.ts +167 -28
  67. package/src/lib/rendering/render/column-utils.ts +95 -0
  68. package/src/lib/rendering/render/hit-test.ts +50 -0
  69. package/src/lib/rendering/render/index.ts +88 -76
  70. package/src/lib/rendering/render/lines.ts +53 -47
  71. package/src/lib/rendering/render/primitives.ts +423 -0
  72. package/src/lib/rendering/render/theme.spec.ts +8 -12
  73. package/src/lib/rendering/render/theme.ts +7 -10
  74. package/src/lib/rendering/render/types.ts +3 -2
  75. package/src/lib/rendering/render/walk.spec.ts +35 -38
  76. package/src/lib/rendering/render/walk.ts +94 -64
  77. package/src/lib/rendering/utils/damage-tracker.spec.ts +8 -7
  78. package/src/lib/rendering/utils/damage-tracker.ts +6 -18
  79. package/src/lib/rendering/utils/index.ts +1 -1
  80. package/src/lib/services/grid.service.set-filter.spec.ts +219 -0
  81. package/src/lib/services/grid.service.spec.ts +1241 -201
  82. package/src/lib/services/grid.service.ts +1204 -235
  83. package/src/lib/themes/parts/color-schemes.ts +132 -0
  84. package/src/lib/themes/parts/icon-sets.ts +258 -0
  85. package/src/lib/themes/theme-builder.ts +347 -0
  86. package/src/lib/themes/theme-quartz.ts +72 -0
  87. package/src/lib/themes/types.ts +238 -0
  88. package/src/lib/types/ag-grid-types.ts +573 -14
  89. package/src/public-api.ts +39 -9
  90. package/src/stories/Advanced.stories.ts +249 -0
  91. package/src/stories/ArgentGrid.stories.ts +301 -0
  92. package/src/stories/Benchmark.stories.ts +76 -0
  93. package/src/stories/CellRenderers.stories.ts +395 -0
  94. package/src/stories/Filtering.stories.ts +292 -0
  95. package/src/stories/Grouping.stories.ts +290 -0
  96. package/src/stories/Streaming.stories.ts +57 -0
  97. package/src/stories/Theming.stories.ts +137 -0
  98. package/src/stories/Tooltips.stories.ts +381 -0
  99. package/src/stories/benchmark-wrapper.component.ts +355 -0
  100. package/src/stories/story-utils.ts +88 -0
  101. package/src/stories/streaming-wrapper.component.ts +441 -0
  102. package/tsconfig.json +1 -0
  103. package/tsconfig.storybook.json +10 -0
  104. package/vitest.config.ts +9 -9
  105. package/demo-app/README.md +0 -70
  106. package/demo-app/angular.json +0 -78
  107. package/demo-app/e2e/benchmark.spec.ts +0 -53
  108. package/demo-app/e2e/demo-page.spec.ts +0 -77
  109. package/demo-app/e2e/grid-features.spec.ts +0 -269
  110. package/demo-app/package-lock.json +0 -14023
  111. package/demo-app/package.json +0 -36
  112. package/demo-app/playwright-test-menu.js +0 -19
  113. package/demo-app/playwright.config.ts +0 -23
  114. package/demo-app/src/app/app.component.ts +0 -10
  115. package/demo-app/src/app/app.config.ts +0 -13
  116. package/demo-app/src/app/app.routes.ts +0 -7
  117. package/demo-app/src/app/demo-page/demo-page.component.css +0 -313
  118. package/demo-app/src/app/demo-page/demo-page.component.html +0 -124
  119. package/demo-app/src/app/demo-page/demo-page.component.ts +0 -366
  120. package/demo-app/src/index.html +0 -19
  121. package/demo-app/src/main.ts +0 -6
  122. 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: Install demo app dependencies
51
- working-directory: ./demo-app
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: './demo-app/dist/argent-grid-demo/browser'
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 (209 passing tests)
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, II, III & IV - COMPLETE! 🚀
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 support |
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
- | Guard Rail Tests | ✅ | 7+ passing Playwright E2E scenarios |
82
+ | Sparklines | ✅ | Line, Bar, Area charts in cells |
83
+ | Guard Rail Tests | ✅ | 10+ passing Playwright E2E scenarios |
83
84
 
84
- ### ⏳ Phase V (Future)
85
+ ### ⏳ Phase VII (Next)
85
86
 
86
87
  | Feature | Priority | Notes |
87
88
  |---------|----------|-------|
88
- | Excel-like Range Selection | High | Drag-to-select rectangular ranges |
89
- | Column Virtualization | Medium | Horizontal scrolling for 50+ columns |
90
- | Pivot Tables | Low | Complex but powerful |
91
- | Tree Data | Low | Parent/child relationships |
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 should utilize the following tools for high-quality contributions:
155
+ Agents working on this repository MUST follow these verification steps to ensure stability and code quality:
127
156
 
128
- 1. **Playwright Skill**: Used for running the `demo-app` E2E suite (`npm run test:e2e`).
129
- 2. **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 before concluding a task.
130
- 3. **TS Strict Mode**: The library is verified against the `demo-app`'s strict TypeScript configuration. Ensure all property accesses (especially dynamic ones in tests) are type-safe.
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 V - Advanced Analysis)
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
- 1. **Excel-like Range Selection**
145
- - Drag-to-select multiple cells
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
- 2. **Full-featured Excel Export**
150
- - Use `exceljs` for native `.xlsx` files with styles/colors.
183
+ ## Recent Changes (Phase VII Highlights)
151
184
 
152
- 3. **Column Virtualization**
153
- - Only render visible columns in CanvasRenderer.renderColGroup.
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 IV Highlights)
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
- ## 🎨 Demo App Development
144
+ ## 🎨 Storybook Development
145
145
 
146
- The repository includes a standalone Angular application for visual testing and performance benchmarking. It is configured to import `argent-grid` directly from the `src/` folder using TypeScript path mapping.
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
- **Why this is better:**
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
- ### Run Demo App
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
- cd demo-app
157
- npm install
158
- npm start
160
+ # Build static Storybook site
161
+ npm run build-storybook
159
162
  ```
160
163
 
161
- Open [http://localhost:4200](http://localhost:4200) to view the demo.
164
+ Output will be in the `./storybook-static` directory.
162
165
 
163
166
  ### E2E Testing (Playwright)
164
167
 
165
- argent-grid uses Playwright for end-to-end testing of visual and interactive features (like Canvas rendering, dragging, and menu interactions).
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
- cd demo-app
173
- npx playwright test
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 (Enter/Escape/Tab)
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 built-in benchmarking suite to measure rendering efficiency, scroll performance, and memory overhead.
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 the demo app: `cd demo-app && npm start`
189
- 2. Open [http://localhost:4200](http://localhost:4200)
190
- 3. Click the **🚀 Benchmark** button in the header.
191
- 4. View real-time **ms frame** metrics and a detailed report covering initial render, scrolling, and selection updates.
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 and see results in your terminal:
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
- ## Performance Targets
201
-
202
- | Metric | Baseline | Target | Status |
203
- | :--- | :--- | :--- | :--- |
204
- | **Initial Render (100k rows)** | ~45ms | < 30ms | 🚀 (Optimizing) |
205
- | **Scroll Frame Time (avg)** | ~3.8ms | < 4ms | ✅ |
206
- | **Selection Update (All)** | ~12ms | < 20ms | ✅ (Damage Tracking) |
207
- | **Memory per 100k rows** | ~45MB | < 30MB | 🚀 (Optimizing) |
208
- | **Max Rows (60fps)** | 1,000,000+ | 1,000,000+ | ✅ |
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
+ });