@lowdefy/blocks-aggrid 5.6.0 → 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/dist/AgGrid.js +8 -2
- package/dist/AgGridInput.js +7 -2
- package/dist/blocks/AgGridAlpine/gallery.yaml +1451 -0
- package/dist/blocks/AgGridAlpine/tests/AgGridAlpine.e2e.yaml +310 -0
- package/dist/blocks/AgGridBalham/gallery.yaml +645 -0
- package/dist/blocks/AgGridBalham/tests/AgGridBalham.e2e.yaml +594 -0
- package/dist/blocks/AgGridInputAlpine/gallery.yaml +362 -0
- package/dist/blocks/AgGridInputAlpine/tests/AgGridInputAlpine.e2e.yaml +365 -0
- package/dist/blocks/AgGridInputBalham/gallery.yaml +362 -0
- package/dist/blocks/AgGridInputBalham/tests/AgGridInputBalham.e2e.yaml +365 -0
- package/dist/blocks/AgGridInputMaterial/gallery.yaml +362 -0
- package/dist/blocks/AgGridInputMaterial/tests/AgGridInputMaterial.e2e.yaml +365 -0
- package/dist/blocks/AgGridLowdefy/gallery.yaml +1242 -0
- package/dist/blocks/AgGridLowdefy/tests/AgGridLowdefy.e2e.yaml +667 -0
- package/dist/blocks/AgGridLowdefyInput/gallery.yaml +489 -0
- package/dist/blocks/AgGridLowdefyInput/tests/AgGridLowdefyInput.e2e.yaml +686 -0
- package/dist/blocks/AgGridMaterial/gallery.yaml +645 -0
- package/dist/blocks/AgGridMaterial/tests/AgGridMaterial.e2e.yaml +310 -0
- package/dist/cellRenderers/MenuCell.js +110 -0
- package/dist/cellRenderers/index.js +2 -0
- package/dist/createDisplayMeta.js +94 -0
- package/dist/processColDefs.js +75 -32
- package/dist/useColDefs.js +65 -0
- package/package.json +12 -12
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,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,25 +44,25 @@
|
|
|
44
44
|
"dist/*"
|
|
45
45
|
],
|
|
46
46
|
"dependencies": {
|
|
47
|
-
"@lowdefy/block-utils": "
|
|
48
|
-
"@lowdefy/blocks-antd": "
|
|
49
|
-
"@lowdefy/helpers": "
|
|
47
|
+
"@lowdefy/block-utils": "6.0.0",
|
|
48
|
+
"@lowdefy/blocks-antd": "6.0.0",
|
|
49
|
+
"@lowdefy/helpers": "6.0.0",
|
|
50
50
|
"ag-grid-community": "33.3.2",
|
|
51
51
|
"ag-grid-react": "33.3.2"
|
|
52
52
|
},
|
|
53
53
|
"peerDependencies": {
|
|
54
|
-
"@ant-design/icons": "
|
|
54
|
+
"@ant-design/icons": "6.1.0",
|
|
55
55
|
"antd": ">=6",
|
|
56
|
-
"dayjs": "
|
|
56
|
+
"dayjs": "1.11.20",
|
|
57
57
|
"react": ">=18",
|
|
58
58
|
"react-dom": ">=18"
|
|
59
59
|
},
|
|
60
60
|
"devDependencies": {
|
|
61
|
-
"@lowdefy/block-dev-e2e": "
|
|
62
|
-
"@lowdefy/e2e-utils": "
|
|
63
|
-
"@playwright/test": "1.
|
|
64
|
-
"@swc/cli": "0.8.
|
|
65
|
-
"@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",
|
|
66
66
|
"copyfiles": "2.4.1"
|
|
67
67
|
},
|
|
68
68
|
"publishConfig": {
|
|
@@ -71,7 +71,7 @@
|
|
|
71
71
|
"scripts": {
|
|
72
72
|
"build": "swc src --out-dir dist --config-file ../../../../.swcrc --cli-config-file ../../../../.swc-cli.json && pnpm copyfiles",
|
|
73
73
|
"clean": "rm -rf dist",
|
|
74
|
-
"copyfiles": "copyfiles -u 1 \"./src/**/*\" dist -e \"./src/**/*.js\" -e \"./src/**/*.
|
|
74
|
+
"copyfiles": "copyfiles -u 1 \"./src/**/*\" dist -e \"./src/**/*.js\" -e \"./src/**/*.snap\"",
|
|
75
75
|
"e2e": "playwright test --config e2e/playwright.config.js",
|
|
76
76
|
"e2e:ui": "playwright test --config e2e/playwright.config.js --ui"
|
|
77
77
|
}
|