@singularsystems/neo-react 1.0.16 → 1.0.17
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/ReactComponents/Grid/Grid.d.ts +9 -1
- package/dist/ReactComponents/Grid/Grid.js +5 -6
- package/dist/ReactComponents/Grid/Row.d.ts +2 -0
- package/dist/ReactComponents/Grid/Row.js +10 -5
- package/dist/ReactComponents/Grid/StickyTableHeader.d.ts +5 -1
- package/dist/ReactComponents/Grid/StickyTableHeader.js +37 -8
- package/dist/ReactComponents/PropTypes.d.ts +1 -1
- package/package.json +1 -1
|
@@ -58,7 +58,10 @@ export interface IGridProps<T> extends Omit<React.HTMLProps<HTMLTableElement>, "
|
|
|
58
58
|
* This is the default unless overridden in Misc.Settings.grid
|
|
59
59
|
*/
|
|
60
60
|
isBordered?: boolean;
|
|
61
|
-
/**
|
|
61
|
+
/**
|
|
62
|
+
* When specified, every alternating row will receive a slightly darker background color.
|
|
63
|
+
* Note, this will not work correctly if your grid has child rows. See the neo react demo pages for a solution.
|
|
64
|
+
*/
|
|
62
65
|
isStriped?: boolean;
|
|
63
66
|
/** When specified, the table will have no cell borders, and the table will have no main border. */
|
|
64
67
|
isBorderless?: boolean;
|
|
@@ -79,6 +82,11 @@ export interface IGridProps<T> extends Omit<React.HTMLProps<HTMLTableElement>, "
|
|
|
79
82
|
* Note: if your app has a fixed header, you need to specify this in the global neo settings.
|
|
80
83
|
*/
|
|
81
84
|
stickyHeader?: boolean;
|
|
85
|
+
/**
|
|
86
|
+
* When true, the index parameter passed to the render function will be set.
|
|
87
|
+
* This has performance implications, as each row needs to be re-rendered on sorting or insertion of items.
|
|
88
|
+
*/
|
|
89
|
+
enableRowIndexes?: boolean;
|
|
82
90
|
}
|
|
83
91
|
export default class Grid<T> extends React.Component<IGridProps<T>> {
|
|
84
92
|
static contextType: React.Context<import("../../React/DataView").DataViewContextParams<unknown>>;
|
|
@@ -45,7 +45,7 @@ var Grid = /** @class */ (function (_super) {
|
|
|
45
45
|
};
|
|
46
46
|
Grid.prototype.render = function () {
|
|
47
47
|
var _this = this;
|
|
48
|
-
var _a = this.props, items = _a.items, showAddButton = _a.showAddButton, addButton = _a.addButton, filterPredicate = _a.filterPredicate, keyProperty = _a.keyProperty, allowSort = _a.allowSort, expandAll = _a.expandAll, collapseAll = _a.collapseAll, initialSort = _a.initialSort, initialSortAscending = _a.initialSortAscending, isBordered = _a.isBordered, isStriped = _a.isStriped, isBorderless = _a.isBorderless, showHover = _a.showHover, isSmallTable = _a.isSmallTable, footerContent = _a.footerContent, footerButtons = _a.footerButtons, stickyHeader = _a.stickyHeader, domProps = __rest(_a, ["items", "showAddButton", "addButton", "filterPredicate", "keyProperty", "allowSort", "expandAll", "collapseAll", "initialSort", "initialSortAscending", "isBordered", "isStriped", "isBorderless", "showHover", "isSmallTable", "footerContent", "footerButtons", "stickyHeader"]);
|
|
48
|
+
var _a = this.props, items = _a.items, showAddButton = _a.showAddButton, addButton = _a.addButton, filterPredicate = _a.filterPredicate, keyProperty = _a.keyProperty, allowSort = _a.allowSort, expandAll = _a.expandAll, collapseAll = _a.collapseAll, initialSort = _a.initialSort, initialSortAscending = _a.initialSortAscending, isBordered = _a.isBordered, isStriped = _a.isStriped, isBorderless = _a.isBorderless, showHover = _a.showHover, isSmallTable = _a.isSmallTable, footerContent = _a.footerContent, footerButtons = _a.footerButtons, stickyHeader = _a.stickyHeader, enableRowIndexes = _a.enableRowIndexes, domProps = __rest(_a, ["items", "showAddButton", "addButton", "filterPredicate", "keyProperty", "allowSort", "expandAll", "collapseAll", "initialSort", "initialSortAscending", "isBordered", "isStriped", "isBorderless", "showHover", "isSmallTable", "footerContent", "footerButtons", "stickyHeader", "enableRowIndexes"]);
|
|
49
49
|
if (expandAll === true) {
|
|
50
50
|
this.gridContext.expandAll = true;
|
|
51
51
|
}
|
|
@@ -101,12 +101,12 @@ var Grid = /** @class */ (function (_super) {
|
|
|
101
101
|
}
|
|
102
102
|
return (React.createElement("table", __assign({}, domProps, { className: className, ref: this.domRef }),
|
|
103
103
|
React.createElement(GridContext.Provider, { value: this.gridContext },
|
|
104
|
-
React.createElement(TableSection, { type: "header" }, this.headerItem && this.props.children(this.headerItem, this.headerItem.meta, true)),
|
|
105
|
-
React.createElement(TableSection, { type: "body" }, this.gridContext.dataView.getItems().map(function (item) { return (React.createElement(ItemGroup, { item: item, key: keyProperty ? item[keyProperty] : item.entityIdentifier, template: _this.props.children })); })),
|
|
104
|
+
React.createElement(TableSection, { type: "header" }, this.headerItem && this.props.children(this.headerItem, this.headerItem.meta, true, -1)),
|
|
105
|
+
React.createElement(TableSection, { type: "body" }, this.gridContext.dataView.getItems().map(function (item, index) { return (React.createElement(ItemGroup, { index: enableRowIndexes ? index : 0, item: item, key: keyProperty ? item[keyProperty] : item.entityIdentifier, template: _this.props.children })); })),
|
|
106
106
|
React.createElement(Observer, null, function () {
|
|
107
107
|
return React.createElement(React.Fragment, null, (showAddButton || addButton || footerButtons || _this.gridContext.hasSummaries || footerContent !== undefined) &&
|
|
108
108
|
React.createElement(TableSection, { type: "footer" },
|
|
109
|
-
_this.gridContext.hasSummaries && _this.headerItem && _this.props.children(_this.headerItem, _this.headerItem.meta, true),
|
|
109
|
+
_this.gridContext.hasSummaries && _this.headerItem && _this.props.children(_this.headerItem, _this.headerItem.meta, true, -1),
|
|
110
110
|
footerContent !== undefined && footerContent(_this.gridContext.dataView.getItems()),
|
|
111
111
|
(showAddButton || addButton || footerButtons) &&
|
|
112
112
|
React.createElement(AddButtonRow, { addButton: addButton, showAddButton: showAddButton, additionalContent: footerButtons })));
|
|
@@ -207,8 +207,7 @@ var ItemGroup = /** @class */ (function (_super) {
|
|
|
207
207
|
}
|
|
208
208
|
ItemGroup.prototype.render = function () {
|
|
209
209
|
this.context.currentItem = this.props.item;
|
|
210
|
-
|
|
211
|
-
return (this.props.template(this.props.item, this.props.item.meta, false));
|
|
210
|
+
return this.props.template(this.props.item, this.props.item.meta, false, this.props.index);
|
|
212
211
|
};
|
|
213
212
|
ItemGroup.contextType = GridContext;
|
|
214
213
|
ItemGroup = __decorate([
|
|
@@ -13,6 +13,8 @@ interface IRowProps extends React.DetailedHTMLProps<React.HTMLAttributes<HTMLTab
|
|
|
13
13
|
* Handler for click events on header or footer rows. The section is passed as the first argument.
|
|
14
14
|
*/
|
|
15
15
|
onHeaderClick?: (section: GridSection, e: React.MouseEvent<HTMLTableRowElement, MouseEvent>) => void;
|
|
16
|
+
/** Class name that will not be applied to headers. */
|
|
17
|
+
bodyClassName?: string;
|
|
16
18
|
}
|
|
17
19
|
interface IState {
|
|
18
20
|
isExpanded: boolean;
|
|
@@ -53,7 +53,7 @@ var Row = /** @class */ (function (_super) {
|
|
|
53
53
|
Row.prototype.render = function () {
|
|
54
54
|
var _this = this;
|
|
55
55
|
_super.prototype.onRender.call(this);
|
|
56
|
-
var _a = this.props, showInHeader = _a.showInHeader, onHeaderClick = _a.onHeaderClick, domProps = __rest(_a, ["showInHeader", "onHeaderClick"]);
|
|
56
|
+
var _a = this.props, showInHeader = _a.showInHeader, onHeaderClick = _a.onHeaderClick, bodyClassName = _a.bodyClassName, domProps = __rest(_a, ["showInHeader", "onHeaderClick", "bodyClassName"]);
|
|
57
57
|
var inBody = this.section === "body";
|
|
58
58
|
if (this.stateObserver)
|
|
59
59
|
this.stateObserver.observe();
|
|
@@ -61,11 +61,16 @@ var Row = /** @class */ (function (_super) {
|
|
|
61
61
|
throw "NeoGrid.Row cannot be used outside of a NeoGrid.";
|
|
62
62
|
}
|
|
63
63
|
var expandButtonOptions = __assign({}, Misc.Settings.grid.expandButton);
|
|
64
|
-
if (inBody
|
|
65
|
-
|
|
66
|
-
|
|
64
|
+
if (inBody) {
|
|
65
|
+
if (this.expandProperty) {
|
|
66
|
+
expandButtonOptions.onClick = this.onExpandClick;
|
|
67
|
+
expandButtonOptions.icon = this.expandProperty.value ? Misc.Settings.icons.expanded : Misc.Settings.icons.collapsed;
|
|
68
|
+
}
|
|
69
|
+
if (bodyClassName) {
|
|
70
|
+
domProps.className = Utils.joinWithSpaces(domProps.className, bodyClassName);
|
|
71
|
+
}
|
|
67
72
|
}
|
|
68
|
-
|
|
73
|
+
else {
|
|
69
74
|
if (onHeaderClick) {
|
|
70
75
|
domProps.onClick = function (e) { return onHeaderClick(_this.section, e); };
|
|
71
76
|
}
|
|
@@ -11,6 +11,8 @@ export declare class StickyTableHeader {
|
|
|
11
11
|
* @param fixedElement A fixed element at the top of the screen to use as an anchor, rather than the top of the screen itself.
|
|
12
12
|
*/
|
|
13
13
|
constructor(table: HTMLTableElement, fixedElement?: HTMLElement | undefined);
|
|
14
|
+
private domObserver;
|
|
15
|
+
private originalWidths;
|
|
14
16
|
/** Parent element that may scroll, requiring a position update. */
|
|
15
17
|
private scrollElement?;
|
|
16
18
|
/** Fixed height parent element that the grid scrolls within. */
|
|
@@ -21,7 +23,9 @@ export declare class StickyTableHeader {
|
|
|
21
23
|
private handleScroll;
|
|
22
24
|
private removeCopy;
|
|
23
25
|
private onPossibleContentChange;
|
|
24
|
-
private
|
|
26
|
+
private syncColumnWidths;
|
|
27
|
+
private storeColumnWidths;
|
|
28
|
+
private restoreColumnWidths;
|
|
25
29
|
dispose(): void;
|
|
26
30
|
/**
|
|
27
31
|
* Returns the first parent element that has a scrollbar.
|
|
@@ -9,8 +9,13 @@ var StickyTableHeader = /** @class */ (function () {
|
|
|
9
9
|
* @param fixedElement A fixed element at the top of the screen to use as an anchor, rather than the top of the screen itself.
|
|
10
10
|
*/
|
|
11
11
|
function StickyTableHeader(table, fixedElement) {
|
|
12
|
+
var _this = this;
|
|
12
13
|
this.table = table;
|
|
13
14
|
this.fixedElement = fixedElement;
|
|
15
|
+
this.domObserver = new MutationObserver(function (mutations) {
|
|
16
|
+
_this.syncColumnWidths();
|
|
17
|
+
});
|
|
18
|
+
this.originalWidths = [];
|
|
14
19
|
this.headerHeight = 0;
|
|
15
20
|
if (!table.tHead) {
|
|
16
21
|
throw Error("Table must have a header section.");
|
|
@@ -46,28 +51,32 @@ var StickyTableHeader = /** @class */ (function () {
|
|
|
46
51
|
if (!this.headerCopy) {
|
|
47
52
|
// Clone the header, and re-insert it into the table. The table will then have 2 headers.
|
|
48
53
|
// The original headers position is set to "fixed" which makes it float.
|
|
49
|
-
// The
|
|
54
|
+
// The original header is floated instead of the clone because the react events are attached to these cells, and they are the cells that are visible. Without this, sorting wouldn't work.
|
|
55
|
+
// The column widths of the floating header then need to be synchronized with the header that is still inside the table layout.
|
|
50
56
|
this.headerHeight = this.header.getBoundingClientRect().height;
|
|
51
57
|
this.headerCopy = this.header.cloneNode(true);
|
|
52
58
|
this.table.insertBefore(this.headerCopy, this.header);
|
|
53
59
|
this.header.classList.add("neo-grid-fixed-header");
|
|
54
|
-
this.
|
|
60
|
+
this.storeColumnWidths();
|
|
61
|
+
this.syncColumnWidths();
|
|
62
|
+
this.domObserver.observe(this.header, { childList: true, subtree: true, attributes: false });
|
|
55
63
|
}
|
|
56
64
|
this.header.style.left = tableBounds.left + "px";
|
|
57
65
|
this.header.style.top = topBoundary + "px";
|
|
58
66
|
if (this.scrollElement) {
|
|
59
67
|
var left = this.scrollElement.scrollLeft;
|
|
60
|
-
var width = this.scrollElement.clientWidth + left;
|
|
68
|
+
var width = this.scrollElement.clientWidth + left - 1;
|
|
61
69
|
this.header.style.clipPath = "rect(0px ".concat(width, "px 100% ").concat(left, "px)");
|
|
62
70
|
}
|
|
63
71
|
}
|
|
64
72
|
else {
|
|
65
|
-
this.setColumnWidths(true);
|
|
66
73
|
this.removeCopy();
|
|
67
74
|
}
|
|
68
75
|
};
|
|
69
76
|
StickyTableHeader.prototype.removeCopy = function () {
|
|
70
77
|
if (this.headerCopy) {
|
|
78
|
+
this.domObserver.disconnect();
|
|
79
|
+
this.restoreColumnWidths();
|
|
71
80
|
this.header.classList.remove("neo-grid-fixed-header");
|
|
72
81
|
this.header.style.clipPath = "";
|
|
73
82
|
this.table.removeChild(this.headerCopy);
|
|
@@ -76,20 +85,40 @@ var StickyTableHeader = /** @class */ (function () {
|
|
|
76
85
|
};
|
|
77
86
|
StickyTableHeader.prototype.onPossibleContentChange = function () {
|
|
78
87
|
var _this = this;
|
|
79
|
-
setTimeout(function () { return _this.
|
|
88
|
+
setTimeout(function () { return _this.syncColumnWidths(); }, 0);
|
|
80
89
|
};
|
|
81
|
-
StickyTableHeader.prototype.
|
|
82
|
-
if (isRemoving === void 0) { isRemoving = false; }
|
|
90
|
+
StickyTableHeader.prototype.syncColumnWidths = function () {
|
|
83
91
|
if (this.headerCopy) {
|
|
84
92
|
for (var i = 0; i < this.header.rows.length; i++) {
|
|
85
93
|
var originalRow = this.header.rows[i], copyRow = this.headerCopy.rows[i];
|
|
94
|
+
if (originalRow.cells.length !== copyRow.cells.length) {
|
|
95
|
+
this.removeCopy();
|
|
96
|
+
this.handleScroll();
|
|
97
|
+
return;
|
|
98
|
+
}
|
|
86
99
|
for (var j = 0; j < originalRow.cells.length; j++) {
|
|
87
100
|
var originalCell = originalRow.cells[j], copyCell = copyRow.cells[j];
|
|
88
|
-
originalCell.style.width =
|
|
101
|
+
originalCell.style.width = window.getComputedStyle(copyCell).width;
|
|
89
102
|
}
|
|
90
103
|
}
|
|
91
104
|
}
|
|
92
105
|
};
|
|
106
|
+
StickyTableHeader.prototype.storeColumnWidths = function () {
|
|
107
|
+
this.originalWidths = [];
|
|
108
|
+
for (var i = 0; i < this.header.rows.length; i++) {
|
|
109
|
+
var row = this.header.rows[i];
|
|
110
|
+
for (var j = 0; j < row.cells.length; j++) {
|
|
111
|
+
var cell = row.cells[j];
|
|
112
|
+
this.originalWidths.push({ cell: cell, width: cell.style.width });
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
};
|
|
116
|
+
StickyTableHeader.prototype.restoreColumnWidths = function () {
|
|
117
|
+
for (var _i = 0, _a = this.originalWidths; _i < _a.length; _i++) {
|
|
118
|
+
var cellRef = _a[_i];
|
|
119
|
+
cellRef.cell.style.width = cellRef.width;
|
|
120
|
+
}
|
|
121
|
+
};
|
|
93
122
|
StickyTableHeader.prototype.dispose = function () {
|
|
94
123
|
document.removeEventListener("scroll", this.handleScroll);
|
|
95
124
|
if (this.scrollElement) {
|
|
@@ -11,7 +11,7 @@ import PropertyInfo from '@singularsystems/neo-core/dist/Model/PropertyInfo';
|
|
|
11
11
|
import { IComponentBase } from './ComponentBase';
|
|
12
12
|
import FileInput, { IFileEditorProps } from './FileManager/FileInput';
|
|
13
13
|
import { FormContextParams } from './FormContext';
|
|
14
|
-
export type ItemCallback<T> = (item: T, meta: TransformMetaType<T>, isHeader: boolean) => React.ReactNode;
|
|
14
|
+
export type ItemCallback<T> = (item: T, meta: TransformMetaType<T>, isHeader: boolean, index: number) => React.ReactNode;
|
|
15
15
|
export declare enum ControlType {
|
|
16
16
|
Date = 0,
|
|
17
17
|
Number = 1,
|