@lowdefy/blocks-aggrid 5.5.0 → 5.6.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/README.md CHANGED
@@ -1,25 +1,62 @@
1
1
  # Lowdefy Blocks for Ag-Grid
2
2
 
3
- This repository provides blocks for [Ag-Grid](https://www.ag-grid.com/), a feature rich javascript grid and table library.
3
+ This repository provides blocks for [AG Grid](https://www.ag-grid.com/), a feature rich javascript grid and table library.
4
4
 
5
- The implementation of these blocks is a minimal wrapper for the [@ag-grid-community/core
6
- ](https://www.npmjs.com/package/@ag-grid-community/core) package. This means you write normal Ag-Grid config to create tables.
5
+ The implementation of these blocks is a minimal wrapper for the [ag-grid-community](https://www.npmjs.com/package/ag-grid-community) package, on AG Grid v33. This means you write normal AG Grid config to create tables.
7
6
 
8
- See the [Ag-Grid docs](https://www.ag-grid.com/documentation/react/getting-started/) for the table settings API.
7
+ See the [AG Grid docs](https://www.ag-grid.com/react-data-grid/) for the table settings API.
9
8
 
10
9
  ## Blocks
11
10
 
12
- Block types for supported [Ag-Grid themes](https://www.ag-grid.com/documentation/javascript/themes-provided/) are available for for `dispay` and `input` block categories.
11
+ Each grid is available as a `display` block and as an `input` block. The display blocks render data; the input blocks additionally hold the table data as the block's value.
13
12
 
14
13
  ### Block types
15
14
 
16
- The availible ag-gird block types are:
15
+ Display blocks:
17
16
 
18
- - [`AgGridAlpine`](https://www.ag-grid.com/example?theme=ag-theme-alpine)
19
- - [`AgGridAlpineDark`](https://www.ag-grid.com/example?theme=ag-theme-alpine-dark)
20
- - [`AgGridBalham`](https://www.ag-grid.com/example?theme=ag-theme-balham)
21
- - [`AgGridBalhamDark`](https://www.ag-grid.com/example?theme=ag-theme-balham-dark)
22
- - [`AgGridMaterial`](https://www.ag-grid.com/example?theme=ag-theme-material)
17
+ - `AgGridLowdefy` — themed from the app's antd design tokens. Recommended for Lowdefy apps.
18
+ - `AgGridAlpine`
19
+ - `AgGridBalham`
20
+ - `AgGridMaterial`
21
+
22
+ Input blocks:
23
+
24
+ - `AgGridLowdefyInput` — themed from the app's antd design tokens. Recommended for Lowdefy apps.
25
+ - `AgGridInputAlpine`
26
+ - `AgGridInputBalham`
27
+ - `AgGridInputMaterial`
28
+
29
+ ## Themes
30
+
31
+ All eight blocks render through [AG Grid's Theming API](https://www.ag-grid.com/react-data-grid/theming/). No block imports an AG Grid stylesheet and no block uses `theme="legacy"`.
32
+
33
+ **`AgGridLowdefy` is the recommended grid for Lowdefy apps.** It adopts the app's antd theme tokens — primary colour, surfaces, fonts and radius — and follows light/dark mode automatically, with no configuration. It takes a `size` property (`small | middle | large`, default `middle`) matching antd Table's densities, which sets row and header height to 36 / 44 / 54 pixels.
34
+
35
+ `AgGridBalham`, `AgGridAlpine` and `AgGridMaterial` remain first-class built-ins for users who want those looks, and are kept indefinitely with the same API. On v33 they render AG Grid's prebuilt Theming API equivalents of those themes (`themeBalham` / `themeAlpine` / `themeMaterial`) with the same antd colour mapping applied as theme parameters, so they look very close to before but are no longer pixel-identical.
36
+
37
+ ### Adopting `AgGridLowdefy`
38
+
39
+ To adopt, change `type: AgGridBalham` to `type: AgGridLowdefy` (or `type: AgGridInputBalham` to `type: AgGridLowdefyInput`). Every property carries over unchanged, and the grid will deliberately look different afterwards — that is the point. This is a visual opt-in, not a migration.
40
+
41
+ ### `size` and explicit heights
42
+
43
+ A `rowHeight` or `headerHeight` grid option overrides what `size` sets — use one or the other, not both. `size` sets the theme parameters `rowHeight` and `headerHeight`, and an AG Grid grid option always beats a theme parameter, so `size: large` together with `rowHeight: 30` gives 30 pixel rows under a 54 pixel header.
44
+
45
+ ### `themeParams`
46
+
47
+ All eight blocks take a `themeParams` object property: [AG Grid theming parameter](https://www.ag-grid.com/react-data-grid/theming-parameters/) names merged onto the block's own theme, for retinting a single grid.
48
+
49
+ ```yaml
50
+ - id: my_table
51
+ type: AgGridLowdefy
52
+ properties:
53
+ themeParams:
54
+ headerBackgroundColor: '#1a1a2e'
55
+ headerTextColor: '#e0e0ff'
56
+ borderColor: var(--ant-color-border)
57
+ ```
58
+
59
+ Values are CSS strings and may reference antd tokens. Neither Lowdefy nor AG Grid validates parameter names, so a misspelled key is a silent no-op — check spelling against AG Grid's theming parameter reference.
23
60
 
24
61
  ### Events
25
62
 
@@ -72,9 +109,7 @@ The availible ag-gird block types are:
72
109
 
73
110
  - `exportDataAsCsv`: When called, table data will be downloaded in csv format.
74
111
  - `sizeColumnsToFit`: When called, size table column widths to fit all columns to table width.
75
- - `autoSize`: When called, auto size columns. The following can be passed as the first argument of `args`.
76
- - `skipHeader: boolean`: Do not consider header content width when auto-sizing columns.
77
- - `columnIds: string[]`: List of `colId`s for which to calculate auto-size when called.
112
+ - `autoSize`: When called, auto size columns. The following can be passed as the first argument of `args`. - `skipHeader: boolean`: Do not consider header content width when auto-sizing columns. - `columnIds: string[]`: List of `colId`s for which to calculate auto-size when called.
78
113
  - `setFilterModel`: When called, apply filter model to table. See https://www.ag-grid.com/javascript-data-grid/filter-api/ for model details.
79
114
  - `setQuickFilter`: When called, pass a quick filter text into the grid for filtering. See https://www.ag-grid.com/javascript-data-grid/filter-quick/ for details.
80
115
 
@@ -299,12 +334,14 @@ pages:
299
334
  sortable: true
300
335
  resizable: true
301
336
  filter: true
302
- rowSelection: 'multiple'
337
+ rowSelection:
338
+ mode: multiRow
339
+ enableClickSelection: true
340
+ checkboxes: true
303
341
  columnDefs:
304
342
  - headerName: Title
305
343
  field: title
306
344
  width: 350
307
- checkboxSelection: true
308
345
  - headerName: Year
309
346
  field: year
310
347
  width: 100
@@ -379,13 +416,15 @@ pages:
379
416
  sortable: true
380
417
  resizable: true
381
418
  filter: true
382
- rowSelection: 'multiple'
419
+ rowSelection:
420
+ mode: multiRow
421
+ enableClickSelection: true
422
+ checkboxes: true
423
+ headerCheckbox: true
383
424
  columnDefs:
384
425
  - headerName: Title
385
426
  field: title
386
427
  width: 350
387
- checkboxSelection: true
388
- headerCheckboxSelection: true
389
428
  - headerName: Year
390
429
  field: year
391
430
  width: 100
package/dist/AgGrid.js CHANGED
@@ -13,22 +13,25 @@
13
13
  See the License for the specific language governing permissions and
14
14
  limitations under the License.
15
15
  */ import React, { useState, useRef, useEffect, useMemo, useCallback } from 'react';
16
- import { AgGridReact } from '@ag-grid-community/react';
17
- import { ClientSideRowModelModule } from '@ag-grid-community/client-side-row-model';
18
- import { CsvExportModule } from '@ag-grid-community/csv-export';
16
+ import { AgGridReact } from 'ag-grid-react';
17
+ import { AllCommunityModule, ModuleRegistry } from 'ag-grid-community';
19
18
  import processColDefs from './processColDefs.js';
20
19
  import assignRowId from './assignRowId.js';
21
20
  import LoadingOverlay from './LoadingOverlay.js';
22
- const AgGrid = ({ properties, methods, loading, events, components })=>{
23
- const { quickFilterValue, columnDefs, defaultColDef, rowData: newRowData, suppressCellFocus = true, ...someProperties } = properties;
21
+ // Registration is idempotent, so each core registers independently to stay standalone.
22
+ ModuleRegistry.registerModules([
23
+ AllCommunityModule
24
+ ]);
25
+ const AgGrid = ({ components, events, loading, methods, properties, theme })=>{
26
+ const { quickFilterValue, columnDefs, defaultColDef, height, rowData: newRowData, rowId, size, suppressCellFocus = true, themeParams, ...someProperties } = properties;
24
27
  const [rowData, setRowData] = useState(newRowData ?? []);
25
28
  const gridRef = useRef();
26
29
  const memoDefaultColDef = useMemo(()=>defaultColDef);
27
30
  const getRowId = useCallback((params)=>{
28
- if (properties.rowId && params.data[properties.rowId] !== undefined) return params.data[properties.rowId];
31
+ if (rowId && params.data[rowId] !== undefined) return params.data[rowId];
29
32
  return assignRowId(params);
30
33
  }, [
31
- properties.rowId
34
+ rowId
32
35
  ]);
33
36
  const onRowClick = useCallback((event)=>{
34
37
  if (events.onRowClick) {
@@ -60,7 +63,9 @@ const AgGrid = ({ properties, methods, loading, events, components })=>{
60
63
  }
61
64
  }, []);
62
65
  const onRowSelected = useCallback((event)=>{
63
- if (!event.node.selected) return; // see https://stackoverflow.com/a/63265775/2453657
66
+ // AG Grid fires onRowSelected for deselection too, which the Lowdefy event does not represent.
67
+ // See https://stackoverflow.com/a/63265775/2453657
68
+ if (!event.node.isSelected()) return;
64
69
  if (events.onRowSelected) {
65
70
  methods.triggerEvent({
66
71
  name: 'onRowSelected',
@@ -144,6 +149,7 @@ const AgGrid = ({ properties, methods, loading, events, components })=>{
144
149
  }, /*#__PURE__*/ React.createElement(AgGridReact, {
145
150
  columnMenu: "legacy",
146
151
  ...someProperties,
152
+ theme: theme,
147
153
  suppressCellFocus: suppressCellFocus,
148
154
  rowData: rowData,
149
155
  defaultColDef: memoDefaultColDef,
@@ -153,10 +159,6 @@ const AgGrid = ({ properties, methods, loading, events, components })=>{
153
159
  onRowSelected: onRowSelected,
154
160
  onRowClicked: onRowClick,
155
161
  onCellClicked: onCellClicked,
156
- modules: [
157
- ClientSideRowModelModule,
158
- CsvExportModule
159
- ],
160
162
  columnDefs: processColDefs(columnDefs, methods, components),
161
163
  ref: gridRef,
162
164
  getRowId: getRowId,
@@ -13,22 +13,25 @@
13
13
  See the License for the specific language governing permissions and
14
14
  limitations under the License.
15
15
  */ import React, { useState, useRef, useEffect, useMemo, useCallback } from 'react';
16
- import { AgGridReact } from '@ag-grid-community/react';
17
- import { ClientSideRowModelModule } from '@ag-grid-community/client-side-row-model';
18
- import { CsvExportModule } from '@ag-grid-community/csv-export';
16
+ import { AgGridReact } from 'ag-grid-react';
17
+ import { AllCommunityModule, ModuleRegistry } from 'ag-grid-community';
19
18
  import processColDefs from './processColDefs.js';
20
19
  import assignRowId from './assignRowId.js';
21
20
  import LoadingOverlay from './LoadingOverlay.js';
22
- const AgGridInput = ({ properties, methods, loading, events, value })=>{
23
- const { quickFilterValue, columnDefs, defaultColDef, ...someProperties } = properties;
21
+ // Registration is idempotent, so each core registers independently to stay standalone.
22
+ ModuleRegistry.registerModules([
23
+ AllCommunityModule
24
+ ]);
25
+ const AgGridInput = ({ events, loading, methods, properties, theme, value })=>{
26
+ const { quickFilterValue, columnDefs, defaultColDef, height, rowId, size, themeParams, ...someProperties } = properties;
24
27
  const [rowData, setRowData] = useState(value ?? []);
25
28
  const gridRef = useRef();
26
29
  const memoDefaultColDef = useMemo(()=>defaultColDef);
27
30
  const getRowId = useCallback((params)=>{
28
- if (properties.rowId && params.data[properties.rowId] !== undefined) return params.data[properties.rowId];
31
+ if (rowId && params.data[rowId] !== undefined) return params.data[rowId];
29
32
  return assignRowId(params);
30
33
  }, [
31
- properties.rowId
34
+ rowId
32
35
  ]);
33
36
  const onRowClick = useCallback((event)=>{
34
37
  if (events.onRowClick) {
@@ -60,7 +63,9 @@ const AgGridInput = ({ properties, methods, loading, events, value })=>{
60
63
  }
61
64
  }, []);
62
65
  const onRowSelected = useCallback((event)=>{
63
- if (!event.node.selected) return; // see https://stackoverflow.com/a/63265775/2453657
66
+ // AG Grid fires onRowSelected for deselection too, which the Lowdefy event does not represent.
67
+ // See https://stackoverflow.com/a/63265775/2453657
68
+ if (!event.node.isSelected()) return;
64
69
  if (events.onRowSelected) {
65
70
  methods.triggerEvent({
66
71
  name: 'onRowSelected',
@@ -192,6 +197,7 @@ const AgGridInput = ({ properties, methods, loading, events, value })=>{
192
197
  }, /*#__PURE__*/ React.createElement(AgGridReact, {
193
198
  columnMenu: "legacy",
194
199
  ...someProperties,
200
+ theme: theme,
195
201
  rowData: rowData,
196
202
  onCellClicked: onCellClicked,
197
203
  onCellValueChanged: onCellValueChanged,
@@ -202,10 +208,6 @@ const AgGridInput = ({ properties, methods, loading, events, value })=>{
202
208
  onSortChanged: onSortChanged,
203
209
  onRowDragEnd: onRowDragEnd,
204
210
  defaultColDef: memoDefaultColDef,
205
- modules: [
206
- ClientSideRowModelModule,
207
- CsvExportModule
208
- ],
209
211
  columnDefs: processColDefs(columnDefs, methods),
210
212
  ref: gridRef,
211
213
  getRowId: getRowId,
@@ -1,44 +1,22 @@
1
- .antdTheme.antdTheme {
2
- --ag-background-color: var(--ant-color-bg-container);
3
- --ag-foreground-color: var(--ant-color-text);
4
- --ag-secondary-foreground-color: var(--ant-color-text-secondary);
5
- --ag-border-color: var(--ant-color-border);
6
- --ag-secondary-border-color: var(--ant-color-border-secondary);
7
- --ag-header-background-color: var(--ant-color-fill-quaternary);
8
- --ag-header-foreground-color: var(--ant-color-text);
9
- --ag-header-cell-hover-background-color: var(--ant-color-fill-tertiary);
10
- --ag-header-cell-moving-background-color: var(--ant-color-fill-secondary);
11
- --ag-tooltip-background-color: var(--ant-color-bg-spotlight);
12
- --ag-odd-row-background-color: var(--ant-color-fill-quaternary);
13
- --ag-control-panel-background-color: var(--ant-color-bg-elevated);
14
- --ag-subheader-background-color: var(--ant-color-bg-layout);
15
- --ag-subheader-toolbar-background-color: var(--ant-color-bg-layout);
16
- --ag-selected-row-background-color: var(--ant-color-primary-bg);
17
- --ag-row-hover-color: var(--ant-color-primary-bg-hover);
18
- --ag-column-hover-color: var(--ant-color-primary-bg-hover);
19
- --ag-range-selection-highlight-color: var(--ant-color-primary-bg-hover);
20
- --ag-modal-overlay-background-color: var(--ant-color-bg-mask);
21
- --ag-input-disabled-background-color: var(--ant-color-bg-container-disabled);
22
- --ag-input-disabled-border-color: var(--ant-color-border);
23
- --ag-disabled-foreground-color: var(--ant-color-text-disabled);
24
- --ag-chip-background-color: var(--ant-color-fill-secondary);
25
- --ag-input-focus-box-shadow: 0 0 0 2px var(--ant-color-primary-bg);
26
- --ag-input-focus-border-color: var(--ant-color-primary);
27
- --ag-range-selection-border-color: var(--ant-color-primary);
28
- --ag-range-selection-background-color: var(--ant-color-primary-bg);
29
- --ag-checkbox-checked-color: var(--ant-color-primary);
30
- --ag-checkbox-unchecked-color: var(--ant-color-text-quaternary);
31
- --ag-checkbox-background-color: var(--ant-color-bg-container);
32
- --ag-card-shadow: var(--ant-box-shadow-secondary);
33
- --ag-popup-shadow: var(--ant-box-shadow);
34
- --ag-font-family: var(--ant-font-family);
35
- --ag-font-size: var(--ant-font-size);
36
- }
1
+ /*
2
+ Copyright 2020-2026 Lowdefy, Inc
37
3
 
38
- .antdTheme :global(.ag-root-wrapper) {
39
- border-radius: var(--ant-border-radius);
40
- overflow: hidden;
41
- }
4
+ Licensed under the Apache License, Version 2.0 (the "License");
5
+ you may not use this file except in compliance with the License.
6
+ You may obtain a copy of the License at
7
+
8
+ http://www.apache.org/licenses/LICENSE-2.0
9
+
10
+ Unless required by applicable law or agreed to in writing, software
11
+ distributed under the License is distributed on an "AS IS" BASIS,
12
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ See the License for the specific language governing permissions and
14
+ limitations under the License.
15
+ */
16
+
17
+ /* Lowdefy's own cell-rendering and layout helpers for all AgGrid blocks. Colours come from the
18
+ theme params in src/theme/themeLowdefy.js, not from this file: the Theming API honours AG Grid
19
+ custom properties inherited from an ancestor, so declaring any here would override those params. */
42
20
 
43
21
  /* Avatar sizing per ag-grid theme — reads row-height via the wrapper class. */
44
22
  .antdTheme:global(.ag-theme-balham),
@@ -56,15 +34,6 @@
56
34
  --lf-avatar-font-size: var(--ant-font-size-sm, 12px);
57
35
  }
58
36
 
59
- .antdTheme :global(.ag-overlay-loading-wrapper) {
60
- background-color: color-mix(in srgb, var(--ant-color-bg-container) 70%, transparent);
61
- }
62
-
63
- .antdTheme :global(.ag-overlay-loading-center) {
64
- border-radius: var(--ant-border-radius);
65
- box-shadow: var(--ant-box-shadow-secondary);
66
- }
67
-
68
37
  .antdTheme :global(.ag-overlay-no-rows-wrapper) {
69
38
  color: var(--ant-color-text-secondary);
70
39
  }
@@ -14,11 +14,11 @@
14
14
  limitations under the License.
15
15
  */ import React from 'react';
16
16
  import { withBlockDefaults } from '@lowdefy/block-utils';
17
- import '@ag-grid-community/styles/ag-grid.css';
18
- import '@ag-grid-community/styles/ag-theme-alpine.css';
19
17
  import antdStyles from '../../ag-grid-antd.module.css';
18
+ import { themeAlpineAntd, useGridTheme } from '../../theme/themeLowdefy.js';
20
19
  import AgGrid from '../../AgGrid.js';
21
20
  const AgGridAlpine = ({ blockId, components, events, loading, methods, properties, styles })=>{
21
+ const theme = useGridTheme(themeAlpineAntd, properties.themeParams);
22
22
  return /*#__PURE__*/ React.createElement("div", {
23
23
  id: blockId,
24
24
  className: `ag-theme-alpine ${antdStyles.antdTheme}`,
@@ -32,7 +32,8 @@ const AgGridAlpine = ({ blockId, components, events, loading, methods, propertie
32
32
  events: events,
33
33
  loading: loading,
34
34
  methods: methods,
35
- properties: properties
35
+ properties: properties,
36
+ theme: theme
36
37
  }));
37
38
  };
38
39
  export default withBlockDefaults(AgGridAlpine);
@@ -13,4 +13,4 @@
13
13
  See the License for the specific language governing permissions and
14
14
  limitations under the License.
15
15
  */ import createAgGridDisplayHelper from '../../createAgGridDisplayHelper.js';
16
- export default createAgGridDisplayHelper('alpine');
16
+ export default createAgGridDisplayHelper();
@@ -14,11 +14,11 @@
14
14
  limitations under the License.
15
15
  */ import React from 'react';
16
16
  import { withBlockDefaults } from '@lowdefy/block-utils';
17
- import '@ag-grid-community/styles/ag-grid.css';
18
- import '@ag-grid-community/styles/ag-theme-balham.css';
19
17
  import antdStyles from '../../ag-grid-antd.module.css';
18
+ import { themeBalhamAntd, useGridTheme } from '../../theme/themeLowdefy.js';
20
19
  import AgGrid from '../../AgGrid.js';
21
20
  const AgGridBalham = ({ blockId, components, events, loading, methods, properties, styles })=>{
21
+ const theme = useGridTheme(themeBalhamAntd, properties.themeParams);
22
22
  return /*#__PURE__*/ React.createElement("div", {
23
23
  id: blockId,
24
24
  className: `ag-theme-balham ${antdStyles.antdTheme}`,
@@ -32,7 +32,8 @@ const AgGridBalham = ({ blockId, components, events, loading, methods, propertie
32
32
  events: events,
33
33
  loading: loading,
34
34
  methods: methods,
35
- properties: properties
35
+ properties: properties,
36
+ theme: theme
36
37
  }));
37
38
  };
38
39
  export default withBlockDefaults(AgGridBalham);
@@ -13,4 +13,4 @@
13
13
  See the License for the specific language governing permissions and
14
14
  limitations under the License.
15
15
  */ import createAgGridDisplayHelper from '../../createAgGridDisplayHelper.js';
16
- export default createAgGridDisplayHelper('balham');
16
+ export default createAgGridDisplayHelper();
@@ -14,11 +14,11 @@
14
14
  limitations under the License.
15
15
  */ import React from 'react';
16
16
  import { withBlockDefaults } from '@lowdefy/block-utils';
17
- import '@ag-grid-community/styles/ag-grid.css';
18
- import '@ag-grid-community/styles/ag-theme-alpine.css';
19
17
  import antdStyles from '../../ag-grid-antd.module.css';
18
+ import { themeAlpineAntd, useGridTheme } from '../../theme/themeLowdefy.js';
20
19
  import AgGridInput from '../../AgGridInput.js';
21
20
  const AgGridInputAlpine = ({ blockId, events, loading, methods, properties, required, styles, validation, value })=>{
21
+ const theme = useGridTheme(themeAlpineAntd, properties.themeParams);
22
22
  return /*#__PURE__*/ React.createElement("div", {
23
23
  id: blockId,
24
24
  className: `ag-theme-alpine ${antdStyles.antdTheme}`,
@@ -34,6 +34,7 @@ const AgGridInputAlpine = ({ blockId, events, loading, methods, properties, requ
34
34
  methods: methods,
35
35
  properties: properties,
36
36
  required: required,
37
+ theme: theme,
37
38
  validation: validation,
38
39
  value: value
39
40
  }));
@@ -13,4 +13,4 @@
13
13
  See the License for the specific language governing permissions and
14
14
  limitations under the License.
15
15
  */ import createAgGridInputHelper from '../../createAgGridInputHelper.js';
16
- export default createAgGridInputHelper('alpine');
16
+ export default createAgGridInputHelper();
@@ -14,11 +14,11 @@
14
14
  limitations under the License.
15
15
  */ import React from 'react';
16
16
  import { withBlockDefaults } from '@lowdefy/block-utils';
17
- import '@ag-grid-community/styles/ag-grid.css';
18
- import '@ag-grid-community/styles/ag-theme-balham.css';
19
17
  import antdStyles from '../../ag-grid-antd.module.css';
18
+ import { themeBalhamAntd, useGridTheme } from '../../theme/themeLowdefy.js';
20
19
  import AgGridInput from '../../AgGridInput.js';
21
20
  const AgGridInputBalham = ({ blockId, events, loading, methods, properties, required, styles, validation, value })=>{
21
+ const theme = useGridTheme(themeBalhamAntd, properties.themeParams);
22
22
  return /*#__PURE__*/ React.createElement("div", {
23
23
  id: blockId,
24
24
  className: `ag-theme-balham ${antdStyles.antdTheme}`,
@@ -34,6 +34,7 @@ const AgGridInputBalham = ({ blockId, events, loading, methods, properties, requ
34
34
  methods: methods,
35
35
  properties: properties,
36
36
  required: required,
37
+ theme: theme,
37
38
  validation: validation,
38
39
  value: value
39
40
  }));
@@ -13,4 +13,4 @@
13
13
  See the License for the specific language governing permissions and
14
14
  limitations under the License.
15
15
  */ import createAgGridInputHelper from '../../createAgGridInputHelper.js';
16
- export default createAgGridInputHelper('balham');
16
+ export default createAgGridInputHelper();
@@ -14,11 +14,11 @@
14
14
  limitations under the License.
15
15
  */ import React from 'react';
16
16
  import { withBlockDefaults } from '@lowdefy/block-utils';
17
- import '@ag-grid-community/styles/ag-grid.css';
18
- import '@ag-grid-community/styles/ag-theme-material.css';
19
17
  import antdStyles from '../../ag-grid-antd.module.css';
18
+ import { themeMaterialAntd, useGridTheme } from '../../theme/themeLowdefy.js';
20
19
  import AgGridInput from '../../AgGridInput.js';
21
20
  const AgGridInputMaterial = ({ blockId, events, loading, methods, properties, required, styles, validation, value })=>{
21
+ const theme = useGridTheme(themeMaterialAntd, properties.themeParams);
22
22
  return /*#__PURE__*/ React.createElement("div", {
23
23
  id: blockId,
24
24
  className: `ag-theme-material ${antdStyles.antdTheme}`,
@@ -34,6 +34,7 @@ const AgGridInputMaterial = ({ blockId, events, loading, methods, properties, re
34
34
  methods: methods,
35
35
  properties: properties,
36
36
  required: required,
37
+ theme: theme,
37
38
  validation: validation,
38
39
  value: value
39
40
  }));
@@ -13,4 +13,4 @@
13
13
  See the License for the specific language governing permissions and
14
14
  limitations under the License.
15
15
  */ import createAgGridInputHelper from '../../createAgGridInputHelper.js';
16
- export default createAgGridInputHelper('material');
16
+ export default createAgGridInputHelper();
@@ -0,0 +1,45 @@
1
+ /*
2
+ Copyright 2020-2026 Lowdefy, Inc
3
+
4
+ Licensed under the Apache License, Version 2.0 (the "License");
5
+ you may not use this file except in compliance with the License.
6
+ You may obtain a copy of the License at
7
+
8
+ http://www.apache.org/licenses/LICENSE-2.0
9
+
10
+ Unless required by applicable law or agreed to in writing, software
11
+ distributed under the License is distributed on an "AS IS" BASIS,
12
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ See the License for the specific language governing permissions and
14
+ limitations under the License.
15
+ */ import React from 'react';
16
+ import { withBlockDefaults } from '@lowdefy/block-utils';
17
+ import antdStyles from '../../ag-grid-antd.module.css';
18
+ import { sizeConfig, themeForSize, useGridTheme } from '../../theme/themeLowdefy.js';
19
+ import AgGrid from '../../AgGrid.js';
20
+ const AgGridLowdefy = ({ blockId, components, events, loading, methods, properties, styles })=>{
21
+ // The shared module's avatar rules key on the file-theme wrapper class the legacy blocks carry,
22
+ // which this block does not have. Setting the vars inline is also what makes avatars track size,
23
+ // since this block's density is not fixed.
24
+ const { avatarSize, avatarFontSize } = sizeConfig(properties.size);
25
+ const theme = useGridTheme(themeForSize(properties.size), properties.themeParams);
26
+ return /*#__PURE__*/ React.createElement("div", {
27
+ id: blockId,
28
+ className: antdStyles.antdTheme,
29
+ style: {
30
+ width: '100%',
31
+ height: properties.height ?? 500,
32
+ '--lf-avatar-size': `${avatarSize}px`,
33
+ '--lf-avatar-font-size': `${avatarFontSize}px`,
34
+ ...styles?.element
35
+ }
36
+ }, /*#__PURE__*/ React.createElement(AgGrid, {
37
+ components: components,
38
+ events: events,
39
+ loading: loading,
40
+ methods: methods,
41
+ properties: properties,
42
+ theme: theme
43
+ }));
44
+ };
45
+ export default withBlockDefaults(AgGridLowdefy);
@@ -0,0 +1,16 @@
1
+ /*
2
+ Copyright 2020-2026 Lowdefy, Inc
3
+
4
+ Licensed under the Apache License, Version 2.0 (the "License");
5
+ you may not use this file except in compliance with the License.
6
+ You may obtain a copy of the License at
7
+
8
+ http://www.apache.org/licenses/LICENSE-2.0
9
+
10
+ Unless required by applicable law or agreed to in writing, software
11
+ distributed under the License is distributed on an "AS IS" BASIS,
12
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ See the License for the specific language governing permissions and
14
+ limitations under the License.
15
+ */ import createAgGridDisplayHelper from '../../createAgGridDisplayHelper.js';
16
+ export default createAgGridDisplayHelper();
@@ -0,0 +1,18 @@
1
+ /*
2
+ Copyright 2020-2026 Lowdefy, Inc
3
+
4
+ Licensed under the Apache License, Version 2.0 (the "License");
5
+ you may not use this file except in compliance with the License.
6
+ You may obtain a copy of the License at
7
+
8
+ http://www.apache.org/licenses/LICENSE-2.0
9
+
10
+ Unless required by applicable law or agreed to in writing, software
11
+ distributed under the License is distributed on an "AS IS" BASIS,
12
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ See the License for the specific language governing permissions and
14
+ limitations under the License.
15
+ */ import createDisplayMeta from '../../createDisplayMeta.js';
16
+ export default createDisplayMeta('AgGridLowdefy', {
17
+ size: true
18
+ });
@@ -0,0 +1,48 @@
1
+ /*
2
+ Copyright 2020-2026 Lowdefy, Inc
3
+
4
+ Licensed under the Apache License, Version 2.0 (the "License");
5
+ you may not use this file except in compliance with the License.
6
+ You may obtain a copy of the License at
7
+
8
+ http://www.apache.org/licenses/LICENSE-2.0
9
+
10
+ Unless required by applicable law or agreed to in writing, software
11
+ distributed under the License is distributed on an "AS IS" BASIS,
12
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ See the License for the specific language governing permissions and
14
+ limitations under the License.
15
+ */ import React from 'react';
16
+ import { withBlockDefaults } from '@lowdefy/block-utils';
17
+ import antdStyles from '../../ag-grid-antd.module.css';
18
+ import { sizeConfig, themeForSize, useGridTheme } from '../../theme/themeLowdefy.js';
19
+ import AgGridInput from '../../AgGridInput.js';
20
+ const AgGridLowdefyInput = ({ blockId, events, loading, methods, properties, required, styles, validation, value })=>{
21
+ // The shared module's avatar rules key on the file-theme wrapper class the legacy blocks carry,
22
+ // which this block does not have. Setting the vars inline is also what makes avatars track size,
23
+ // since this block's density is not fixed.
24
+ const { avatarSize, avatarFontSize } = sizeConfig(properties.size);
25
+ const theme = useGridTheme(themeForSize(properties.size), properties.themeParams);
26
+ return /*#__PURE__*/ React.createElement("div", {
27
+ id: blockId,
28
+ className: antdStyles.antdTheme,
29
+ style: {
30
+ width: '100%',
31
+ height: properties.height ?? 500,
32
+ '--lf-avatar-size': `${avatarSize}px`,
33
+ '--lf-avatar-font-size': `${avatarFontSize}px`,
34
+ ...styles?.element
35
+ }
36
+ }, /*#__PURE__*/ React.createElement(AgGridInput, {
37
+ blockId: blockId,
38
+ events: events,
39
+ loading: loading,
40
+ methods: methods,
41
+ properties: properties,
42
+ required: required,
43
+ theme: theme,
44
+ validation: validation,
45
+ value: value
46
+ }));
47
+ };
48
+ export default withBlockDefaults(AgGridLowdefyInput);
@@ -0,0 +1,16 @@
1
+ /*
2
+ Copyright 2020-2026 Lowdefy, Inc
3
+
4
+ Licensed under the Apache License, Version 2.0 (the "License");
5
+ you may not use this file except in compliance with the License.
6
+ You may obtain a copy of the License at
7
+
8
+ http://www.apache.org/licenses/LICENSE-2.0
9
+
10
+ Unless required by applicable law or agreed to in writing, software
11
+ distributed under the License is distributed on an "AS IS" BASIS,
12
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ See the License for the specific language governing permissions and
14
+ limitations under the License.
15
+ */ import createAgGridInputHelper from '../../createAgGridInputHelper.js';
16
+ export default createAgGridInputHelper();
@@ -0,0 +1,18 @@
1
+ /*
2
+ Copyright 2020-2026 Lowdefy, Inc
3
+
4
+ Licensed under the Apache License, Version 2.0 (the "License");
5
+ you may not use this file except in compliance with the License.
6
+ You may obtain a copy of the License at
7
+
8
+ http://www.apache.org/licenses/LICENSE-2.0
9
+
10
+ Unless required by applicable law or agreed to in writing, software
11
+ distributed under the License is distributed on an "AS IS" BASIS,
12
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ See the License for the specific language governing permissions and
14
+ limitations under the License.
15
+ */ import createInputMeta from '../../createInputMeta.js';
16
+ export default createInputMeta('AgGridLowdefyInput', {
17
+ size: true
18
+ });
@@ -14,11 +14,11 @@
14
14
  limitations under the License.
15
15
  */ import React from 'react';
16
16
  import { withBlockDefaults } from '@lowdefy/block-utils';
17
- import '@ag-grid-community/styles/ag-grid.css';
18
- import '@ag-grid-community/styles/ag-theme-material.css';
19
17
  import antdStyles from '../../ag-grid-antd.module.css';
18
+ import { themeMaterialAntd, useGridTheme } from '../../theme/themeLowdefy.js';
20
19
  import AgGrid from '../../AgGrid.js';
21
20
  const AgGridMaterial = ({ blockId, components, events, loading, methods, properties, styles })=>{
21
+ const theme = useGridTheme(themeMaterialAntd, properties.themeParams);
22
22
  return /*#__PURE__*/ React.createElement("div", {
23
23
  id: blockId,
24
24
  className: `ag-theme-material ${antdStyles.antdTheme}`,
@@ -32,7 +32,8 @@ const AgGridMaterial = ({ blockId, components, events, loading, methods, propert
32
32
  events: events,
33
33
  loading: loading,
34
34
  methods: methods,
35
- properties: properties
35
+ properties: properties,
36
+ theme: theme
36
37
  }));
37
38
  };
38
39
  export default withBlockDefaults(AgGridMaterial);
@@ -13,4 +13,4 @@
13
13
  See the License for the specific language governing permissions and
14
14
  limitations under the License.
15
15
  */ import createAgGridDisplayHelper from '../../createAgGridDisplayHelper.js';
16
- export default createAgGridDisplayHelper('material');
16
+ export default createAgGridDisplayHelper();
package/dist/blocks.js CHANGED
@@ -17,4 +17,6 @@ export { default as AgGridBalham } from './blocks/AgGridBalham/AgGridBalham.js';
17
17
  export { default as AgGridInputAlpine } from './blocks/AgGridInputAlpine/AgGridInputAlpine.js';
18
18
  export { default as AgGridInputBalham } from './blocks/AgGridInputBalham/AgGridInputBalham.js';
19
19
  export { default as AgGridInputMaterial } from './blocks/AgGridInputMaterial/AgGridInputMaterial.js';
20
+ export { default as AgGridLowdefy } from './blocks/AgGridLowdefy/AgGridLowdefy.js';
21
+ export { default as AgGridLowdefyInput } from './blocks/AgGridLowdefyInput/AgGridLowdefyInput.js';
20
22
  export { default as AgGridMaterial } from './blocks/AgGridMaterial/AgGridMaterial.js';
@@ -14,7 +14,7 @@
14
14
  limitations under the License.
15
15
  */ import { createBlockHelper, escapeId } from '@lowdefy/e2e-utils';
16
16
  import { expect } from '@playwright/test';
17
- function createAgGridDisplayHelper(theme) {
17
+ function createAgGridDisplayHelper() {
18
18
  const locator = (page, blockId)=>page.locator(`#${escapeId(blockId)} .ag-root-wrapper`);
19
19
  return createBlockHelper({
20
20
  locator,
@@ -26,7 +26,6 @@ function createAgGridDisplayHelper(theme) {
26
26
  rowCount: (page, blockId, count)=>expect(locator(page, blockId).locator('.ag-row')).toHaveCount(count),
27
27
  headerCount: (page, blockId, count)=>expect(locator(page, blockId).locator('.ag-header-cell-text')).toHaveCount(count),
28
28
  cellText: (page, blockId, rowIndex, colIndex, text)=>expect(locator(page, blockId).locator(`.ag-row[row-index="${rowIndex}"] .ag-cell`).nth(colIndex)).toHaveText(text),
29
- themeClass: (page, blockId)=>expect(page.locator(`#${escapeId(blockId)}`)).toHaveClass(new RegExp(`ag-theme-${theme}`)),
30
29
  emptyOverlay: (page, blockId)=>expect(locator(page, blockId).locator('.ag-overlay-no-rows-center')).toBeVisible()
31
30
  }
32
31
  });
@@ -14,7 +14,7 @@
14
14
  limitations under the License.
15
15
  */ import { createBlockHelper, escapeId } from '@lowdefy/e2e-utils';
16
16
  import { expect } from '@playwright/test';
17
- function createAgGridInputHelper(theme) {
17
+ function createAgGridInputHelper() {
18
18
  const locator = (page, blockId)=>page.locator(`#${escapeId(blockId)} .ag-root-wrapper`);
19
19
  return createBlockHelper({
20
20
  locator,
@@ -33,7 +33,6 @@ function createAgGridInputHelper(theme) {
33
33
  rowCount: (page, blockId, count)=>expect(locator(page, blockId).locator('.ag-row')).toHaveCount(count),
34
34
  headerCount: (page, blockId, count)=>expect(locator(page, blockId).locator('.ag-header-cell-text')).toHaveCount(count),
35
35
  cellText: (page, blockId, rowIndex, colIndex, text)=>expect(locator(page, blockId).locator(`.ag-row[row-index="${rowIndex}"] .ag-cell`).nth(colIndex)).toHaveText(text),
36
- themeClass: (page, blockId)=>expect(page.locator(`#${escapeId(blockId)}`)).toHaveClass(new RegExp(`ag-theme-${theme}`)),
37
36
  emptyOverlay: (page, blockId)=>expect(locator(page, blockId).locator('.ag-overlay-no-rows-center')).toBeVisible(),
38
37
  dragHandle: (page, blockId, rowIndex)=>expect(locator(page, blockId).locator(`.ag-row[row-index="${rowIndex}"] .ag-drag-handle`)).toBeVisible()
39
38
  }
@@ -12,10 +12,11 @@
12
12
  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
13
  See the License for the specific language governing permissions and
14
14
  limitations under the License.
15
- */ // Shared meta for the display AgGrid theme blocks (AgGridAlpine / AgGridMaterial / AgGridBalham).
16
- // They are identical apart from the theme name in the css key description, so each block's meta.js
17
- // is a one-line call to this factory rather than a duplicated copy of the whole schema.
18
- function createDisplayMeta(blockName) {
15
+ */ // Shared meta for the display AgGrid theme blocks (AgGridAlpine / AgGridMaterial / AgGridBalham /
16
+ // AgGridLowdefy). They are identical apart from the theme name in the css key description and
17
+ // whether they take a size property, so each block's meta.js is a one-line call to this factory
18
+ // rather than a duplicated copy of the whole schema.
19
+ function createDisplayMeta(blockName, { size = false } = {}) {
19
20
  return {
20
21
  category: 'display',
21
22
  icons: [],
@@ -92,6 +93,22 @@ function createDisplayMeta(blockName) {
92
93
  type: 'object',
93
94
  additionalProperties: false,
94
95
  properties: {
96
+ ...size ? {
97
+ size: {
98
+ type: 'string',
99
+ enum: [
100
+ 'small',
101
+ 'middle',
102
+ 'large'
103
+ ],
104
+ default: 'middle',
105
+ description: "Row density, mirroring antd Table sizes. `small` is compact, `middle` (the Lowdefy default) matches antd Table's `middle`, `large` matches antd Table's default density. Changes spacing and row/header height only — colours and font size are identical across sizes."
106
+ }
107
+ } : {},
108
+ themeParams: {
109
+ type: 'object',
110
+ description: "AG Grid Theming API parameters merged onto this block's theme, for per-grid overrides. Keys are AG Grid param names, e.g. `headerBackgroundColor`, `rowHoverColor`, `borderColor`. Values are CSS strings and may reference antd tokens, e.g. `var(--ant-color-primary)`. An unrecognised param name has no effect — neither Lowdefy nor AG Grid validates the names — so check spelling against AG Grid's theming parameter reference."
111
+ },
95
112
  height: {
96
113
  type: [
97
114
  'number',
@@ -13,9 +13,10 @@
13
13
  See the License for the specific language governing permissions and
14
14
  limitations under the License.
15
15
  */ // Shared meta for the input AgGrid theme blocks (AgGridInputAlpine / AgGridInputMaterial /
16
- // AgGridInputBalham). They are identical apart from the theme name in the css key description, so
17
- // each block's meta.js is a one-line call to this factory rather than a duplicated copy.
18
- function createInputMeta(blockName) {
16
+ // AgGridInputBalham / AgGridLowdefyInput). They are identical apart from the theme name in the css
17
+ // key description and whether they take a size property, so each block's meta.js is a one-line call
18
+ // to this factory rather than a duplicated copy of the whole schema.
19
+ function createInputMeta(blockName, { size = false } = {}) {
19
20
  return {
20
21
  category: 'input',
21
22
  icons: [],
@@ -104,6 +105,22 @@ function createInputMeta(blockName) {
104
105
  type: 'object',
105
106
  additionalProperties: false,
106
107
  properties: {
108
+ ...size ? {
109
+ size: {
110
+ type: 'string',
111
+ enum: [
112
+ 'small',
113
+ 'middle',
114
+ 'large'
115
+ ],
116
+ default: 'middle',
117
+ description: "Row density, mirroring antd Table sizes. `small` is compact, `middle` (the Lowdefy default) matches antd Table's `middle`, `large` matches antd Table's default density. Changes spacing and row/header height only — colours and font size are identical across sizes."
118
+ }
119
+ } : {},
120
+ themeParams: {
121
+ type: 'object',
122
+ description: "AG Grid Theming API parameters merged onto this block's theme, for per-grid overrides. Keys are AG Grid param names, e.g. `headerBackgroundColor`, `rowHoverColor`, `borderColor`. Values are CSS strings and may reference antd tokens, e.g. `var(--ant-color-primary)`. An unrecognised param name has no effect — neither Lowdefy nor AG Grid validates the names — so check spelling against AG Grid's theming parameter reference."
123
+ },
107
124
  height: {
108
125
  type: [
109
126
  'number',
package/dist/e2e.js CHANGED
@@ -17,4 +17,6 @@ export { default as AgGridBalham } from './blocks/AgGridBalham/e2e.js';
17
17
  export { default as AgGridInputAlpine } from './blocks/AgGridInputAlpine/e2e.js';
18
18
  export { default as AgGridInputBalham } from './blocks/AgGridInputBalham/e2e.js';
19
19
  export { default as AgGridInputMaterial } from './blocks/AgGridInputMaterial/e2e.js';
20
+ export { default as AgGridLowdefy } from './blocks/AgGridLowdefy/e2e.js';
21
+ export { default as AgGridLowdefyInput } from './blocks/AgGridLowdefyInput/e2e.js';
20
22
  export { default as AgGridMaterial } from './blocks/AgGridMaterial/e2e.js';
package/dist/metas.js CHANGED
@@ -17,4 +17,6 @@ export { default as AgGridBalham } from './blocks/AgGridBalham/meta.js';
17
17
  export { default as AgGridInputAlpine } from './blocks/AgGridInputAlpine/meta.js';
18
18
  export { default as AgGridInputBalham } from './blocks/AgGridInputBalham/meta.js';
19
19
  export { default as AgGridInputMaterial } from './blocks/AgGridInputMaterial/meta.js';
20
+ export { default as AgGridLowdefy } from './blocks/AgGridLowdefy/meta.js';
21
+ export { default as AgGridLowdefyInput } from './blocks/AgGridLowdefyInput/meta.js';
20
22
  export { default as AgGridMaterial } from './blocks/AgGridMaterial/meta.js';
@@ -0,0 +1,165 @@
1
+ /*
2
+ Copyright 2020-2026 Lowdefy, Inc
3
+
4
+ Licensed under the Apache License, Version 2.0 (the "License");
5
+ you may not use this file except in compliance with the License.
6
+ You may obtain a copy of the License at
7
+
8
+ http://www.apache.org/licenses/LICENSE-2.0
9
+
10
+ Unless required by applicable law or agreed to in writing, software
11
+ distributed under the License is distributed on an "AS IS" BASIS,
12
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ See the License for the specific language governing permissions and
14
+ limitations under the License.
15
+ */ import { useMemo } from 'react';
16
+ import { themeAlpine, themeBalham, themeMaterial, themeQuartz } from 'ag-grid-community';
17
+ import { type } from '@lowdefy/helpers';
18
+ // Mirrors antd Table's small / middle / default densities. spacing, rowHeight and headerHeight feed
19
+ // the theme size variants; avatarSize and avatarFontSize feed the wrapper's inline CSS custom
20
+ // properties. One table serves both consumers.
21
+ const SIZES = {
22
+ small: {
23
+ spacing: 4,
24
+ rowHeight: 36,
25
+ headerHeight: 36,
26
+ avatarSize: 20,
27
+ avatarFontSize: 10
28
+ },
29
+ middle: {
30
+ spacing: 6,
31
+ rowHeight: 44,
32
+ headerHeight: 44,
33
+ avatarSize: 24,
34
+ avatarFontSize: 12
35
+ },
36
+ large: {
37
+ spacing: 8,
38
+ rowHeight: 54,
39
+ headerHeight: 54,
40
+ avatarSize: 28,
41
+ avatarFontSize: 14
42
+ }
43
+ };
44
+ // Every colour is a var(--ant-*) reference rather than a resolved value, so antd's cssVar mode
45
+ // regenerates the grid's colours on each theme or dark-mode change with no JS.
46
+ //
47
+ // Four of these tokens carry a fallback chain even though antd's cssVar mode emits its whole alias
48
+ // token set on `.lowdefy` regardless of which components a page renders — so in practice the primary
49
+ // --ant-* reference always resolves and the fallback never fires. The chains are defensive, not
50
+ // load-bearing: they guard against an antd alias no longer being emitted. That defensiveness is not
51
+ // free — tooltipBackgroundColor's and modalOverlayBackgroundColor's fallbacks land on the grid's
52
+ // normal surface colour, which would flatten the tooltip onto the grid and make the loading mask
53
+ // opaque if either ever fired. They stay because removing them is not this fix's call.
54
+ //
55
+ // Applied to all four bases: this is what the antd CSS overlay (src/ag-grid-antd.module.css) imposes
56
+ // on the six original theme blocks today, fontFamily / fontSize / oddRowBackgroundColor included; its
57
+ // --ag-* colour block is superseded by these params once that file's colours are removed.
58
+ const antdParams = {
59
+ accentColor: 'var(--ant-color-primary)',
60
+ backgroundColor: 'var(--ant-color-bg-container)',
61
+ foregroundColor: 'var(--ant-color-text)',
62
+ borderColor: 'var(--ant-color-border-secondary)',
63
+ chromeBackgroundColor: 'var(--ant-color-fill-quaternary)',
64
+ headerBackgroundColor: 'var(--ant-color-fill-quaternary)',
65
+ headerTextColor: 'var(--ant-color-text)',
66
+ headerCellHoverBackgroundColor: 'var(--ant-color-fill-tertiary)',
67
+ oddRowBackgroundColor: 'var(--ant-color-fill-quaternary)',
68
+ rowHoverColor: 'var(--ant-color-fill-tertiary)',
69
+ selectedRowBackgroundColor: 'var(--ant-color-primary-bg)',
70
+ checkboxCheckedBackgroundColor: 'var(--ant-color-primary)',
71
+ checkboxUncheckedBorderColor: 'var(--ant-color-border)',
72
+ fontFamily: 'var(--ant-font-family)',
73
+ fontSize: 'var(--ant-font-size)',
74
+ menuBackgroundColor: 'var(--ant-color-bg-elevated, var(--ant-color-bg-container))',
75
+ menuShadow: 'var(--ant-box-shadow-secondary)',
76
+ popupShadow: 'var(--ant-box-shadow-secondary)',
77
+ // dropdownShadow and cellEditingShadow both ref cardShadow, whose v33 default is a hardcoded
78
+ // light-mode literal, so leaving it unset renders wrong in dark mode.
79
+ cardShadow: 'var(--ant-box-shadow-secondary)',
80
+ tooltipBackgroundColor: 'var(--ant-color-bg-spotlight, var(--ant-color-bg-container))',
81
+ // AG Grid's default tooltipTextColor refs textColor, which foregroundColor above sets to antd's
82
+ // normal (non-inverted) text colour — unreadable against the spotlight surface tooltipBackgroundColor
83
+ // uses. antd always pairs colorBgSpotlight with colorTextLightSolid, a token that is #fff in both
84
+ // light and dark mode, so the fallback here is a literal #fff rather than another --ant-* alias:
85
+ // aliasing to e.g. --ant-color-text would just reintroduce this same inversion.
86
+ tooltipTextColor: 'var(--ant-color-text-light-solid, #fff)',
87
+ modalOverlayBackgroundColor: 'var(--ant-color-bg-mask, var(--ant-color-bg-container))',
88
+ // Not a colour. AG Grid's own dark value lives under a data-ag-theme-mode="dark" attribute Lowdefy
89
+ // never sets, and this param has no antd token to ride on, so the decision is handed to the
90
+ // document and set as color-scheme on <html> from the app's dark-mode state.
91
+ browserColorScheme: 'inherit'
92
+ };
93
+ // Lowdefy blocks only — the four structural choices the antd overlay never made. Applying these to a
94
+ // legacy base would overwrite the params that base sets to define itself (Balham's borderRadius: 2 and
95
+ // headerFontWeight: 'bold', Material's borderRadius: 0) and, because a param set in the default mode
96
+ // is deleted from every non-default mode, erase that base's light/dark variants for those names too.
97
+ const lowdefyParams = {
98
+ headerFontWeight: 600,
99
+ borderRadius: 'var(--ant-border-radius)',
100
+ wrapperBorderRadius: 'var(--ant-border-radius-lg, var(--ant-border-radius, 8px))',
101
+ oddRowBackgroundColor: 'transparent'
102
+ };
103
+ const base = themeQuartz.withParams({
104
+ ...antdParams,
105
+ ...lowdefyParams
106
+ });
107
+ // Sizes differ only in spacing and heights, matching antd, where size changes padding rather than
108
+ // the type scale. Built once at module scope so switching size only swaps which object is passed.
109
+ const themes = Object.fromEntries(Object.entries(SIZES).map(([size, { spacing, rowHeight, headerHeight }])=>[
110
+ size,
111
+ base.withParams({
112
+ spacing,
113
+ rowHeight,
114
+ headerHeight
115
+ })
116
+ ]));
117
+ // Bounded by the number of distinct bad values in the app's config, not by render count.
118
+ const warned = new Set();
119
+ // Object.hasOwn rather than `in`: `in` walks the prototype chain, so size: 'toString' would resolve
120
+ // themes['toString'] to a function and AG Grid would be handed a function as its theme.
121
+ //
122
+ // size is normalised to a string before the hasOwn check, the warned Set and the message: a
123
+ // non-primitive size (e.g. an object or array from a config mistake) is a fresh reference every
124
+ // render, so keying on the raw value would warn once per render instead of once per distinct value.
125
+ const resolveSize = (size)=>{
126
+ if (type.isNone(size)) return 'middle';
127
+ const key = String(size);
128
+ if (Object.hasOwn(SIZES, key)) return key;
129
+ if (!warned.has(key)) {
130
+ warned.add(key);
131
+ console.warn(`Lowdefy AG Grid property "size" received "${key}", which is not a valid size. Use one of ${Object.keys(SIZES).join(', ')}. Falling back to "middle".`);
132
+ }
133
+ return 'middle';
134
+ };
135
+ const themeForSize = (size)=>themes[resolveSize(size)];
136
+ const sizeConfig = (size)=>SIZES[resolveSize(size)];
137
+ // The six original blocks take antdParams and only antdParams, on AG Grid's prebuilt reproductions of
138
+ // their file themes. Their type scale, radii, header weight and zebra come from the base theme, which
139
+ // is what keeps them recognisably Balham / Alpine / Material.
140
+ const themeBalhamAntd = themeBalham.withParams(antdParams);
141
+ const themeAlpineAntd = themeAlpine.withParams(antdParams);
142
+ // Material's styleMaterial part sets its own primaryColor and refs it for the tab underline, button
143
+ // text, input focus border and cell editing border. antdParams sets accentColor, a different param,
144
+ // so without this those stay Material indigo. primaryColor exists only on Material's param type, so
145
+ // the shared map cannot carry it.
146
+ const themeMaterialAntd = themeMaterial.withParams({
147
+ ...antdParams,
148
+ primaryColor: 'var(--ant-color-primary)'
149
+ });
150
+ // Returns the base object untouched when there is nothing to merge, so the module-scope themes stay
151
+ // shared and identity-stable. An empty object counts as absent: {} is what an operator-driven
152
+ // themeParams produces when nothing applies. type.isObject rejects anything that is not a plain
153
+ // object (a string, array, number or boolean from a config mistake) instead of letting
154
+ // Object.keys coerce it — Object.keys('dark') is truthy and would make withParams emit junk
155
+ // --ag-0 / --ag-1 style variables from the string's characters. Keyed on the serialised params
156
+ // rather than object identity because Lowdefy re-evaluates block properties each render, so
157
+ // themeParams is a fresh reference every time.
158
+ const useGridTheme = (baseTheme, themeParams)=>{
159
+ const key = type.isObject(themeParams) && Object.keys(themeParams).length ? JSON.stringify(themeParams) : null;
160
+ return useMemo(()=>key ? baseTheme.withParams(JSON.parse(key)) : baseTheme, [
161
+ baseTheme,
162
+ key
163
+ ]);
164
+ };
165
+ export { SIZES, sizeConfig, themeAlpineAntd, themeBalhamAntd, themeForSize, themeMaterialAntd, useGridTheme };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lowdefy/blocks-aggrid",
3
- "version": "5.5.0",
3
+ "version": "5.6.0",
4
4
  "license": "Apache-2.0",
5
5
  "description": "AgGrid Blocks for Lowdefy.",
6
6
  "homepage": "https://lowdefy.com",
@@ -44,14 +44,11 @@
44
44
  "dist/*"
45
45
  ],
46
46
  "dependencies": {
47
- "@ag-grid-community/client-side-row-model": "32.3.9",
48
- "@ag-grid-community/core": "32.3.9",
49
- "@ag-grid-community/csv-export": "32.3.9",
50
- "@ag-grid-community/react": "32.3.9",
51
- "@ag-grid-community/styles": "32.3.9",
52
- "@lowdefy/block-utils": "5.5.0",
53
- "@lowdefy/blocks-antd": "5.5.0",
54
- "@lowdefy/helpers": "5.5.0"
47
+ "@lowdefy/block-utils": "5.6.0",
48
+ "@lowdefy/blocks-antd": "5.6.0",
49
+ "@lowdefy/helpers": "5.6.0",
50
+ "ag-grid-community": "33.3.2",
51
+ "ag-grid-react": "33.3.2"
55
52
  },
56
53
  "peerDependencies": {
57
54
  "@ant-design/icons": ">=6",
@@ -61,8 +58,8 @@
61
58
  "react-dom": ">=18"
62
59
  },
63
60
  "devDependencies": {
64
- "@lowdefy/block-dev-e2e": "5.5.0",
65
- "@lowdefy/e2e-utils": "5.5.0",
61
+ "@lowdefy/block-dev-e2e": "5.6.0",
62
+ "@lowdefy/e2e-utils": "5.6.0",
66
63
  "@playwright/test": "1.50.1",
67
64
  "@swc/cli": "0.8.0",
68
65
  "@swc/core": "1.15.18",