@jielga/tmdatagrid 2.0.0-beta.9 → 2.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 +5 -212
- package/dist/index.d.ts +1281 -768
- package/dist/index.js +4607 -3250
- package/dist/index.js.map +1 -1
- package/dist/styles.css +1 -1
- package/docs/adding-rows.md +132 -0
- package/docs/anatomy.md +119 -0
- package/docs/card-view.md +108 -0
- package/docs/cell-selection.md +194 -0
- package/docs/column-layout.md +182 -0
- package/docs/column-menu.md +66 -0
- package/docs/columns.md +268 -0
- package/docs/components.md +311 -0
- package/docs/draft-store.md +242 -0
- package/docs/editing.md +303 -0
- package/docs/editors.md +250 -0
- package/docs/export.md +319 -0
- package/docs/filtering.md +362 -0
- package/docs/getting-started.md +123 -0
- package/docs/grouping.md +165 -0
- package/docs/loading-and-empty.md +92 -0
- package/docs/localization.md +79 -0
- package/docs/menu.md +143 -0
- package/docs/migrating-to-2.md +163 -0
- package/docs/pagination.md +144 -0
- package/docs/persistence.md +114 -0
- package/docs/portfolio-rebalancer.md +94 -0
- package/docs/query-builder.md +179 -0
- package/docs/quick-search.md +84 -0
- package/docs/row-details.md +115 -0
- package/docs/row-interaction.md +149 -0
- package/docs/row-pinning.md +132 -0
- package/docs/row-selection.md +136 -0
- package/docs/row-styling.md +133 -0
- package/docs/scrolling.md +112 -0
- package/docs/server-query.md +246 -0
- package/docs/server-side.md +206 -0
- package/docs/sorting.md +101 -0
- package/docs/styling.md +126 -0
- package/docs/summary-row.md +76 -0
- package/docs/testing.md +744 -0
- package/docs/toolbar.md +161 -0
- package/docs/use-tm-data-grid.md +361 -0
- package/package.json +22 -46
- package/skills/appearance/SKILL.md +72 -19
- package/skills/cell-selection/SKILL.md +46 -47
- package/skills/columns/SKILL.md +90 -34
- package/skills/data/SKILL.md +86 -16
- package/skills/editing/SKILL.md +67 -40
- package/skills/editing/references/common-mistakes.md +77 -69
- package/skills/editing/references/editing-api.md +22 -19
- package/skills/editing/references/editors-and-validation.md +24 -17
- package/skills/filtering/SKILL.md +148 -40
- package/skills/getting-started/SKILL.md +17 -15
- package/skills/grouping/SKILL.md +31 -16
- package/skills/options/SKILL.md +7 -7
- package/skills/rows/SKILL.md +22 -18
- package/skills/server-side/SKILL.md +170 -17
- package/skills/testing/SKILL.md +150 -32
- package/skills/testing-components/SKILL.md +230 -0
- package/skills/testing-editing/SKILL.md +240 -0
- package/src/{tmdatagrid/components → components}/TMDataGrid.tsx +38 -21
- package/src/{tmdatagrid/components → components}/TMDataGridCellEditor.tsx +54 -8
- package/src/{tmdatagrid/components → components}/TMDataGridColumnsPanel.module.css +5 -1
- package/src/{tmdatagrid/components → components}/TMDataGridColumnsPanel.tsx +47 -55
- package/src/{tmdatagrid/components → components}/TMDataGridDetailsColumn.tsx +5 -51
- package/src/{tmdatagrid/components → components}/TMDataGridDraftActions.tsx +41 -24
- package/src/{tmdatagrid/components → components}/TMDataGridEditColumn.tsx +12 -59
- package/src/{tmdatagrid/components → components}/TMDataGridEntryRows.tsx +164 -92
- package/src/components/TMDataGridExportPicker.module.css +77 -0
- package/src/components/TMDataGridExportPicker.tsx +234 -0
- package/src/components/TMDataGridFilterPanel.module.css +54 -0
- package/src/components/TMDataGridFilterPanel.tsx +348 -0
- package/src/{tmdatagrid/components → components}/TMDataGridFilterPills.tsx +15 -8
- package/src/components/TMDataGridFilterSurface.module.css +54 -0
- package/src/components/TMDataGridFilterSurface.tsx +167 -0
- package/src/{tmdatagrid/components → components}/TMDataGridFooter.tsx +53 -90
- package/src/{tmdatagrid/components → components}/TMDataGridGroupColumn.tsx +5 -69
- package/src/{tmdatagrid/components → components}/TMDataGridHeaderCell.module.css +12 -2
- package/src/{tmdatagrid/components → components}/TMDataGridHeaderCell.tsx +58 -21
- package/src/components/TMDataGridHeaderFilterRow.module.css +51 -0
- package/src/components/TMDataGridHeaderFilterRow.tsx +301 -0
- package/src/components/TMDataGridMenu.tsx +357 -0
- package/src/{tmdatagrid/components → components}/TMDataGridSelectColumn.tsx +11 -48
- package/src/{tmdatagrid/components → components}/TMDataGridTable.module.css +69 -56
- package/src/{tmdatagrid/components → components}/TMDataGridTable.tsx +240 -138
- package/src/{tmdatagrid/components → components}/TMDataGridToolbar.module.css +5 -0
- package/src/components/TMDataGridToolbar.tsx +181 -0
- package/src/{tmdatagrid/components → components}/editors/TMDataGridBooleanEditor.tsx +3 -3
- package/src/{tmdatagrid/components → components}/editors/TMDataGridDateEditor.tsx +3 -3
- package/src/{tmdatagrid/components → components}/editors/TMDataGridMultiSelectEditor.tsx +3 -3
- package/src/{tmdatagrid/components → components}/editors/TMDataGridNumberEditor.tsx +3 -3
- package/src/{tmdatagrid/components → components}/editors/TMDataGridSelectEditor.tsx +3 -3
- package/src/{tmdatagrid/components → components}/editors/TMDataGridStringEditor.tsx +3 -3
- package/src/{tmdatagrid/components → components}/editors/editorShared.ts +16 -2
- package/src/{tmdatagrid/components → components}/filters/DgAutocompleteFilter.tsx +5 -4
- package/src/{tmdatagrid/components → components}/filters/DgDateRangeFilter.tsx +22 -5
- package/src/{tmdatagrid/components → components}/filters/DgRangeSliderFilter.tsx +5 -1
- package/src/{tmdatagrid/components → components}/filters/DgTriStateFilter.tsx +5 -1
- package/src/{tmdatagrid/components → components}/filters/TMDataGridFilterValueInput.tsx +44 -28
- package/src/components/filters/controlLayout.ts +32 -0
- package/src/components/filters/filterControlFor.ts +65 -0
- package/src/components/generatedColumns.tsx +187 -0
- package/src/{tmdatagrid/components → components}/icons.ts +1 -0
- package/src/{tmdatagrid/components → components}/sticky.module.css +44 -0
- package/src/components/useHideableColumns.ts +52 -0
- package/src/{tmdatagrid/core → core}/autosize.ts +5 -2
- package/src/{tmdatagrid/core → core}/columnOptions.ts +60 -8
- package/src/{tmdatagrid/core → core}/columnOrdering.ts +33 -14
- package/src/{tmdatagrid/core → core}/columnUtils.ts +44 -5
- package/src/core/controlledStateSync.ts +108 -0
- package/src/core/deletedRows.ts +34 -0
- package/src/core/dom.ts +74 -0
- package/src/{tmdatagrid/core → core}/editEngine.ts +1107 -460
- package/src/core/export.ts +704 -0
- package/src/{tmdatagrid/core → core}/filterControls.ts +38 -1
- package/src/{tmdatagrid/core → core}/filterOperators.ts +64 -1
- package/src/core/filterSurface.ts +99 -0
- package/src/{tmdatagrid/core → core}/grouping.ts +21 -0
- package/src/{tmdatagrid/core → core}/labels.ts +51 -6
- package/src/{tmdatagrid/core → core}/labelsSv.ts +27 -6
- package/src/core/pageReset.ts +120 -0
- package/src/core/pagination.ts +81 -0
- package/src/{tmdatagrid/core → core}/persistence.ts +22 -5
- package/src/{tmdatagrid/core → core}/summary.ts +20 -4
- package/src/{tmdatagrid/index.ts → index.ts} +69 -35
- package/src/{tmdatagrid/useTMDataGrid.tsx → useTMDataGrid.tsx} +428 -109
- package/src/useTMDataGridExport.ts +78 -0
- package/src/tmdatagrid/components/TMDataGridFilterPanel.module.css +0 -35
- package/src/tmdatagrid/components/TMDataGridFilterPanel.tsx +0 -354
- package/src/tmdatagrid/components/TMDataGridToolbar.tsx +0 -161
- package/src/tmdatagrid/core/cellExport.ts +0 -320
- /package/src/{tmdatagrid/TMDataGridContext.ts → TMDataGridContext.ts} +0 -0
- /package/src/{tmdatagrid/components → components}/TMDataGrid.module.css +0 -0
- /package/src/{tmdatagrid/components → components}/TMDataGridDetailsColumn.module.css +0 -0
- /package/src/{tmdatagrid/components → components}/TMDataGridFilterPills.module.css +0 -0
- /package/src/{tmdatagrid/components → components}/TMDataGridFooter.module.css +0 -0
- /package/src/{tmdatagrid/components → components}/TMDataGridGroupColumn.module.css +0 -0
- /package/src/{tmdatagrid/components → components}/TMDataGridRowNumberColumn.tsx +0 -0
- /package/src/{tmdatagrid/components → components}/TMDataGridSearch.tsx +0 -0
- /package/src/{tmdatagrid/core → core}/capabilities.ts +0 -0
- /package/src/{tmdatagrid/core → core}/cellNavigation.ts +0 -0
- /package/src/{tmdatagrid/core → core}/cellRange.ts +0 -0
- /package/src/{tmdatagrid/core → core}/controlledState.ts +0 -0
- /package/src/{tmdatagrid/core → core}/draftCellContext.ts +0 -0
- /package/src/{tmdatagrid/core → core}/editorFocus.ts +0 -0
- /package/src/{tmdatagrid/core → core}/expanding.ts +0 -0
- /package/src/{tmdatagrid/core → core}/matchHighlight.ts +0 -0
- /package/src/{tmdatagrid/core → core}/quickSearch.ts +0 -0
- /package/src/{tmdatagrid/core → core}/resizePreview.ts +0 -0
- /package/src/{tmdatagrid/core → core}/rowPinning.ts +0 -0
- /package/src/{tmdatagrid/core → core}/rowSelection.ts +0 -0
- /package/src/{tmdatagrid/core → core}/sizes.ts +0 -0
- /package/src/{tmdatagrid/core → core}/useSettledTableState.ts +0 -0
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
import { Checkbox } from "@mantine/core";
|
|
2
2
|
import { useSelector } from "@tanstack/react-store";
|
|
3
|
-
import type {
|
|
3
|
+
import type { Row, RowData } from "@tanstack/react-table";
|
|
4
4
|
import {
|
|
5
5
|
useBodyControlTabIndex,
|
|
6
6
|
useTMDataGridContext,
|
|
7
7
|
} from "../TMDataGridContext";
|
|
8
|
+
import { isMouseEvent } from "../core/dom";
|
|
8
9
|
import {
|
|
9
10
|
getDisplayedRows,
|
|
10
11
|
getSelectableRowIds,
|
|
@@ -62,7 +63,7 @@ function SelectAllCheckbox<TData extends RowData>({
|
|
|
62
63
|
* change - the same reason the rest of the chrome reads them. See
|
|
63
64
|
* readFeatureFlags.
|
|
64
65
|
*/
|
|
65
|
-
function SelectAllHeader<TData extends RowData>({
|
|
66
|
+
export function SelectAllHeader<TData extends RowData>({
|
|
66
67
|
table,
|
|
67
68
|
}: {
|
|
68
69
|
table: TMDataGridTable<TData>;
|
|
@@ -72,7 +73,7 @@ function SelectAllHeader<TData extends RowData>({
|
|
|
72
73
|
return <SelectAllCheckbox table={table} />;
|
|
73
74
|
}
|
|
74
75
|
|
|
75
|
-
function SelectRowCheckbox<TData extends RowData>({
|
|
76
|
+
export function SelectRowCheckbox<TData extends RowData>({
|
|
76
77
|
row,
|
|
77
78
|
}: {
|
|
78
79
|
row: Row<TMDataGridFeatures, TData>;
|
|
@@ -80,9 +81,14 @@ function SelectRowCheckbox<TData extends RowData>({
|
|
|
80
81
|
// Cells render inside the grid's provider, so the checkbox can reach the
|
|
81
82
|
// chrome store - it needs the shift-click pivot, and the feature flags to know
|
|
82
83
|
// which row model a range is measured over.
|
|
83
|
-
const { ui, features, labels } = useTMDataGridContext();
|
|
84
|
+
const { ui, features, labels, edit } = useTMDataGridContext();
|
|
84
85
|
const tabIndex = useBodyControlTabIndex();
|
|
85
86
|
const isGroupRow = row.subRows.length > 0;
|
|
87
|
+
// A deletion mark makes the row unselectable (see `enableRowSelection` in
|
|
88
|
+
// the hook), and the box below reads that through `getCanSelect`. The
|
|
89
|
+
// mark lives in the edit store, so the subscription is what re-renders
|
|
90
|
+
// the box when it lands - the row and cell identities do not change.
|
|
91
|
+
useSelector(edit.store, (state) => state.deletedRowIds.includes(row.id));
|
|
86
92
|
|
|
87
93
|
// A group row is never selected by id: `rowSelection` only holds the leaves,
|
|
88
94
|
// and TanStack's `getIsSelected()` is a plain lookup in that map. A group
|
|
@@ -126,7 +132,7 @@ function SelectRowCheckbox<TData extends RowData>({
|
|
|
126
132
|
// silently loses the clicked row, which `onChange` then toggles back off.
|
|
127
133
|
onChange={(event) => {
|
|
128
134
|
const native = event.nativeEvent;
|
|
129
|
-
const isMouse = native
|
|
135
|
+
const isMouse = isMouseEvent(native);
|
|
130
136
|
const resolved = resolveRowSelectionClick({
|
|
131
137
|
rows: getDisplayedRows(row.table, features),
|
|
132
138
|
rowId: row.id,
|
|
@@ -148,46 +154,3 @@ function SelectRowCheckbox<TData extends RowData>({
|
|
|
148
154
|
/>
|
|
149
155
|
);
|
|
150
156
|
}
|
|
151
|
-
|
|
152
|
-
/**
|
|
153
|
-
* The generated checkbox column, prepended under
|
|
154
|
-
* `selectionMode: "checkbox"` (the default) or `"checkboxAndHighlight"`.
|
|
155
|
-
*/
|
|
156
|
-
export function createSelectColumn<TData extends RowData>(
|
|
157
|
-
label = "Checkbox selection",
|
|
158
|
-
): ColumnDef<TMDataGridFeatures, TData, unknown> {
|
|
159
|
-
return {
|
|
160
|
-
id: SELECT_COLUMN_ID,
|
|
161
|
-
meta: {
|
|
162
|
-
label,
|
|
163
|
-
align: "center",
|
|
164
|
-
// Structurally the first column; it also anchors the left pinned lane, so
|
|
165
|
-
// no other column can be moved in front of it.
|
|
166
|
-
enableOrdering: false,
|
|
167
|
-
},
|
|
168
|
-
// A system lane: as wide as the control it holds and no wider. Fixed at
|
|
169
|
-
// every scale - the control does not grow with the font size, so neither
|
|
170
|
-
// should its track.
|
|
171
|
-
size: 36,
|
|
172
|
-
minSize: 36,
|
|
173
|
-
maxSize: 36,
|
|
174
|
-
enableResizing: false,
|
|
175
|
-
enableSorting: false,
|
|
176
|
-
enableColumnFilter: false,
|
|
177
|
-
enableGlobalFilter: false,
|
|
178
|
-
// Not a column the user chose, so not one they can switch off: hiding the
|
|
179
|
-
// lane would take the grid's only way to select a row with it, with the
|
|
180
|
-
// row-selection state left behind and no way back to it. Keeping it out of
|
|
181
|
-
// "Manage columns" follows from this - the panel lists what can be hidden.
|
|
182
|
-
enableHiding: false,
|
|
183
|
-
// Structurally pinned to the left; users shouldn't be able to move it.
|
|
184
|
-
enablePinning: false,
|
|
185
|
-
header: ({ table }) => <SelectAllHeader table={table} />,
|
|
186
|
-
cell: ({ row }) => <SelectRowCheckbox row={row} />,
|
|
187
|
-
// Every cell on a group row that is not the grouped column counts as
|
|
188
|
-
// aggregated, this lane included, and an aggregated cell with nothing
|
|
189
|
-
// declared renders blank. Without this the checkbox would disappear from
|
|
190
|
-
// exactly the rows that select a whole group. See renderCellContent.
|
|
191
|
-
aggregatedCell: ({ row }) => <SelectRowCheckbox row={row} />,
|
|
192
|
-
};
|
|
193
|
-
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/* Anchors the filter
|
|
1
|
+
/* Anchors the filter popup, which floats over the first body rows. */
|
|
2
2
|
.tableWrapper {
|
|
3
3
|
position: relative;
|
|
4
4
|
flex: 1;
|
|
@@ -7,9 +7,17 @@
|
|
|
7
7
|
flex-direction: column;
|
|
8
8
|
}
|
|
9
9
|
|
|
10
|
+
/* The sidebar surface is a second column of the wrapper rather than a layer
|
|
11
|
+
over the rows, so the wrapper lays its children out side by side. The
|
|
12
|
+
sidebar's own module decides which side it lands on. */
|
|
13
|
+
.tableWrapper[data-dg-filter-sidebar] {
|
|
14
|
+
flex-direction: row;
|
|
15
|
+
}
|
|
16
|
+
|
|
10
17
|
.scrollContainer {
|
|
11
18
|
position: relative;
|
|
12
19
|
flex: 1;
|
|
20
|
+
min-width: 0;
|
|
13
21
|
min-height: 0;
|
|
14
22
|
overflow: auto;
|
|
15
23
|
/* Lets .messageRow size itself to the scrollport (100cqi) instead of the
|
|
@@ -20,6 +28,13 @@
|
|
|
20
28
|
/* Column tracks are set inline via gridTemplateColumns. */
|
|
21
29
|
.grid {
|
|
22
30
|
display: grid;
|
|
31
|
+
/* The grid is the containing block every sticky row inside it is held by, so
|
|
32
|
+
it has to reach the bottom of the scrollport even when the rows do not fill
|
|
33
|
+
it - that is what puts the summary row on the bottom edge of a short body.
|
|
34
|
+
`align-content` keeps the free space out of the row tracks; distributed
|
|
35
|
+
into them it would stretch every row instead. */
|
|
36
|
+
min-height: 100%;
|
|
37
|
+
align-content: start;
|
|
23
38
|
}
|
|
24
39
|
|
|
25
40
|
/* The pair of focusable elements bracketing the body, which is how the body
|
|
@@ -45,46 +60,6 @@
|
|
|
45
60
|
z-index: var(--dg-z-header, 6);
|
|
46
61
|
}
|
|
47
62
|
|
|
48
|
-
/* The scrolled-under shadow: a soft band under the header, only while body
|
|
49
|
-
rows are actually beneath it. On the last header row - the header/body
|
|
50
|
-
boundary - not on every stacked group row. A scroll-driven animation, like
|
|
51
|
-
the pinned-lane gradients: the shadow tracks the scroll on the compositor
|
|
52
|
-
with no listener and no render, and an inactive timeline (nothing to
|
|
53
|
-
scroll) leaves `opacity: 0` standing, so a grid that fits shows nothing.
|
|
54
|
-
Where unsupported there is simply no shadow - the header's border already
|
|
55
|
-
draws the boundary. */
|
|
56
|
-
.headerRow[data-dg-header-last]::after {
|
|
57
|
-
content: "";
|
|
58
|
-
position: absolute;
|
|
59
|
-
inset: 100% 0 auto 0;
|
|
60
|
-
height: 6px;
|
|
61
|
-
pointer-events: none;
|
|
62
|
-
background: linear-gradient(
|
|
63
|
-
to bottom,
|
|
64
|
-
var(--dg-header-shadow-color, rgba(0, 0, 0, 0.14)),
|
|
65
|
-
transparent
|
|
66
|
-
);
|
|
67
|
-
opacity: 0;
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
@supports (animation-timeline: scroll()) {
|
|
71
|
-
.headerRow[data-dg-header-last]::after {
|
|
72
|
-
animation: dg-header-shadow linear both;
|
|
73
|
-
animation-timeline: scroll(nearest block);
|
|
74
|
-
/* Arrives over the first rows leaving, reads as depth not as a fade. */
|
|
75
|
-
animation-range: 0px 24px;
|
|
76
|
-
}
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
@keyframes dg-header-shadow {
|
|
80
|
-
from {
|
|
81
|
-
opacity: 0;
|
|
82
|
-
}
|
|
83
|
-
to {
|
|
84
|
-
opacity: 1;
|
|
85
|
-
}
|
|
86
|
-
}
|
|
87
|
-
|
|
88
63
|
.bodyRow {
|
|
89
64
|
--row-bg: var(--mantine-color-body);
|
|
90
65
|
display: grid;
|
|
@@ -164,8 +139,13 @@
|
|
|
164
139
|
align-items: center;
|
|
165
140
|
padding: 0 var(--dg-padding);
|
|
166
141
|
border-bottom: 1px solid var(--mantine-color-default-border);
|
|
167
|
-
/*
|
|
168
|
-
|
|
142
|
+
/* Two layers, not one. The base is the theme's body colour and `--row-bg`
|
|
143
|
+
(inherited from .bodyRow) is a tint painted over it, so a consumer whose
|
|
144
|
+
row token is translucent - a `color-mix(..., transparent)` - is safe under
|
|
145
|
+
the sticky lanes: a single translucent `background-color` would let the
|
|
146
|
+
scrolled body read through every pinned cell and pinned row. */
|
|
147
|
+
background-color: var(--mantine-color-body);
|
|
148
|
+
background-image: linear-gradient(var(--row-bg), var(--row-bg));
|
|
169
149
|
font-size: var(--dg-font-size);
|
|
170
150
|
}
|
|
171
151
|
|
|
@@ -189,13 +169,15 @@
|
|
|
189
169
|
A tint over the row's own background rather than instead of it, so a
|
|
190
170
|
selected cell on a highlighted row still reads as both. `color-mix` keeps
|
|
191
171
|
one declaration for light and dark: it thins the theme's primary colour into
|
|
192
|
-
whatever `--row-bg` the row resolved to.
|
|
172
|
+
whatever `--row-bg` the row resolved to. Painted as the cell's tint layer,
|
|
173
|
+
over the opaque base above, for the same reason `--row-bg` is. */
|
|
193
174
|
.bodyCell[data-selected="true"] {
|
|
194
|
-
|
|
175
|
+
--dg-range-tint: color-mix(
|
|
195
176
|
in srgb,
|
|
196
177
|
var(--mantine-primary-color-filled) 14%,
|
|
197
178
|
var(--row-bg)
|
|
198
179
|
);
|
|
180
|
+
background-image: linear-gradient(var(--dg-range-tint), var(--dg-range-tint));
|
|
199
181
|
}
|
|
200
182
|
|
|
201
183
|
/* The outline around the block, drawn edge by edge: only the cells on a side
|
|
@@ -267,6 +249,15 @@
|
|
|
267
249
|
gap: 2px;
|
|
268
250
|
}
|
|
269
251
|
|
|
252
|
+
/* The editor's own box: the input fills it, and it is what the validation
|
|
253
|
+
tooltip is anchored to. */
|
|
254
|
+
.cellEditorField {
|
|
255
|
+
display: flex;
|
|
256
|
+
align-items: center;
|
|
257
|
+
flex: 1 1 auto;
|
|
258
|
+
min-width: 0;
|
|
259
|
+
}
|
|
260
|
+
|
|
270
261
|
/* cellConfirm's ✓ / ✕ pair, beside the input. */
|
|
271
262
|
.cellEditorActions {
|
|
272
263
|
display: flex;
|
|
@@ -275,16 +266,19 @@
|
|
|
275
266
|
}
|
|
276
267
|
|
|
277
268
|
/* Corner triangles for a cell's edit state, drawn like a spreadsheet's: a
|
|
278
|
-
draft not yet saved is blue, a value failing validation is red.
|
|
279
|
-
|
|
269
|
+
draft not yet saved is blue, a value failing validation is red. An entry
|
|
270
|
+
cell takes the red one only - everything in it is new. The cell needs a
|
|
271
|
+
positioning context; pinned and focused cells set their own inline
|
|
280
272
|
`position`, which wins over this. */
|
|
281
273
|
.bodyCell[data-dirty],
|
|
282
|
-
.bodyCell[data-invalid]
|
|
274
|
+
.bodyCell[data-invalid],
|
|
275
|
+
.entryCell[data-invalid] {
|
|
283
276
|
position: relative;
|
|
284
277
|
}
|
|
285
278
|
|
|
286
279
|
.bodyCell[data-dirty]::after,
|
|
287
|
-
.bodyCell[data-invalid]::after
|
|
280
|
+
.bodyCell[data-invalid]::after,
|
|
281
|
+
.entryCell[data-invalid]::after {
|
|
288
282
|
content: "";
|
|
289
283
|
position: absolute;
|
|
290
284
|
top: 0;
|
|
@@ -295,7 +289,8 @@
|
|
|
295
289
|
}
|
|
296
290
|
|
|
297
291
|
/* Invalid wins over dirty - a cell is usually both. */
|
|
298
|
-
.bodyCell[data-invalid]::after
|
|
292
|
+
.bodyCell[data-invalid]::after,
|
|
293
|
+
.entryCell[data-invalid]::after {
|
|
299
294
|
border-top-color: var(--mantine-color-error);
|
|
300
295
|
border-right-color: var(--mantine-color-error);
|
|
301
296
|
}
|
|
@@ -322,7 +317,9 @@
|
|
|
322
317
|
.detailsCell {
|
|
323
318
|
grid-column: 1 / -1;
|
|
324
319
|
border-bottom: 1px solid var(--mantine-color-default-border);
|
|
325
|
-
|
|
320
|
+
/* Base and tint, exactly as .bodyCell paints them. */
|
|
321
|
+
background-color: var(--mantine-color-body);
|
|
322
|
+
background-image: linear-gradient(var(--row-bg), var(--row-bg));
|
|
326
323
|
padding: var(--dg-padding);
|
|
327
324
|
/* The row above may be the selection control, which turns text selection off
|
|
328
325
|
for everything inside it. A panel is content, so it takes both back. */
|
|
@@ -348,7 +345,7 @@
|
|
|
348
345
|
padding: var(--mantine-spacing-xl);
|
|
349
346
|
}
|
|
350
347
|
|
|
351
|
-
/* Marked deleted under draft: struck through and inert until
|
|
348
|
+
/* Marked deleted under draft: struck through and inert until saveDrafts
|
|
352
349
|
reports it - a row about to go away must not keep taking edits. Interaction
|
|
353
350
|
comes off the data cells, not the row: `pointer-events: none` on the row
|
|
354
351
|
would also kill the edit lane's Restore, which is the one control the row
|
|
@@ -389,8 +386,8 @@
|
|
|
389
386
|
element, its rows flow normally inside it. The top block stacks under the
|
|
390
387
|
entry block when both exist; `--dg-entry-height` is measured only then, so
|
|
391
388
|
the offset is otherwise the header alone. The bottom block stacks above the
|
|
392
|
-
summary row the same way.
|
|
393
|
-
|
|
389
|
+
summary row the same way. The cells inside paint an opaque base under
|
|
390
|
+
`--row-bg` already, so the blocks only add the edge borders. */
|
|
394
391
|
.pinnedTopBlock {
|
|
395
392
|
display: grid;
|
|
396
393
|
grid-column: 1 / -1;
|
|
@@ -438,7 +435,13 @@
|
|
|
438
435
|
.entryRow[data-committed="true"] .entryCell {
|
|
439
436
|
padding: 0 var(--dg-padding);
|
|
440
437
|
border-bottom: 1px solid var(--mantine-color-default-border);
|
|
441
|
-
|
|
438
|
+
/* The tint over .entryCell's opaque base, not instead of it: the block is
|
|
439
|
+
sticky, so a translucent `--dg-row-new-bg` would otherwise show the body
|
|
440
|
+
scrolling underneath. */
|
|
441
|
+
background-image: linear-gradient(
|
|
442
|
+
var(--dg-row-new-bg, transparent),
|
|
443
|
+
var(--dg-row-new-bg, transparent)
|
|
444
|
+
);
|
|
442
445
|
}
|
|
443
446
|
|
|
444
447
|
.entryRow[data-committed="true"] .entryCell[data-control-column="true"] {
|
|
@@ -484,12 +487,22 @@
|
|
|
484
487
|
|
|
485
488
|
/* The summary row - one sticky row of column footers along the bottom edge,
|
|
486
489
|
rendered only while at least one column defines `footer`. Same subgrid
|
|
487
|
-
placement as the header, so its cells sit exactly on the body's tracks.
|
|
490
|
+
placement as the header, so its cells sit exactly on the body's tracks.
|
|
491
|
+
|
|
492
|
+
Both insets are set, so the row is on the scrollport's bottom edge whether
|
|
493
|
+
the body overflows or not. A percentage in a sticky inset resolves against
|
|
494
|
+
the scrollport: with too few rows to fill it, `top` pushes the row down
|
|
495
|
+
until `.grid` - which reaches the scrollport's bottom - stops it, flush with
|
|
496
|
+
the edge; with the body overflowing, `top` is already satisfied and
|
|
497
|
+
`bottom: 0` pins the row as it always did. Where the two conflict the top
|
|
498
|
+
one wins, which is why it has to be the row's own height short of 100% and
|
|
499
|
+
not 100%. `--dg-summary-height` is measured whenever this row exists. */
|
|
488
500
|
.summaryRow {
|
|
489
501
|
display: grid;
|
|
490
502
|
grid-column: 1 / -1;
|
|
491
503
|
grid-template-columns: subgrid;
|
|
492
504
|
position: sticky;
|
|
505
|
+
top: calc(100% - var(--dg-summary-height, 0px));
|
|
493
506
|
bottom: 0;
|
|
494
507
|
z-index: var(--dg-z-summary-row, 4);
|
|
495
508
|
}
|