@lowdefy/blocks-aggrid 5.5.1 → 6.0.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 +58 -19
- package/dist/AgGrid.js +22 -14
- package/dist/AgGridInput.js +21 -14
- package/dist/ag-grid-antd.module.css +18 -49
- package/dist/blocks/AgGridAlpine/AgGridAlpine.js +4 -3
- package/dist/blocks/AgGridAlpine/e2e.js +1 -1
- package/dist/blocks/AgGridAlpine/gallery.yaml +1451 -0
- package/dist/blocks/AgGridAlpine/tests/AgGridAlpine.e2e.yaml +310 -0
- package/dist/blocks/AgGridBalham/AgGridBalham.js +4 -3
- package/dist/blocks/AgGridBalham/e2e.js +1 -1
- package/dist/blocks/AgGridBalham/gallery.yaml +645 -0
- package/dist/blocks/AgGridBalham/tests/AgGridBalham.e2e.yaml +594 -0
- package/dist/blocks/AgGridInputAlpine/AgGridInputAlpine.js +3 -2
- package/dist/blocks/AgGridInputAlpine/e2e.js +1 -1
- package/dist/blocks/AgGridInputAlpine/gallery.yaml +362 -0
- package/dist/blocks/AgGridInputAlpine/tests/AgGridInputAlpine.e2e.yaml +365 -0
- package/dist/blocks/AgGridInputBalham/AgGridInputBalham.js +3 -2
- package/dist/blocks/AgGridInputBalham/e2e.js +1 -1
- package/dist/blocks/AgGridInputBalham/gallery.yaml +362 -0
- package/dist/blocks/AgGridInputBalham/tests/AgGridInputBalham.e2e.yaml +365 -0
- package/dist/blocks/AgGridInputMaterial/AgGridInputMaterial.js +3 -2
- package/dist/blocks/AgGridInputMaterial/e2e.js +1 -1
- package/dist/blocks/AgGridInputMaterial/gallery.yaml +362 -0
- package/dist/blocks/AgGridInputMaterial/tests/AgGridInputMaterial.e2e.yaml +365 -0
- package/dist/blocks/AgGridLowdefy/AgGridLowdefy.js +45 -0
- package/dist/blocks/AgGridLowdefy/e2e.js +16 -0
- package/dist/blocks/AgGridLowdefy/gallery.yaml +1242 -0
- package/dist/blocks/AgGridLowdefy/meta.js +18 -0
- package/dist/blocks/AgGridLowdefy/tests/AgGridLowdefy.e2e.yaml +667 -0
- package/dist/blocks/AgGridLowdefyInput/AgGridLowdefyInput.js +48 -0
- package/dist/blocks/AgGridLowdefyInput/e2e.js +16 -0
- package/dist/blocks/AgGridLowdefyInput/gallery.yaml +489 -0
- package/dist/blocks/AgGridLowdefyInput/meta.js +18 -0
- package/dist/blocks/AgGridLowdefyInput/tests/AgGridLowdefyInput.e2e.yaml +686 -0
- package/dist/blocks/AgGridMaterial/AgGridMaterial.js +4 -3
- package/dist/blocks/AgGridMaterial/e2e.js +1 -1
- package/dist/blocks/AgGridMaterial/gallery.yaml +645 -0
- package/dist/blocks/AgGridMaterial/tests/AgGridMaterial.e2e.yaml +310 -0
- package/dist/blocks.js +2 -0
- package/dist/cellRenderers/MenuCell.js +110 -0
- package/dist/cellRenderers/index.js +2 -0
- package/dist/createAgGridDisplayHelper.js +1 -2
- package/dist/createAgGridInputHelper.js +1 -2
- package/dist/createDisplayMeta.js +115 -4
- package/dist/createInputMeta.js +20 -3
- package/dist/e2e.js +2 -0
- package/dist/metas.js +2 -0
- package/dist/processColDefs.js +75 -32
- package/dist/theme/themeLowdefy.js +165 -0
- package/dist/useColDefs.js +65 -0
- package/package.json +14 -17
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';
|
package/dist/processColDefs.js
CHANGED
|
@@ -16,7 +16,7 @@
|
|
|
16
16
|
import { type } from '@lowdefy/helpers';
|
|
17
17
|
import { getCellRenderer } from './cellRenderers/index.js';
|
|
18
18
|
import createEllipsisCell from './cellRenderers/EllipsisCell.js';
|
|
19
|
-
function applyEllipsis(colDef, ellipsis) {
|
|
19
|
+
function applyEllipsis(colDef, ellipsis, makeEllipsisRenderer) {
|
|
20
20
|
if (!type.isInt(ellipsis) || ellipsis < 1) return colDef;
|
|
21
21
|
const clampClass = `lf-ellipsis-${Math.min(ellipsis, 6)}`;
|
|
22
22
|
const existingClass = colDef.cellClass;
|
|
@@ -34,7 +34,7 @@ function applyEllipsis(colDef, ellipsis) {
|
|
|
34
34
|
// ag-grid's internal cell wrappers. Skip if a cellRenderer is already set
|
|
35
35
|
// (user or built-in cell.type takes precedence and can opt in via CSS).
|
|
36
36
|
if (!colDef.cellRenderer) {
|
|
37
|
-
next.cellRenderer =
|
|
37
|
+
next.cellRenderer = makeEllipsisRenderer();
|
|
38
38
|
}
|
|
39
39
|
return next;
|
|
40
40
|
}
|
|
@@ -66,41 +66,76 @@ function applyAlignment(colDef, cell) {
|
|
|
66
66
|
headerClass
|
|
67
67
|
};
|
|
68
68
|
}
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
69
|
+
// A cellRenderer is a React element type, so a new function is a different
|
|
70
|
+
// component: CellCtrl.refreshCellRenderer bails when `cellRendererClass !==
|
|
71
|
+
// componentClass`, and the React cell comp re-keys. Building the renderers fresh on
|
|
72
|
+
// every render therefore unmounted every cell whenever anything re-rendered the
|
|
73
|
+
// block, destroying whatever a cell was holding — an open popup, a focused input, a
|
|
74
|
+
// half-typed value in the selector / textInput / paragraphInput cells.
|
|
75
|
+
//
|
|
76
|
+
// So the adapter installed on the colDef is created once per column and kept, and
|
|
77
|
+
// the closure it calls is replaced in place. ag-grid keeps the cell; the cell
|
|
78
|
+
// renders the current config.
|
|
79
|
+
function stableRenderer(entry, slot, render) {
|
|
80
|
+
let stable = entry[slot];
|
|
81
|
+
if (!stable) {
|
|
82
|
+
const box = {
|
|
83
|
+
render
|
|
84
|
+
};
|
|
85
|
+
// ag-grid calls the renderer as a React function component when returned directly.
|
|
86
|
+
function CellRendererAdapter(params) {
|
|
87
|
+
return box.render(params);
|
|
88
|
+
}
|
|
89
|
+
stable = {
|
|
90
|
+
box,
|
|
91
|
+
Adapter: CellRendererAdapter
|
|
92
|
+
};
|
|
93
|
+
entry[slot] = stable;
|
|
94
|
+
}
|
|
95
|
+
stable.box.render = render;
|
|
96
|
+
return stable.Adapter;
|
|
97
|
+
}
|
|
98
|
+
// Keyed by colId or field so an adapter survives a column reorder, falling back to
|
|
99
|
+
// position for columns that declare neither. A key already taken in this pass gets a
|
|
100
|
+
// suffix, so two columns sharing a field do not share an adapter.
|
|
101
|
+
function colKey(col, index, prefix, seen) {
|
|
102
|
+
const id = type.isString(col.colId) ? col.colId : type.isString(col.field) ? col.field : `${index}`;
|
|
103
|
+
const base = `${prefix}${id}`;
|
|
104
|
+
let key = base;
|
|
105
|
+
let n = 1;
|
|
106
|
+
while(seen.has(key)){
|
|
107
|
+
key = `${base}#${n}`;
|
|
108
|
+
n += 1;
|
|
109
|
+
}
|
|
110
|
+
seen.add(key);
|
|
111
|
+
return key;
|
|
81
112
|
}
|
|
82
|
-
function recProcessColDefs(columnDefs, methods, components) {
|
|
83
|
-
return columnDefs.map((col)=>{
|
|
113
|
+
function recProcessColDefs(columnDefs, methods, components, cache, seen, prefix) {
|
|
114
|
+
return columnDefs.map((col, index)=>{
|
|
115
|
+
const key = colKey(col, index, prefix, seen);
|
|
116
|
+
const entry = cache.get(key) ?? {};
|
|
117
|
+
cache.set(key, entry);
|
|
84
118
|
const newColDef = {};
|
|
85
119
|
if (type.isArray(col.children)) {
|
|
86
|
-
newColDef.children = recProcessColDefs(col.children, methods, components);
|
|
120
|
+
newColDef.children = recProcessColDefs(col.children, methods, components, cache, seen, `${key}/`);
|
|
87
121
|
}
|
|
88
122
|
if (type.isObject(col.cell) && type.isString(col.cell.type)) {
|
|
89
|
-
const
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
123
|
+
const Renderer = getCellRenderer(col.cell.type);
|
|
124
|
+
if (Renderer) {
|
|
125
|
+
const cell = col.cell;
|
|
126
|
+
newColDef.cellRenderer = stableRenderer(entry, 'cell', (params)=>Renderer({
|
|
127
|
+
...params,
|
|
128
|
+
cellConfig: cell,
|
|
129
|
+
methods,
|
|
130
|
+
components
|
|
131
|
+
}));
|
|
96
132
|
}
|
|
97
133
|
} else if (type.isFunction(col.cellRenderer)) {
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
html:
|
|
134
|
+
const cellRenderer = col.cellRenderer;
|
|
135
|
+
newColDef.cellRenderer = stableRenderer(entry, 'cell', (params)=>renderHtml({
|
|
136
|
+
html: cellRenderer(params),
|
|
101
137
|
methods
|
|
102
|
-
});
|
|
103
|
-
};
|
|
138
|
+
}));
|
|
104
139
|
}
|
|
105
140
|
const merged = {
|
|
106
141
|
...col,
|
|
@@ -110,10 +145,18 @@ function recProcessColDefs(columnDefs, methods, components) {
|
|
|
110
145
|
delete merged.cell;
|
|
111
146
|
delete merged.ellipsis;
|
|
112
147
|
const aligned = applyAlignment(merged, col.cell);
|
|
113
|
-
return applyEllipsis(aligned, col.ellipsis);
|
|
148
|
+
return applyEllipsis(aligned, col.ellipsis, ()=>stableRenderer(entry, 'ellipsis', createEllipsisCell(col.ellipsis)));
|
|
114
149
|
});
|
|
115
150
|
}
|
|
116
|
-
function processColDefs(columnDefs = [], methods, components) {
|
|
117
|
-
|
|
151
|
+
function processColDefs(columnDefs = [], methods, components, cache = new Map()) {
|
|
152
|
+
const seen = new Set();
|
|
153
|
+
const processed = recProcessColDefs(columnDefs, methods, components, cache, seen, '');
|
|
154
|
+
// Drop columns that are no longer defined, so a grid whose columns come and go does
|
|
155
|
+
// not accumulate adapters. A column that returns gets a fresh one, which is correct
|
|
156
|
+
// — its cells were unmounted with it.
|
|
157
|
+
for (const key of cache.keys()){
|
|
158
|
+
if (!seen.has(key)) cache.delete(key);
|
|
159
|
+
}
|
|
160
|
+
return processed;
|
|
118
161
|
}
|
|
119
162
|
export default processColDefs;
|
|
@@ -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 };
|
|
@@ -0,0 +1,65 @@
|
|
|
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 { useEffect, useRef } from 'react';
|
|
16
|
+
import { type } from '@lowdefy/helpers';
|
|
17
|
+
import processColDefs from './processColDefs.js';
|
|
18
|
+
// Fingerprint the authored columnDefs, functions included. JSON.stringify drops
|
|
19
|
+
// function values unless a replacer returns something for them, and a cellRenderer or
|
|
20
|
+
// valueGetter built by an operator is a new function on every evaluation — so identity
|
|
21
|
+
// is the only signal available that one of them changed.
|
|
22
|
+
function fingerprint(columnDefs) {
|
|
23
|
+
const functions = [];
|
|
24
|
+
const json = JSON.stringify(columnDefs, (_key, value)=>{
|
|
25
|
+
if (type.isFunction(value)) {
|
|
26
|
+
functions.push(value);
|
|
27
|
+
return `__fn__${functions.length - 1}`;
|
|
28
|
+
}
|
|
29
|
+
return value;
|
|
30
|
+
});
|
|
31
|
+
return {
|
|
32
|
+
json,
|
|
33
|
+
functions
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
function unchanged(previous, next) {
|
|
37
|
+
if (!previous) return false;
|
|
38
|
+
if (previous.json !== next.json) return false;
|
|
39
|
+
if (previous.functions.length !== next.functions.length) return false;
|
|
40
|
+
return previous.functions.every((fn, index)=>fn === next.functions[index]);
|
|
41
|
+
}
|
|
42
|
+
// Cell renderers keep their identity across renders (see processColDefs), which is
|
|
43
|
+
// what stops ag-grid destroying a cell mid-interaction — but it also means nothing
|
|
44
|
+
// replaces a cell when its column definition changes. ag-grid refreshes body cells on
|
|
45
|
+
// a data change; it does not listen for colDefChanged. So ask it: refreshCells
|
|
46
|
+
// re-renders the mounted cells in place with the new definition. It passes
|
|
47
|
+
// `newData: false`, so React keeps the instances, and with them whatever the cell
|
|
48
|
+
// was holding.
|
|
49
|
+
function useColDefs({ columnDefs, methods, components, gridRef }) {
|
|
50
|
+
const cache = useRef(new Map());
|
|
51
|
+
const previous = useRef();
|
|
52
|
+
const processed = processColDefs(columnDefs, methods, components, cache.current);
|
|
53
|
+
useEffect(()=>{
|
|
54
|
+
const next = fingerprint(columnDefs);
|
|
55
|
+
const first = previous.current === undefined;
|
|
56
|
+
const same = unchanged(previous.current, next);
|
|
57
|
+
previous.current = next;
|
|
58
|
+
if (first || same) return;
|
|
59
|
+
gridRef.current?.api?.refreshCells({
|
|
60
|
+
force: true
|
|
61
|
+
});
|
|
62
|
+
});
|
|
63
|
+
return processed;
|
|
64
|
+
}
|
|
65
|
+
export default useColDefs;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lowdefy/blocks-aggrid",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "6.0.0",
|
|
4
4
|
"license": "Apache-2.0",
|
|
5
5
|
"description": "AgGrid Blocks for Lowdefy.",
|
|
6
6
|
"homepage": "https://lowdefy.com",
|
|
@@ -44,28 +44,25 @@
|
|
|
44
44
|
"dist/*"
|
|
45
45
|
],
|
|
46
46
|
"dependencies": {
|
|
47
|
-
"@
|
|
48
|
-
"@
|
|
49
|
-
"@
|
|
50
|
-
"
|
|
51
|
-
"
|
|
52
|
-
"@lowdefy/block-utils": "5.5.1",
|
|
53
|
-
"@lowdefy/blocks-antd": "5.5.1",
|
|
54
|
-
"@lowdefy/helpers": "5.5.1"
|
|
47
|
+
"@lowdefy/block-utils": "6.0.0",
|
|
48
|
+
"@lowdefy/blocks-antd": "6.0.0",
|
|
49
|
+
"@lowdefy/helpers": "6.0.0",
|
|
50
|
+
"ag-grid-community": "33.3.2",
|
|
51
|
+
"ag-grid-react": "33.3.2"
|
|
55
52
|
},
|
|
56
53
|
"peerDependencies": {
|
|
57
|
-
"@ant-design/icons": "
|
|
54
|
+
"@ant-design/icons": "6.1.0",
|
|
58
55
|
"antd": ">=6",
|
|
59
|
-
"dayjs": "
|
|
56
|
+
"dayjs": "1.11.20",
|
|
60
57
|
"react": ">=18",
|
|
61
58
|
"react-dom": ">=18"
|
|
62
59
|
},
|
|
63
60
|
"devDependencies": {
|
|
64
|
-
"@lowdefy/block-dev-e2e": "
|
|
65
|
-
"@lowdefy/e2e-utils": "
|
|
66
|
-
"@playwright/test": "1.
|
|
67
|
-
"@swc/cli": "0.8.
|
|
68
|
-
"@swc/core": "1.15.
|
|
61
|
+
"@lowdefy/block-dev-e2e": "6.0.0",
|
|
62
|
+
"@lowdefy/e2e-utils": "6.0.0",
|
|
63
|
+
"@playwright/test": "1.59.1",
|
|
64
|
+
"@swc/cli": "0.8.1",
|
|
65
|
+
"@swc/core": "1.15.32",
|
|
69
66
|
"copyfiles": "2.4.1"
|
|
70
67
|
},
|
|
71
68
|
"publishConfig": {
|
|
@@ -74,7 +71,7 @@
|
|
|
74
71
|
"scripts": {
|
|
75
72
|
"build": "swc src --out-dir dist --config-file ../../../../.swcrc --cli-config-file ../../../../.swc-cli.json && pnpm copyfiles",
|
|
76
73
|
"clean": "rm -rf dist",
|
|
77
|
-
"copyfiles": "copyfiles -u 1 \"./src/**/*\" dist -e \"./src/**/*.js\" -e \"./src/**/*.
|
|
74
|
+
"copyfiles": "copyfiles -u 1 \"./src/**/*\" dist -e \"./src/**/*.js\" -e \"./src/**/*.snap\"",
|
|
78
75
|
"e2e": "playwright test --config e2e/playwright.config.js",
|
|
79
76
|
"e2e:ui": "playwright test --config e2e/playwright.config.js --ui"
|
|
80
77
|
}
|