From 19c0501568db9c0e64ee06ad603af9fb032b8389 Mon Sep 17 00:00:00 2001 From: Artem Belik Date: Thu, 23 Jul 2026 17:39:13 +0300 Subject: [PATCH 1/3] chore: bump @koobiq/ag-grid-angular-theme to 34.5.1, added new examples (#DS-5312) --- .../stackblitz/stackblitz-writer.ts | 15 +- docs/data-grid/ag-grid/ag-grid.en.md | 26 ++ docs/data-grid/ag-grid/ag-grid.ru.md | 26 ++ package.json | 5 +- packages/components-dev/ag-grid/module.ts | 16 + packages/components-dev/ag-grid/styles.scss | 1 + .../actions-panel-overview-example.ts | 1 - .../ag-grid-column-state-example.ts | 4 +- .../ag-grid-copy-selected-example.ts | 2 - .../ag-grid-export/ag-grid-export-example.ts | 136 ++++++++ .../ag-grid-external-filter-state-example.ts | 2 +- .../ag-grid-filter-state-example.ts | 4 +- .../ag-grid-infinite-selection-example.ts | 82 ++++- .../ag-grid-overview-example.ts | 2 - .../ag-grid-quick-filter-state-example.ts | 2 +- .../ag-grid-row-actions-example.ts | 2 - .../ag-grid-row-dragging-example.ts | 2 - .../ag-grid-row-focus-state-example.ts | 63 ++++ .../ag-grid-row-group-example.ts | 109 +++++++ .../ag-grid-row-selection-state-example.ts | 74 +++++ .../ag-grid-status-bar-example.ts | 2 - .../docs-examples/components/ag-grid/index.ts | 12 + .../content-panel-with-grid-example.ts | 2 - tools/cspell-locales/en.json | 1 + yarn.lock | 302 +++++++++++++++++- 25 files changed, 848 insertions(+), 45 deletions(-) create mode 100644 packages/docs-examples/components/ag-grid/ag-grid-export/ag-grid-export-example.ts create mode 100644 packages/docs-examples/components/ag-grid/ag-grid-row-focus-state/ag-grid-row-focus-state-example.ts create mode 100644 packages/docs-examples/components/ag-grid/ag-grid-row-group/ag-grid-row-group-example.ts create mode 100644 packages/docs-examples/components/ag-grid/ag-grid-row-selection-state/ag-grid-row-selection-state-example.ts diff --git a/apps/docs/src/app/components/stackblitz/stackblitz-writer.ts b/apps/docs/src/app/components/stackblitz/stackblitz-writer.ts index df8de2bbfc..2be0bb7699 100644 --- a/apps/docs/src/app/components/stackblitz/stackblitz-writer.ts +++ b/apps/docs/src/app/components/stackblitz/stackblitz-writer.ts @@ -23,22 +23,25 @@ const TEMPLATE_PATH = 'assets/stackblitz/'; */ const OPTIONAL_PACKAGE_JSON_DEPENDENCIES = { 'country-flag-icons': { - 'country-flag-icons': '^1.6.20' + 'country-flag-icons': '^1' }, '@koobiq/components/markdown': { - marked: '^17.0.3' + marked: '^17' }, '@koobiq/components/input': { - '@maskito/angular': '^5.0.1', - '@maskito/kit': '^5.0.1' + '@maskito/angular': '^5', + '@maskito/kit': '^5' }, '@koobiq/components/code-block': { - 'highlight.js': '^11.11.1' + 'highlight.js': '^11' }, '@koobiq/ag-grid-angular-theme': { '@koobiq/ag-grid-angular-theme': '^34', 'ag-grid-angular': '^34', - 'ag-grid-community': '^34' + 'ag-grid-community': '^34', + jspdf: '^4', + 'jspdf-autotable': '^5', + xlsx: '^0' } } as const; diff --git a/docs/data-grid/ag-grid/ag-grid.en.md b/docs/data-grid/ag-grid/ag-grid.en.md index 3864120217..859361f330 100644 --- a/docs/data-grid/ag-grid/ag-grid.en.md +++ b/docs/data-grid/ag-grid/ag-grid.en.md @@ -54,12 +54,26 @@ The `kbqAgGridRowActions` directive adds an action panel that appears when hover +### Row grouping + +The `kbqAgGridRowGroup` directive implements client-side row grouping. Attach it to `ag-grid-angular`, supply raw data via `[kbqAgGridRowGroupRowData]` instead of `[rowData]`, and set the grouped columns via `[(kbqAgGridRowGroupCols)]`. + +Collapsed/expanded group state and row selection can each be persisted independently by setting `kbqAgGridRowGroupCollapsedState` and `kbqAgGridRowGroupSelectionState` to a unique key, connecting store providers via `kbqAgGridRowGroupCollapsedStateStoreProvider` and `kbqAgGridRowGroupSelectionStateStoreProvider`. + + + ### Copying selected rows The `kbqAgGridCopyByCtrlC` directive allows you to copy selected rows to the clipboard using the `Ctrl+C` keyboard shortcut. +### Export + +The grid's own API can be used to export the currently displayed data (respecting active filters, sorting, and formatters). `api.exportDataAsCsv()` downloads a CSV file with no additional dependencies. Other formats can be built on top of the grid's cell values using third-party libraries — for example, XLSX via [`xlsx`](https://www.npmjs.com/package/xlsx), and PDF via [`jspdf`](https://www.npmjs.com/package/jspdf) with [`jspdf-autotable`](https://www.npmjs.com/package/jspdf-autotable). + + + ### Status bar The `kbqAgGridStatusBar` directive adds a customizable panel below the table. @@ -96,6 +110,18 @@ The `kbqAgGridExternalFilterState` directive saves the external filter value. Ad +#### Rows + +The `kbqAgGridRowSelectionState` directive saves row selection. Add it with a unique key, connect the store provider via `kbqAgGridRowSelectionStateStoreProvider`, and set `getRowId`. + + + +#### Focus + +The `kbqAgGridRowFocusState` directive saves the focused cell. Add it with a unique key, connect the store provider via `kbqAgGridRowFocusStateStoreProvider`, and set `getRowId`. + + + ### Column menu The `kbqAgGridColumnMenu` directive adds a button in the top-right corner of the grid that opens a column management menu. The menu allows showing and hiding columns, reordering them via drag-and-drop, pinning them to the left or right, and searching for a column by name. The reset button restores columns to their initial state. diff --git a/docs/data-grid/ag-grid/ag-grid.ru.md b/docs/data-grid/ag-grid/ag-grid.ru.md index e1cd7ba646..a11adabed1 100644 --- a/docs/data-grid/ag-grid/ag-grid.ru.md +++ b/docs/data-grid/ag-grid/ag-grid.ru.md @@ -54,12 +54,26 @@ import { AgGridModule } from 'ag-grid-angular'; +### Группировка строк + +Директива `kbqAgGridRowGroup` реализует группировку строк на стороне клиента. Подключите её к `ag-grid-angular`, передайте исходные данные через `[kbqAgGridRowGroupRowData]` вместо `[rowData]` и укажите колонки группировки через `[(kbqAgGridRowGroupCols)]`. + +Состояние свёрнутых/развёрнутых групп и выделение строк можно сохранять независимо друг от друга: укажите уникальный ключ в `kbqAgGridRowGroupCollapsedState` и `kbqAgGridRowGroupSelectionState`, подключив провайдеры хранилища через `kbqAgGridRowGroupCollapsedStateStoreProvider` и `kbqAgGridRowGroupSelectionStateStoreProvider`. + + + ### Копирование выделенных строк Директива `kbqAgGridCopyByCtrlC` позволяет копировать выделенные строки в буфер обмена при помощи комбинации клавиш `Ctrl+C`. +### Экспорт + +Для экспорта отображаемых данных (с учётом активных фильтров, сортировки и форматирования) можно использовать собственный API таблицы. Метод `api.exportDataAsCsv()` позволяет скачать CSV-файл без дополнительных зависимостей. Другие форматы можно получить на основе значений ячеек таблицы с помощью сторонних библиотек — например, XLSX с помощью [`xlsx`](https://www.npmjs.com/package/xlsx), а PDF — с помощью [`jspdf`](https://www.npmjs.com/package/jspdf) и [`jspdf-autotable`](https://www.npmjs.com/package/jspdf-autotable). + + + ### Панель статуса Директива `kbqAgGridStatusBar` добавляет настраиваемую панель под таблицей. @@ -96,6 +110,18 @@ import { AgGridModule } from 'ag-grid-angular'; +#### Строки + +Директива `kbqAgGridRowSelectionState` сохраняет выделение строк. Добавьте её с уникальным ключом, подключите провайдер хранилища через `kbqAgGridRowSelectionStateStoreProvider` и укажите `getRowId`. + + + +#### Фокус + +Директива `kbqAgGridRowFocusState` сохраняет сфокусированную ячейку. Добавьте её с уникальным ключом, подключите провайдер хранилища через `kbqAgGridRowFocusStateStoreProvider` и укажите `getRowId`. + + + ### Меню колонок Директива `kbqAgGridColumnMenu` добавляет в правый верхний угол таблицы кнопку, которая открывает меню управления колонками. В меню можно показывать и скрывать колонки, менять их порядок перетаскиванием, закреплять слева или справа и находить колонку по названию. Кнопка сброса возвращает колонки к исходному состоянию. diff --git a/package.json b/package.json index c101b75289..bc28df379b 100644 --- a/package.json +++ b/package.json @@ -29,7 +29,7 @@ "@docsearch/js": "^4.6.3", "@fontsource/inter": "^5.2.8", "@fontsource/jetbrains-mono": "^5.2.6", - "@koobiq/ag-grid-angular-theme": "^34.4.0", + "@koobiq/ag-grid-angular-theme": "^34.5.1", "@koobiq/date-adapter": "^3.5.1", "@koobiq/date-formatter": "^3.5.1", "@koobiq/icons": "^11.7.1", @@ -39,10 +39,13 @@ "ag-grid-angular": "^34.3.1", "ag-grid-community": "^34.3.1", "highlight.js": "^11.11.1", + "jspdf": "^4.2.1", + "jspdf-autotable": "^5.0.8", "marked": "^17.0.3", "overlayscrollbars": "2.7.3", "rxjs": "^7.8.2", "tslib": "^2.8.1", + "xlsx": "^0.18.5", "zone.js": "~0.16.2" }, "devDependencies": { diff --git a/packages/components-dev/ag-grid/module.ts b/packages/components-dev/ag-grid/module.ts index f53088f70e..c8f216718e 100644 --- a/packages/components-dev/ag-grid/module.ts +++ b/packages/components-dev/ag-grid/module.ts @@ -3,6 +3,7 @@ import { AgGridColumnMenuExample, AgGridColumnStateExample, AgGridCopySelectedExample, + AgGridExportExample, AgGridExternalFilterStateExample, AgGridFilterStateExample, AgGridInfiniteSelectionExample, @@ -11,6 +12,9 @@ import { AgGridQuickFilterStateExample, AgGridRowActionsExample, AgGridRowDraggingExample, + AgGridRowFocusStateExample, + AgGridRowGroupExample, + AgGridRowSelectionStateExample, AgGridSkeletonCellRendererExample, AgGridStatusBarExample } from 'packages/docs-examples/components/ag-grid'; @@ -22,13 +26,17 @@ import { DevThemeToggle } from '../theme-toggle'; AgGridColumnMenuExample, AgGridOverviewExample, AgGridRowDraggingExample, + AgGridRowGroupExample, AgGridCopySelectedExample, + AgGridExportExample, AgGridStatusBarExample, AgGridRowActionsExample, AgGridColumnStateExample, AgGridFilterStateExample, AgGridQuickFilterStateExample, AgGridExternalFilterStateExample, + AgGridRowSelectionStateExample, + AgGridRowFocusStateExample, AgGridLoadingOverlayExample, AgGridSkeletonCellRendererExample, AgGridInfiniteSelectionExample @@ -50,12 +58,20 @@ import { DevThemeToggle } from '../theme-toggle';

+ +
+ +


+ +

+ +

diff --git a/packages/components-dev/ag-grid/styles.scss b/packages/components-dev/ag-grid/styles.scss index 73f957ca98..ec25f9bd38 100644 --- a/packages/components-dev/ag-grid/styles.scss +++ b/packages/components-dev/ag-grid/styles.scss @@ -5,4 +5,5 @@ dev-app { display: block; max-width: 608px; + padding: var(--kbq-size-s); } diff --git a/packages/docs-examples/components/actions-panel/actions-panel-overview/actions-panel-overview-example.ts b/packages/docs-examples/components/actions-panel/actions-panel-overview/actions-panel-overview-example.ts index 61a15a6cf8..1f215523b9 100644 --- a/packages/docs-examples/components/actions-panel/actions-panel-overview/actions-panel-overview-example.ts +++ b/packages/docs-examples/components/actions-panel/actions-panel-overview/actions-panel-overview-example.ts @@ -139,7 +139,6 @@ export class ExampleGrid { node.setSelected(true); } }); - api.setColumnWidths([{ key: 'ag-Grid-SelectionColumn', newWidth: 36 }]); this.api = api; } diff --git a/packages/docs-examples/components/ag-grid/ag-grid-column-state/ag-grid-column-state-example.ts b/packages/docs-examples/components/ag-grid/ag-grid-column-state/ag-grid-column-state-example.ts index d2d1651056..774799c4e7 100644 --- a/packages/docs-examples/components/ag-grid/ag-grid-column-state/ag-grid-column-state-example.ts +++ b/packages/docs-examples/components/ag-grid/ag-grid-column-state/ag-grid-column-state-example.ts @@ -17,12 +17,12 @@ ModuleRegistry.registerModules([AllCommunityModule]); selector: 'ag-grid-column-state-example', imports: [AgGridModule, KbqAgGridThemeModule, KbqButtonModule], template: ` - + + + + + + + + `, + styles: ` + :host { + display: flex; + flex-direction: column; + align-items: center; + gap: var(--kbq-size-m); + } + + .ag-grid-export-example-actions { + display: flex; + gap: var(--kbq-size-m); + } + `, + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class AgGridExportExample { + private readonly api = signal(null); + private readonly filename = 'example-export'; + protected readonly defaultColDef: ColDef = { + sortable: true, + resizable: true, + filter: true, + floatingFilter: true + }; + protected readonly columnDefs: ColDef[] = [ + { field: 'column0', headerName: 'Project name', width: 130 }, + { field: 'column1', headerName: 'Column 1', width: 130 }, + { field: 'column2', headerName: 'Column 2', width: 130 }, + { field: 'column3', headerName: 'Column 3', width: 130 }, + { field: 'column4', headerName: 'Column 4', width: 130 } + ]; + protected readonly rowData = Array.from({ length: 20 }, (_, index) => ({ + column0: 'Project name ' + index, + column1: 'Text ' + index, + column2: 'Text ' + index, + column3: 'Text ' + index, + column4: 'Text ' + index + })); + + /** Stores the grid API once the grid finishes initializing. */ + protected onGridReady({ api }: GridReadyEvent): void { + this.api.set(api); + } + + /** Downloads the grid data as a .csv file. */ + protected downloadCsv(): void { + this.api()?.exportDataAsCsv({ fileName: `${this.filename}.csv` }); + } + + /** Downloads the grid data as an .xlsx file. */ + protected downloadXlsx(): void { + const table = this.getExportTable(); + + if (!table) return; + + const worksheet = utils.aoa_to_sheet([table.headers, ...table.rows]); + const workbook = utils.book_new(); + + utils.book_append_sheet(workbook, worksheet, 'Export'); + writeFile(workbook, `${this.filename}.xlsx`); + } + + /** Downloads the grid data as a .pdf file. */ + protected downloadPdf(): void { + const table = this.getExportTable(); + + if (!table) return; + + const pdf = new jsPDF({ orientation: 'landscape' }); + + autoTable(pdf, { head: [table.headers], body: table.rows, theme: 'plain' }); + pdf.save(`${this.filename}.pdf`); + } + + /** Reads the currently displayed columns and rows (respecting filter, sort and formatters). */ + private getExportTable(): ExportTable | null { + const api = this.api(); + + if (!api) return null; + + const columns = api.getAllDisplayedColumns(); + const headers = columns.map((column) => column.getColDef().headerName ?? column.getColId()); + const rows: string[][] = []; + + api.forEachNodeAfterFilterAndSort((node) => { + if (!node.data) return; + + rows.push( + columns.map((column) => api.getCellValue({ rowNode: node, colKey: column, useFormatter: true }) ?? '') + ); + }); + + return { headers, rows }; + } +} diff --git a/packages/docs-examples/components/ag-grid/ag-grid-external-filter-state/ag-grid-external-filter-state-example.ts b/packages/docs-examples/components/ag-grid/ag-grid-external-filter-state/ag-grid-external-filter-state-example.ts index d09c703e7c..72ab9534f8 100644 --- a/packages/docs-examples/components/ag-grid/ag-grid-external-filter-state/ag-grid-external-filter-state-example.ts +++ b/packages/docs-examples/components/ag-grid/ag-grid-external-filter-state/ag-grid-external-filter-state-example.ts @@ -31,7 +31,7 @@ ModuleRegistry.registerModules([AllCommunityModule]); Reset state + ({ column5: 'Text ' + index })); +/** + * Shape actually worth sending to a backend. `KbqAgGridInfiniteSelectionState.excludedIds` is only + * meaningful while `selectAll` is `true` — outside select-all mode, the directive leaves individual + * row selection entirely to AG Grid's own API, so `includedIds` has to be read from there instead. + * Both fields are always present so the inapplicable one reads as an explicit `null`, not a missing key. + */ +type SelectionDto = { + selectAll: boolean; + includedIds: readonly string[] | null; + excludedIds: readonly string[] | null; +}; + /** * @title AG Grid with infinite selection */ @@ -37,7 +52,6 @@ const ROW_DATA = Array.from({ length: 1000 }, (_, index) => ({ imports: [AgGridModule, KbqAgGridThemeModule, JsonPipe], template: ` ({ [columnDefs]="columnDefs" [defaultColDef]="defaultColDef" [rowSelection]="rowSelection" + [selectionColumnDef]="selectionColumnDef" [kbqAgGridInfiniteSelectionDatasource]="datasource" [getRowId]="getRowId" [cacheBlockSize]="10" (kbqAgGridInfiniteSelectionStateChange)="onSelectAllChange($event)" + (selectionChanged)="onSelectionChanged($event)" /> -
{{ selection.state() | json }}
+
+ DTO sent to the backend: +
{{ selectionDto() | json }}
+
`, styles: ` :host { @@ -67,25 +86,31 @@ const ROW_DATA = Array.from({ length: 1000 }, (_, index) => ({ height: 300px; } + .ag-grid-infinite-selection-example-dto { + display: flex; + flex-direction: column; + gap: var(--kbq-size-s); + width: 180px; + font-size: var(--kbq-typography-text-compact-font-size); + color: var(--kbq-foreground-contrast-secondary); + } + pre { margin: 0; - width: 180px; max-height: 300px; overflow: scroll; - font-size: var(--kbq-typography-text-compact-font-size); - color: var(--kbq-foreground-contrast-secondary); } `, changeDetection: ChangeDetectionStrategy.OnPush }) export class AgGridInfiniteSelectionExample { protected readonly columnDefs: ColDef[] = [ - { field: 'column0', headerName: 'Project name' }, - { field: 'column1', headerName: 'Text' }, - { field: 'column2', headerName: 'Text' }, - { field: 'column3', headerName: 'Text' }, - { field: 'column4', headerName: 'Text' }, - { field: 'column5', headerName: 'Text' } + { field: 'column0', headerName: 'Project name', pinned: 'left', width: 130 }, + { field: 'column1', headerName: 'Text', width: 130 }, + { field: 'column2', headerName: 'Text', width: 130 }, + { field: 'column3', headerName: 'Text', width: 130 }, + { field: 'column4', headerName: 'Text', width: 130 }, + { field: 'column5', headerName: 'Text', width: 130 } ]; protected readonly datasource: IDatasource = { rowCount: ROW_DATA.length, @@ -102,8 +127,39 @@ export class AgGridInfiniteSelectionExample { mode: 'multiRow', isRowSelectable: ({ data }) => data !== undefined }; + protected readonly selectionColumnDef: SelectionColumnDef = { + pinned: 'left' + }; + private readonly infiniteSelection = viewChild.required(KbqAgGridInfiniteSelection); + private readonly includedIds = signal([]); + + /** + * The DTO this example would send to the backend for the current selection — combines the + * directive's own `selectAll`/`excludedIds` state with `includedIds` tracked separately via + * AG Grid's native selection, since the directive only maintains `excludedIds` while + * `selectAll` is `true` (see `SelectionDto`). + */ + protected readonly selectionDto = computed(() => { + const state = this.infiniteSelection().state(); + + return { + selectAll: state.selectAll, + includedIds: state.selectAll ? null : this.includedIds(), + excludedIds: state.selectAll ? state.excludedIds : null + }; + }); protected onSelectAllChange(state: KbqAgGridInfiniteSelectionState): void { console.debug('onSelectAllChange: ', state); } + + /** Tracks individually selected row ids — only meaningful while `selectAll` is `false`. */ + protected onSelectionChanged({ api }: SelectionChangedEvent): void { + this.includedIds.set( + api + .getSelectedNodes() + .map((node) => node.id) + .filter((id) => id !== undefined) + ); + } } diff --git a/packages/docs-examples/components/ag-grid/ag-grid-overview/ag-grid-overview-example.ts b/packages/docs-examples/components/ag-grid/ag-grid-overview/ag-grid-overview-example.ts index 10884b6e2b..80c859dfd9 100644 --- a/packages/docs-examples/components/ag-grid/ag-grid-overview/ag-grid-overview-example.ts +++ b/packages/docs-examples/components/ag-grid/ag-grid-overview/ag-grid-overview-example.ts @@ -148,7 +148,5 @@ export class AgGridOverviewExample { node.setSelected(true); } }); - - api.setColumnWidths([{ key: 'ag-Grid-SelectionColumn', newWidth: 36 }]); } } diff --git a/packages/docs-examples/components/ag-grid/ag-grid-quick-filter-state/ag-grid-quick-filter-state-example.ts b/packages/docs-examples/components/ag-grid/ag-grid-quick-filter-state/ag-grid-quick-filter-state-example.ts index 6ec4256370..7be3bd7897 100644 --- a/packages/docs-examples/components/ag-grid/ag-grid-quick-filter-state/ag-grid-quick-filter-state-example.ts +++ b/packages/docs-examples/components/ag-grid/ag-grid-quick-filter-state/ag-grid-quick-filter-state-example.ts @@ -28,7 +28,7 @@ ModuleRegistry.registerModules([AllCommunityModule]); #quickFilterState="kbqAgGridQuickFilterState" kbqAgGridTheme kbqAgGridThemeDisableCellFocusStyles - kbqAgGridQuickFilterState="dev-ag-grid-quick-filter-state" + kbqAgGridQuickFilterState="example-ag-grid-quick-filter-state" [alwaysMultiSort]="true" [rowData]="rowData" [columnDefs]="columnDefs" diff --git a/packages/docs-examples/components/ag-grid/ag-grid-row-actions/ag-grid-row-actions-example.ts b/packages/docs-examples/components/ag-grid/ag-grid-row-actions/ag-grid-row-actions-example.ts index 1f12bd8f8b..b51f465c79 100644 --- a/packages/docs-examples/components/ag-grid/ag-grid-row-actions/ag-grid-row-actions-example.ts +++ b/packages/docs-examples/components/ag-grid/ag-grid-row-actions/ag-grid-row-actions-example.ts @@ -155,7 +155,5 @@ export class AgGridRowActionsExample { node.setSelected(true); } }); - - api.setColumnWidths([{ key: 'ag-Grid-SelectionColumn', newWidth: 36 }]); } } diff --git a/packages/docs-examples/components/ag-grid/ag-grid-row-dragging/ag-grid-row-dragging-example.ts b/packages/docs-examples/components/ag-grid/ag-grid-row-dragging/ag-grid-row-dragging-example.ts index 668b2f9e4f..08f3ff8d91 100644 --- a/packages/docs-examples/components/ag-grid/ag-grid-row-dragging/ag-grid-row-dragging-example.ts +++ b/packages/docs-examples/components/ag-grid/ag-grid-row-dragging/ag-grid-row-dragging-example.ts @@ -117,7 +117,5 @@ export class AgGridRowDraggingExample { node.setSelected(true); } }); - - api.setColumnWidths([{ key: 'ag-Grid-SelectionColumn', newWidth: 36 }]); } } diff --git a/packages/docs-examples/components/ag-grid/ag-grid-row-focus-state/ag-grid-row-focus-state-example.ts b/packages/docs-examples/components/ag-grid/ag-grid-row-focus-state/ag-grid-row-focus-state-example.ts new file mode 100644 index 0000000000..15fefdcfd3 --- /dev/null +++ b/packages/docs-examples/components/ag-grid/ag-grid-row-focus-state/ag-grid-row-focus-state-example.ts @@ -0,0 +1,63 @@ +import { ChangeDetectionStrategy, Component } from '@angular/core'; +import { + KbqAgGridRowFocusStateLocalStorageStore, + kbqAgGridRowFocusStateStoreProvider, + KbqAgGridThemeModule +} from '@koobiq/ag-grid-angular-theme'; +import { KbqButtonModule } from '@koobiq/components/button'; +import { AgGridModule } from 'ag-grid-angular'; +import { AllCommunityModule, ColDef, GetRowIdParams, ModuleRegistry } from 'ag-grid-community'; + +ModuleRegistry.registerModules([AllCommunityModule]); + +/** + * @title AG Grid with `KbqAgGridRowFocusState` directive + */ +@Component({ + selector: 'ag-grid-row-focus-state-example', + imports: [AgGridModule, KbqAgGridThemeModule, KbqButtonModule], + template: ` + + + + `, + styles: ` + :host { + display: flex; + flex-direction: column; + align-items: center; + gap: var(--kbq-size-m); + } + `, + providers: [ + kbqAgGridRowFocusStateStoreProvider(KbqAgGridRowFocusStateLocalStorageStore) + ], + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class AgGridRowFocusStateExample { + protected readonly getRowId = (params: GetRowIdParams): string => params.data.column0; + protected readonly columnDefs: ColDef[] = [ + { field: 'column0', headerName: 'Column 0', width: 130 }, + { field: 'column1', headerName: 'Column 1', width: 130 }, + { field: 'column2', headerName: 'Column 2', width: 130 }, + { field: 'column3', headerName: 'Column 3', width: 130 }, + { field: 'column4', headerName: 'Column 4', width: 130 } + ]; + protected readonly rowData = Array.from({ length: 100 }, (_, index) => ({ + column0: 'Text ' + index, + column1: 'Text ' + index, + column2: 'Text ' + index, + column3: 'Text ' + index, + column4: 'Text ' + index + })); +} diff --git a/packages/docs-examples/components/ag-grid/ag-grid-row-group/ag-grid-row-group-example.ts b/packages/docs-examples/components/ag-grid/ag-grid-row-group/ag-grid-row-group-example.ts new file mode 100644 index 0000000000..b02a388d24 --- /dev/null +++ b/packages/docs-examples/components/ag-grid/ag-grid-row-group/ag-grid-row-group-example.ts @@ -0,0 +1,109 @@ +import { ChangeDetectionStrategy, Component, model } from '@angular/core'; +import { + KbqAgGridRowGroup, + KbqAgGridRowGroupCollapsedStateLocalStorageStore, + kbqAgGridRowGroupCollapsedStateStoreProvider, + kbqAgGridRowGroupColOptionsProvider, + KbqAgGridRowGroupSelectionStateLocalStorageStore, + kbqAgGridRowGroupSelectionStateStoreProvider, + KbqAgGridThemeModule +} from '@koobiq/ag-grid-angular-theme'; +import { KbqButtonModule } from '@koobiq/components/button'; +import { AgGridModule } from 'ag-grid-angular'; +import { AllCommunityModule, ColDef, ModuleRegistry, RowSelectionOptions } from 'ag-grid-community'; + +ModuleRegistry.registerModules([AllCommunityModule]); + +const CATEGORIES = ['BruteForce', 'Complex Attack', 'DDoS', 'HIPS alert', 'IDS/IPS Alert', 'XSS']; +const SEVERITIES = ['Low', 'Medium', 'High', 'Critical']; + +/** + * @title AG Grid with `KbqAgGridRowGroup` directive + */ +@Component({ + selector: 'ag-grid-row-group-example', + imports: [AgGridModule, KbqAgGridThemeModule, KbqButtonModule], + template: ` +
+ + +
+ + + `, + styles: ` + :host { + display: flex; + flex-direction: column; + align-items: center; + gap: var(--kbq-size-m); + } + + .ag-grid-row-group-example-actions { + display: flex; + gap: var(--kbq-size-m); + } + `, + providers: [ + kbqAgGridRowGroupCollapsedStateStoreProvider(KbqAgGridRowGroupCollapsedStateLocalStorageStore), + kbqAgGridRowGroupSelectionStateStoreProvider(KbqAgGridRowGroupSelectionStateLocalStorageStore), + kbqAgGridRowGroupColOptionsProvider({ headerName: 'Group' }) + ], + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class AgGridRowGroupExample { + protected readonly groupCols = model(['category', 'severity']); + protected readonly rowId = (row: Record): string => row.id as string; + protected readonly defaultColDef: ColDef = { + sortable: true, + resizable: true, + width: 140 + }; + protected readonly rowSelection: RowSelectionOptions = { + mode: 'multiRow', + headerCheckbox: true, + checkboxes: true + }; + protected readonly columnDefs: ColDef[] = [ + { field: 'column0', headerName: 'Column 0', width: 130 }, + { field: 'category', headerName: 'Category', width: 130 }, + { field: 'severity', headerName: 'Severity', width: 130 }, + { field: 'column3', headerName: 'Column 3', width: 130 }, + { field: 'column4', headerName: 'Column 4', width: 130 }, + { field: 'column5', headerName: 'Column 5', width: 130 }, + { field: 'column6', headerName: 'Column 6', width: 130 } + ]; + + protected readonly rowData = Array.from({ length: 24 }, (_, index) => ({ + id: String(index), + column0: 'Text ' + index, + category: CATEGORIES[index % CATEGORIES.length], + severity: SEVERITIES[index % SEVERITIES.length], + column3: 'Text ' + index, + column4: 'Text ' + index, + column5: 'Text ' + index, + column6: 'Text ' + index + })); + + /** Deselects every data row, including rows hidden inside a collapsed group. */ + protected clearSelectionState(rowGroup: KbqAgGridRowGroup): void { + for (const row of this.rowData) { + rowGroup.setRowSelected(row.id, false); + } + } +} diff --git a/packages/docs-examples/components/ag-grid/ag-grid-row-selection-state/ag-grid-row-selection-state-example.ts b/packages/docs-examples/components/ag-grid/ag-grid-row-selection-state/ag-grid-row-selection-state-example.ts new file mode 100644 index 0000000000..6d4667a96d --- /dev/null +++ b/packages/docs-examples/components/ag-grid/ag-grid-row-selection-state/ag-grid-row-selection-state-example.ts @@ -0,0 +1,74 @@ +import { ChangeDetectionStrategy, Component } from '@angular/core'; +import { + KbqAgGridRowSelectionStateLocalStorageStore, + kbqAgGridRowSelectionStateStoreProvider, + KbqAgGridThemeModule +} from '@koobiq/ag-grid-angular-theme'; +import { KbqButtonModule } from '@koobiq/components/button'; +import { AgGridModule } from 'ag-grid-angular'; +import { AllCommunityModule, ColDef, GetRowIdParams, ModuleRegistry, RowSelectionOptions } from 'ag-grid-community'; + +ModuleRegistry.registerModules([AllCommunityModule]); + +/** + * @title AG Grid with `KbqAgGridRowSelectionState` directive + */ +@Component({ + selector: 'ag-grid-row-selection-state-example', + imports: [AgGridModule, KbqAgGridThemeModule, KbqButtonModule], + template: ` + + + + `, + styles: ` + :host { + display: flex; + flex-direction: column; + align-items: center; + gap: var(--kbq-size-m); + } + `, + providers: [ + kbqAgGridRowSelectionStateStoreProvider(KbqAgGridRowSelectionStateLocalStorageStore) + ], + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class AgGridRowSelectionStateExample { + protected readonly getRowId = (params: GetRowIdParams): string => params.data.column0; + protected readonly defaultColDef: ColDef = { + sortable: true, + resizable: true + }; + protected readonly rowSelection: RowSelectionOptions = { + mode: 'multiRow', + headerCheckbox: true, + checkboxes: true + }; + protected readonly columnDefs: ColDef[] = [ + { field: 'column0', headerName: 'Column 0', width: 130 }, + { field: 'column1', headerName: 'Column 1', width: 130 }, + { field: 'column2', headerName: 'Column 2', width: 130 }, + { field: 'column3', headerName: 'Column 3', width: 130 }, + { field: 'column4', headerName: 'Column 4', width: 130 } + ]; + protected readonly rowData = Array.from({ length: 100 }, (_, index) => ({ + column0: 'Text ' + index, + column1: 'Text ' + index, + column2: 'Text ' + index, + column3: 'Text ' + index, + column4: 'Text ' + index + })); +} diff --git a/packages/docs-examples/components/ag-grid/ag-grid-status-bar/ag-grid-status-bar-example.ts b/packages/docs-examples/components/ag-grid/ag-grid-status-bar/ag-grid-status-bar-example.ts index 1afc9ae754..e599f1bd5a 100644 --- a/packages/docs-examples/components/ag-grid/ag-grid-status-bar/ag-grid-status-bar-example.ts +++ b/packages/docs-examples/components/ag-grid/ag-grid-status-bar/ag-grid-status-bar-example.ts @@ -161,7 +161,5 @@ export class AgGridStatusBarExample { node.setSelected(true); } }); - - api.setColumnWidths([{ key: 'ag-Grid-SelectionColumn', newWidth: 36 }]); } } diff --git a/packages/docs-examples/components/ag-grid/index.ts b/packages/docs-examples/components/ag-grid/index.ts index 87b6f37065..016874aaf8 100644 --- a/packages/docs-examples/components/ag-grid/index.ts +++ b/packages/docs-examples/components/ag-grid/index.ts @@ -2,6 +2,7 @@ import { NgModule } from '@angular/core'; import { AgGridColumnMenuExample } from './ag-grid-column-menu/ag-grid-column-menu-example'; import { AgGridColumnStateExample } from './ag-grid-column-state/ag-grid-column-state-example'; import { AgGridCopySelectedExample } from './ag-grid-copy-selected/ag-grid-copy-selected-example'; +import { AgGridExportExample } from './ag-grid-export/ag-grid-export-example'; import { AgGridExternalFilterStateExample } from './ag-grid-external-filter-state/ag-grid-external-filter-state-example'; import { AgGridFilterStateExample } from './ag-grid-filter-state/ag-grid-filter-state-example'; import { AgGridInfiniteSelectionExample } from './ag-grid-infinite-selection/ag-grid-infinite-selection-example'; @@ -10,6 +11,9 @@ import { AgGridOverviewExample } from './ag-grid-overview/ag-grid-overview-examp import { AgGridQuickFilterStateExample } from './ag-grid-quick-filter-state/ag-grid-quick-filter-state-example'; import { AgGridRowActionsExample } from './ag-grid-row-actions/ag-grid-row-actions-example'; import { AgGridRowDraggingExample } from './ag-grid-row-dragging/ag-grid-row-dragging-example'; +import { AgGridRowFocusStateExample } from './ag-grid-row-focus-state/ag-grid-row-focus-state-example'; +import { AgGridRowGroupExample } from './ag-grid-row-group/ag-grid-row-group-example'; +import { AgGridRowSelectionStateExample } from './ag-grid-row-selection-state/ag-grid-row-selection-state-example'; import { AgGridSkeletonCellRendererExample } from './ag-grid-skeleton-cell-renderer/ag-grid-skeleton-cell-renderer-example'; import { AgGridStatusBarExample } from './ag-grid-status-bar/ag-grid-status-bar-example'; @@ -17,6 +21,7 @@ export { AgGridColumnMenuExample, AgGridColumnStateExample, AgGridCopySelectedExample, + AgGridExportExample, AgGridExternalFilterStateExample, AgGridFilterStateExample, AgGridInfiniteSelectionExample, @@ -25,6 +30,9 @@ export { AgGridQuickFilterStateExample, AgGridRowActionsExample, AgGridRowDraggingExample, + AgGridRowFocusStateExample, + AgGridRowGroupExample, + AgGridRowSelectionStateExample, AgGridSkeletonCellRendererExample, AgGridStatusBarExample }; @@ -33,13 +41,17 @@ const EXAMPLES = [ AgGridColumnMenuExample, AgGridOverviewExample, AgGridRowDraggingExample, + AgGridRowGroupExample, AgGridCopySelectedExample, + AgGridExportExample, AgGridStatusBarExample, AgGridRowActionsExample, AgGridColumnStateExample, AgGridFilterStateExample, AgGridQuickFilterStateExample, AgGridExternalFilterStateExample, + AgGridRowSelectionStateExample, + AgGridRowFocusStateExample, AgGridLoadingOverlayExample, AgGridSkeletonCellRendererExample, AgGridInfiniteSelectionExample diff --git a/packages/docs-examples/components/content-panel/content-panel-with-grid/content-panel-with-grid-example.ts b/packages/docs-examples/components/content-panel/content-panel-with-grid/content-panel-with-grid-example.ts index 3470c438d2..9bc8c20c42 100644 --- a/packages/docs-examples/components/content-panel/content-panel-with-grid/content-panel-with-grid-example.ts +++ b/packages/docs-examples/components/content-panel/content-panel-with-grid/content-panel-with-grid-example.ts @@ -89,8 +89,6 @@ export class ExampleGrid { node.setSelected(true); } }); - - api.setColumnWidths([{ key: 'ag-Grid-SelectionColumn', newWidth: 36 }]); } } diff --git a/tools/cspell-locales/en.json b/tools/cspell-locales/en.json index b3a5393a1f..d2be387a7d 100644 --- a/tools/cspell-locales/en.json +++ b/tools/cspell-locales/en.json @@ -7,6 +7,7 @@ "words": [ "actionbar", "autoselect", + "autotable", "behaviour", "bento", "codeowners", diff --git a/yarn.lock b/yarn.lock index c324047f5e..9c62715fb5 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2946,6 +2946,13 @@ __metadata: languageName: node linkType: hard +"@babel/runtime@npm:^7.12.5, @babel/runtime@npm:^7.28.6": + version: 7.29.7 + resolution: "@babel/runtime@npm:7.29.7" + checksum: 10c0/ca11572f7146b21e0bde6a9ed4bb6a89eafbee5f0944c7eb54d0d8a2dac962c33638a1d611e14faa71dfbb92b4b5f9236232208568a6b7d5c6f3f39ddb91771e + languageName: node + linkType: hard + "@babel/template@npm:^7.24.7": version: 7.24.7 resolution: "@babel/template@npm:7.24.7" @@ -6039,9 +6046,9 @@ __metadata: languageName: node linkType: hard -"@koobiq/ag-grid-angular-theme@npm:^34.4.0": - version: 34.4.0 - resolution: "@koobiq/ag-grid-angular-theme@npm:34.4.0" +"@koobiq/ag-grid-angular-theme@npm:^34.5.1": + version: 34.5.1 + resolution: "@koobiq/ag-grid-angular-theme@npm:34.5.1" dependencies: tslib: "npm:^2.3.0" peerDependencies: @@ -6051,7 +6058,7 @@ __metadata: "@koobiq/icons": ">=9.0.0" ag-grid-angular: ^34.0.0 ag-grid-community: ^34.0.0 - checksum: 10c0/788e3f9505345e759163d5643666d389d68e6c5715cea272cad8b1d7cda348906b8fbf6e32f600bd7d512fa7afe663e02f7a0b87894acc748ecb798c23c0a390 + checksum: 10c0/0531fc2b2409e09a6d17f2d467ca7ebba8d70a0465587de81a42522c76843a3fadf88e8a91f09a4237d74fe0f11f1281828c7a8ff7bbde8298336dd02ffefd3e languageName: node linkType: hard @@ -8998,6 +9005,13 @@ __metadata: languageName: node linkType: hard +"@types/pako@npm:^2.0.3": + version: 2.0.4 + resolution: "@types/pako@npm:2.0.4" + checksum: 10c0/5765bf8bc7e77ee141c454118f03e544b8f6cb51eb257d82dc5830feeab8cd00818af3a1eabefdfbe8dd3ae9916ed5403937bf1031a0ee51deea27fdf4dccdfb + languageName: node + linkType: hard + "@types/qs@npm:*": version: 6.9.13 resolution: "@types/qs@npm:6.9.13" @@ -9005,6 +9019,13 @@ __metadata: languageName: node linkType: hard +"@types/raf@npm:^3.4.0": + version: 3.4.3 + resolution: "@types/raf@npm:3.4.3" + checksum: 10c0/dea835f0daa399c51db9137f5337dc08a2b4a5f61f645658966ecabaebbbd0fd59551f384a1141e14e22a1cc5a591da7d4d88c60a525ad1399108b6dd2641d75 + languageName: node + linkType: hard + "@types/range-parser@npm:*": version: 1.2.7 resolution: "@types/range-parser@npm:1.2.7" @@ -9134,6 +9155,13 @@ __metadata: languageName: node linkType: hard +"@types/trusted-types@npm:^2.0.7": + version: 2.0.7 + resolution: "@types/trusted-types@npm:2.0.7" + checksum: 10c0/4c4855f10de7c6c135e0d32ce462419d8abbbc33713b31d294596c0cc34ae1fa6112a2f9da729c8f7a20707782b0d69da3b1f8df6645b0366d08825ca1522e0c + languageName: node + linkType: hard + "@types/ws@npm:<8.18.2": version: 8.18.1 resolution: "@types/ws@npm:8.18.1" @@ -9877,6 +9905,13 @@ __metadata: languageName: node linkType: hard +"adler-32@npm:~1.3.0": + version: 1.3.1 + resolution: "adler-32@npm:1.3.1" + checksum: 10c0/c1b7185526ee1bbe0eac8ed414d5226af4cd02a0540449a72ec1a75f198c5e93352ba4d7b9327231eea31fd83c2d080d13baf16d8ed5710fb183677beb85f612 + languageName: node + linkType: hard + "ag-charts-types@npm:12.3.1": version: 12.3.1 resolution: "ag-charts-types@npm:12.3.1" @@ -10607,6 +10642,13 @@ __metadata: languageName: node linkType: hard +"base64-arraybuffer@npm:^1.0.2": + version: 1.0.2 + resolution: "base64-arraybuffer@npm:1.0.2" + checksum: 10c0/3acac95c70f9406e87a41073558ba85b6be9dbffb013a3d2a710e3f2d534d506c911847d5d9be4de458af6362c676de0a5c4c2d7bdf4def502d00b313368e72f + languageName: node + linkType: hard + "base64-js@npm:^1.3.0, base64-js@npm:^1.3.1": version: 1.5.1 resolution: "base64-js@npm:1.5.1" @@ -11225,6 +11267,22 @@ __metadata: languageName: node linkType: hard +"canvg@npm:^3.0.11": + version: 3.0.11 + resolution: "canvg@npm:3.0.11" + dependencies: + "@babel/runtime": "npm:^7.12.5" + "@types/raf": "npm:^3.4.0" + core-js: "npm:^3.8.3" + raf: "npm:^3.4.1" + regenerator-runtime: "npm:^0.13.7" + rgbcolor: "npm:^1.0.1" + stackblur-canvas: "npm:^2.0.0" + svg-pathdata: "npm:^6.0.3" + checksum: 10c0/03ea5b69e97a4a476ef5fc8455d0da2718bd68cd8ace3e42718176bf4b7dfd80eb1d0eba47dcd04b34ed9a0c5c8ed849ead0f364dad0e35369254a45d5e098c4 + languageName: node + linkType: hard + "capital-case@npm:^1.0.4": version: 1.0.4 resolution: "capital-case@npm:1.0.4" @@ -11236,6 +11294,16 @@ __metadata: languageName: node linkType: hard +"cfb@npm:~1.2.1": + version: 1.2.2 + resolution: "cfb@npm:1.2.2" + dependencies: + adler-32: "npm:~1.3.0" + crc-32: "npm:~1.2.0" + checksum: 10c0/87f6d9c3878268896ed6ca29dfe32a2aa078b12d0f21d8405c95911b74ab6296823d7312bbf5e18326d00b16cc697f587e07a17018c5edf7a1ba31dd5bc6da36 + languageName: node + linkType: hard + "chalk-template@npm:^1.1.0": version: 1.1.0 resolution: "chalk-template@npm:1.1.0" @@ -11576,6 +11644,13 @@ __metadata: languageName: node linkType: hard +"codepage@npm:~1.15.0": + version: 1.15.0 + resolution: "codepage@npm:1.15.0" + checksum: 10c0/2455b482302cb784b46dea60a8ee83f0c23e794bdd979556bdb107abe681bba722af62a37f5c955ff4efd68fdb9688c3986e719b4fd536c0e06bb25bc82abea3 + languageName: node + linkType: hard + "collect-v8-coverage@npm:^1.0.2": version: 1.0.3 resolution: "collect-v8-coverage@npm:1.0.3" @@ -12196,6 +12271,13 @@ __metadata: languageName: node linkType: hard +"core-js@npm:^3.6.0, core-js@npm:^3.8.3": + version: 3.49.0 + resolution: "core-js@npm:3.49.0" + checksum: 10c0/2e42edb47eda38fd5368380131623c8aa5d4a6b42164125b17744bdc08fa5ebbbdd06b4b4aa6ca3663470a560b0f2fba48e18f142dfe264b0039df85bc625694 + languageName: node + linkType: hard + "core-util-is@npm:^1.0.3, core-util-is@npm:~1.0.0": version: 1.0.3 resolution: "core-util-is@npm:1.0.3" @@ -12250,7 +12332,7 @@ __metadata: languageName: node linkType: hard -"crc-32@npm:^1.2.0": +"crc-32@npm:^1.2.0, crc-32@npm:~1.2.0, crc-32@npm:~1.2.1": version: 1.2.2 resolution: "crc-32@npm:1.2.2" bin: @@ -12463,6 +12545,15 @@ __metadata: languageName: node linkType: hard +"css-line-break@npm:^2.1.0": + version: 2.1.0 + resolution: "css-line-break@npm:2.1.0" + dependencies: + utrie: "npm:^1.0.2" + checksum: 10c0/b2222d99d5daf7861ecddc050244fdce296fad74b000dcff6bdfb1eb16dc2ef0b9ffe2c1c965e3239bd05ebe9eadb6d5438a91592fa8648d27a338e827cf9048 + languageName: node + linkType: hard + "css-loader@npm:7.1.2": version: 7.1.2 resolution: "css-loader@npm:7.1.2" @@ -13030,6 +13121,18 @@ __metadata: languageName: node linkType: hard +"dompurify@npm:^3.3.1": + version: 3.4.12 + resolution: "dompurify@npm:3.4.12" + dependencies: + "@types/trusted-types": "npm:^2.0.7" + dependenciesMeta: + "@types/trusted-types": + optional: true + checksum: 10c0/127a13817353d4e20e75a991a9022a04c3af12af7479f68e2b8bee6dbc7330a96edfb8f4ebff96f4f0f24cd43e8dbba46214131f510c3aa87a843bd8b610d0ab + languageName: node + linkType: hard + "domutils@npm:^3.2.1, domutils@npm:^3.2.2": version: 3.2.2 resolution: "domutils@npm:3.2.2" @@ -14545,6 +14648,17 @@ __metadata: languageName: node linkType: hard +"fast-png@npm:^6.2.0": + version: 6.4.0 + resolution: "fast-png@npm:6.4.0" + dependencies: + "@types/pako": "npm:^2.0.3" + iobuffer: "npm:^5.3.2" + pako: "npm:^2.1.0" + checksum: 10c0/bca27a09d56a5ead536b11c1ddccf4fe44c7c0af88a8faefab6a397527d9c71b00c09b2055d0108807c438c50719dd2acbd7217ef88785b500888db26fa0358a + languageName: node + linkType: hard + "fast-uri@npm:^3.0.1": version: 3.0.1 resolution: "fast-uri@npm:3.0.1" @@ -14627,6 +14741,13 @@ __metadata: languageName: node linkType: hard +"fflate@npm:^0.8.1": + version: 0.8.3 + resolution: "fflate@npm:0.8.3" + checksum: 10c0/eab181ca37f5348ae76d4b6f840e0026e30220e33153289ac942222d8b9638237d486507dbcc09878d724095bd354993a2ee48bbee99c8f2c6440d4448719aa7 + languageName: node + linkType: hard + "figures@npm:^3.0.0": version: 3.2.0 resolution: "figures@npm:3.2.0" @@ -15010,6 +15131,13 @@ __metadata: languageName: node linkType: hard +"frac@npm:~1.1.2": + version: 1.1.2 + resolution: "frac@npm:1.1.2" + checksum: 10c0/640740eb58b590eb38c78c676955bee91cd22d854f5876241a15c49d4495fa53a84898779dcf7eca30aabfe1c1a4a705752b5f224934257c5dda55c545413ba7 + languageName: node + linkType: hard + "fraction.js@npm:^4.3.7": version: 4.3.7 resolution: "fraction.js@npm:4.3.7" @@ -15979,6 +16107,16 @@ __metadata: languageName: node linkType: hard +"html2canvas@npm:^1.0.0-rc.5": + version: 1.4.1 + resolution: "html2canvas@npm:1.4.1" + dependencies: + css-line-break: "npm:^2.1.0" + text-segmentation: "npm:^1.0.3" + checksum: 10c0/6de86f75762b00948edf2ea559f16da0a1ec3facc4a8a7d3f35fcec59bb0c5970463478988ae3d9082152e0173690d46ebf4082e7ac803dd4817bae1d355c0db + languageName: node + linkType: hard + "htmlparser2@npm:^10.0.0": version: 10.0.0 resolution: "htmlparser2@npm:10.0.0" @@ -16445,6 +16583,13 @@ __metadata: languageName: node linkType: hard +"iobuffer@npm:^5.3.2": + version: 5.4.0 + resolution: "iobuffer@npm:5.4.0" + checksum: 10c0/1b3f9a5ea158bc63f038b374b42832acdb9db13ea9cfa4ed78723f30894986442f6c033dff4ae2fdf34724bf0fe432e3b86c11ca82049568c58b8d7fb47a6ac2 + languageName: node + linkType: hard + "ip-address@npm:^10.0.1": version: 10.1.0 resolution: "ip-address@npm:10.1.0" @@ -18126,6 +18271,39 @@ __metadata: languageName: node linkType: hard +"jspdf-autotable@npm:^5.0.8": + version: 5.0.8 + resolution: "jspdf-autotable@npm:5.0.8" + peerDependencies: + jspdf: ^2 || ^3 || ^4 + checksum: 10c0/c5e695d6d31692b9d2c11d284948ad508fc3e616d0b555119451dfd307176bdd80c880459cef6fee9e7db5140272b6fa281ee0ffaeeffddca6bf2497b577b40e + languageName: node + linkType: hard + +"jspdf@npm:^4.2.1": + version: 4.2.1 + resolution: "jspdf@npm:4.2.1" + dependencies: + "@babel/runtime": "npm:^7.28.6" + canvg: "npm:^3.0.11" + core-js: "npm:^3.6.0" + dompurify: "npm:^3.3.1" + fast-png: "npm:^6.2.0" + fflate: "npm:^0.8.1" + html2canvas: "npm:^1.0.0-rc.5" + dependenciesMeta: + canvg: + optional: true + core-js: + optional: true + dompurify: + optional: true + html2canvas: + optional: true + checksum: 10c0/d905809b374de1060ab39ba4b1603935fcced314bef8f63f7fd272d3f96eff0b50a96e48d3c2063ac8e51b84a1442464ff2b037af13f54b082e456416da470b7 + languageName: node + linkType: hard + "jwa@npm:^2.0.1": version: 2.0.1 resolution: "jwa@npm:2.0.1" @@ -18230,7 +18408,7 @@ __metadata: "@eslint/js": "npm:^9.0.0" "@fontsource/inter": "npm:^5.2.8" "@fontsource/jetbrains-mono": "npm:^5.2.6" - "@koobiq/ag-grid-angular-theme": "npm:^34.4.0" + "@koobiq/ag-grid-angular-theme": "npm:^34.5.1" "@koobiq/date-adapter": "npm:^3.5.1" "@koobiq/date-formatter": "npm:^3.5.1" "@koobiq/design-tokens": "npm:^3.17.2" @@ -18300,6 +18478,8 @@ __metadata: jest-environment-jsdom: "npm:^30.4.1" jest-fail-on-console: "npm:^3.3.4" jest-preset-angular: "npm:^16.2.0" + jspdf: "npm:^4.2.1" + jspdf-autotable: "npm:^5.0.8" license-checker: "npm:^25.0.1" lint-staged: "npm:^15.5.2" luxon: "npm:^3.7.2" @@ -18333,6 +18513,7 @@ __metadata: tslib: "npm:^2.8.1" typescript: "npm:5.8.3" typescript-eslint: "npm:^8.60.1" + xlsx: "npm:^0.18.5" zone.js: "npm:~0.16.2" languageName: unknown linkType: soft @@ -20815,6 +20996,13 @@ __metadata: languageName: node linkType: hard +"pako@npm:^2.1.0": + version: 2.2.0 + resolution: "pako@npm:2.2.0" + checksum: 10c0/e5d31de1940fdd13cc4014296b0026112483d0834bce4856ca29c8af8438d030c6416986a0f6df7d5372cae18d6dd6c57f48b24a49d6c207c0a4cc66af15c07d + languageName: node + linkType: hard + "param-case@npm:^3.0.4": version: 3.0.4 resolution: "param-case@npm:3.0.4" @@ -21111,6 +21299,13 @@ __metadata: languageName: node linkType: hard +"performance-now@npm:^2.1.0": + version: 2.1.0 + resolution: "performance-now@npm:2.1.0" + checksum: 10c0/22c54de06f269e29f640e0e075207af57de5052a3d15e360c09b9a8663f393f6f45902006c1e71aa8a5a1cdfb1a47fe268826f8496d6425c362f00f5bc3e85d9 + languageName: node + linkType: hard + "pg-cloudflare@npm:^1.2.5": version: 1.2.5 resolution: "pg-cloudflare@npm:1.2.5" @@ -21994,6 +22189,15 @@ __metadata: languageName: node linkType: hard +"raf@npm:^3.4.1": + version: 3.4.1 + resolution: "raf@npm:3.4.1" + dependencies: + performance-now: "npm:^2.1.0" + checksum: 10c0/337f0853c9e6a77647b0f499beedafea5d6facfb9f2d488a624f88b03df2be72b8a0e7f9118a3ff811377d534912039a3311815700d2b6d2313f82f736f9eb6e + languageName: node + linkType: hard + "railroad-diagrams@npm:^1.0.0": version: 1.0.0 resolution: "railroad-diagrams@npm:1.0.0" @@ -22317,6 +22521,13 @@ __metadata: languageName: node linkType: hard +"regenerator-runtime@npm:^0.13.7": + version: 0.13.11 + resolution: "regenerator-runtime@npm:0.13.11" + checksum: 10c0/12b069dc774001fbb0014f6a28f11c09ebfe3c0d984d88c9bced77fdb6fedbacbca434d24da9ae9371bfbf23f754869307fb51a4c98a8b8b18e5ef748677ca24 + languageName: node + linkType: hard + "regex-parser@npm:^2.2.11": version: 2.3.0 resolution: "regex-parser@npm:2.3.0" @@ -22640,6 +22851,13 @@ __metadata: languageName: node linkType: hard +"rgbcolor@npm:^1.0.1": + version: 1.0.1 + resolution: "rgbcolor@npm:1.0.1" + checksum: 10c0/13af06c523351bac2854b85a22d1dfafd9310efd898e9bd96c8706f9aa09a3ddc8392ab00ae03d12950782164a97677f21834ffd84ffebf76ae106add319f956 + languageName: node + linkType: hard + "rimraf@npm:^5.0.1, rimraf@npm:^5.0.10": version: 5.0.10 resolution: "rimraf@npm:5.0.10" @@ -24106,6 +24324,15 @@ __metadata: languageName: node linkType: hard +"ssf@npm:~0.11.2": + version: 0.11.2 + resolution: "ssf@npm:0.11.2" + dependencies: + frac: "npm:~1.1.2" + checksum: 10c0/c3fd24a90dc37a9dc5c4154cb4121e27507c33ebfeee3532aaf03625756b2c006cf79c0a23db0ba16c4a6e88e1349455327867e03453fc9d54b32c546bc18ca6 + languageName: node + linkType: hard + "ssri@npm:^10.0.0": version: 10.0.5 resolution: "ssri@npm:10.0.5" @@ -24140,6 +24367,13 @@ __metadata: languageName: node linkType: hard +"stackblur-canvas@npm:^2.0.0": + version: 2.7.0 + resolution: "stackblur-canvas@npm:2.7.0" + checksum: 10c0/df290d0629056d5bb43d37548d0b24cb8593c79d742650e68489abf61013db578c9980724c2508bb738d107204f2e2494ab94c3cf69d6b725caa9c63b8c7e272 + languageName: node + linkType: hard + "statuses@npm:2.0.1": version: 2.0.1 resolution: "statuses@npm:2.0.1" @@ -24557,6 +24791,13 @@ __metadata: languageName: node linkType: hard +"svg-pathdata@npm:^6.0.3": + version: 6.0.3 + resolution: "svg-pathdata@npm:6.0.3" + checksum: 10c0/1ba4ad2fa81e86df37d6e78d3be9e664bbedf97773b725a863a85db384285be32dc37d9c0d61e477d89594ee95b967d2c53d6bee2d76420aab670ab4124a38b9 + languageName: node + linkType: hard + "svg-tags@npm:^1.0.0": version: 1.0.0 resolution: "svg-tags@npm:1.0.0" @@ -24801,6 +25042,15 @@ __metadata: languageName: node linkType: hard +"text-segmentation@npm:^1.0.3": + version: 1.0.3 + resolution: "text-segmentation@npm:1.0.3" + dependencies: + utrie: "npm:^1.0.2" + checksum: 10c0/8b9ae8524e3a332371060d0ca62f10ad49a13e954719ea689a6c3a8b8c15c8a56365ede2bb91c322fb0d44b6533785f0da603e066b7554d052999967fb72d600 + languageName: node + linkType: hard + "thenify-all@npm:^1.0.0": version: 1.6.0 resolution: "thenify-all@npm:1.6.0" @@ -25890,6 +26140,15 @@ __metadata: languageName: node linkType: hard +"utrie@npm:^1.0.2": + version: 1.0.2 + resolution: "utrie@npm:1.0.2" + dependencies: + base64-arraybuffer: "npm:^1.0.2" + checksum: 10c0/eaffe645bd81a39e4bc3abb23df5895e9961dbdd49748ef3b173529e8b06ce9dd1163e9705d5309a1c61ee41ffcb825e2043bc0fd1659845ffbdf4b1515dfdb4 + languageName: node + linkType: hard + "uuid@npm:^8.0.0, uuid@npm:^8.3.2": version: 8.3.2 resolution: "uuid@npm:8.3.2" @@ -26459,6 +26718,20 @@ __metadata: languageName: node linkType: hard +"wmf@npm:~1.0.1": + version: 1.0.2 + resolution: "wmf@npm:1.0.2" + checksum: 10c0/3fa5806f382632cadfe65d4ef24f7a583b0c0720171edb00e645af5248ad0bb6784e8fcee1ccd9f475a1a12a7523e2512e9c063731fbbdae14dc469e1c033d93 + languageName: node + linkType: hard + +"word@npm:~0.3.0": + version: 0.3.0 + resolution: "word@npm:0.3.0" + checksum: 10c0/c6da2a9f7a0d81a32fa6768a638d21b153da2be04f94f3964889c7cc1365d74b6ecb43b42256c3f926cd59512d8258206991c78c21000c3da96d42ff1238b840 + languageName: node + linkType: hard + "wordwrap@npm:^1.0.0": version: 1.0.0 resolution: "wordwrap@npm:1.0.0" @@ -26614,6 +26887,23 @@ __metadata: languageName: node linkType: hard +"xlsx@npm:^0.18.5": + version: 0.18.5 + resolution: "xlsx@npm:0.18.5" + dependencies: + adler-32: "npm:~1.3.0" + cfb: "npm:~1.2.1" + codepage: "npm:~1.15.0" + crc-32: "npm:~1.2.1" + ssf: "npm:~0.11.2" + wmf: "npm:~1.0.1" + word: "npm:~0.3.0" + bin: + xlsx: bin/xlsx.njs + checksum: 10c0/787cfa77034a3e86fdcde21572f1011c8976f87823a5e0ee5057f13b2f6e48f17a1710732a91b8ae15d7794945c7cba8a3ca904ea7150e028260b0ab8e1158c8 + languageName: node + linkType: hard + "xml-name-validator@npm:^4.0.0": version: 4.0.0 resolution: "xml-name-validator@npm:4.0.0" From 848189a968fc0885ec258b779924590f696fb9e6 Mon Sep 17 00:00:00 2001 From: Artem Belik Date: Thu, 23 Jul 2026 22:02:47 +0300 Subject: [PATCH 2/3] refactor: license --- tools/validate-licenses/validate-licenses.ts | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/tools/validate-licenses/validate-licenses.ts b/tools/validate-licenses/validate-licenses.ts index 922488ec43..12e7c58e19 100644 --- a/tools/validate-licenses/validate-licenses.ts +++ b/tools/validate-licenses/validate-licenses.ts @@ -19,6 +19,10 @@ const licensesWhitelist: License[] = [ 'BSD-3-Clause', 'BSD-4-Clause', + // OSI-approved, permissive (same tier as MIT/BSD). Reaches the tree via + // jspdf -> fast-png -> pako, a transitive dependency of jspdf (used by the ag-grid PDF export docs example). + 'Zlib', + // All CC-BY licenses have a full copyright grant and attribution section. 'CC-BY-3.0', 'CC-BY-4.0', From 21fd0bd6b05dfd1aa38482c6f7b4ad8a8d604f41 Mon Sep 17 00:00:00 2001 From: Artem Belik Date: Fri, 24 Jul 2026 09:39:57 +0300 Subject: [PATCH 3/3] refactor: stackblitz deps --- .../components/stackblitz/stackblitz-writer.ts | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/apps/docs/src/app/components/stackblitz/stackblitz-writer.ts b/apps/docs/src/app/components/stackblitz/stackblitz-writer.ts index 2be0bb7699..740cf1c99c 100644 --- a/apps/docs/src/app/components/stackblitz/stackblitz-writer.ts +++ b/apps/docs/src/app/components/stackblitz/stackblitz-writer.ts @@ -38,10 +38,19 @@ const OPTIONAL_PACKAGE_JSON_DEPENDENCIES = { '@koobiq/ag-grid-angular-theme': { '@koobiq/ag-grid-angular-theme': '^34', 'ag-grid-angular': '^34', - 'ag-grid-community': '^34', - jspdf: '^4', - 'jspdf-autotable': '^5', - xlsx: '^0' + 'ag-grid-community': '^34' + }, + // Used by packages/docs-examples/components/ag-grid/ag-grid-export/ag-grid-export-example.ts + jspdf: { + jspdf: '^4' + }, + // Used by packages/docs-examples/components/ag-grid/ag-grid-export/ag-grid-export-example.ts + 'jspdf-autotable': { + 'jspdf-autotable': '^5' + }, + // Used by packages/docs-examples/components/ag-grid/ag-grid-export/ag-grid-export-example.ts + xlsx: { + xlsx: '^0.18' } } as const;