@ngx-stoui/core 21.0.11 → 21.0.12
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/package.json +1 -1
- package/styles/toolbox-grid/_toolbox-grid.scss +460 -39
- package/toolbox-grid.css +596 -80
package/toolbox-grid.css
CHANGED
|
@@ -2,15 +2,43 @@
|
|
|
2
2
|
/**
|
|
3
3
|
* EDS (Equinor Design System) Theme for @toolbox-web/grid
|
|
4
4
|
*
|
|
5
|
-
* Styles the toolbox grid to match Equinor's design system.
|
|
6
|
-
*
|
|
7
|
-
*
|
|
5
|
+
* Styles the toolbox grid to match Equinor's design system. Shared by
|
|
6
|
+
* Angular consumers (cargo-tracker-apps via `@ngx-stoui/core/toolbox-grid.css`)
|
|
7
|
+
* and React consumers (planning Roma app).
|
|
8
|
+
*
|
|
9
|
+
* Both `<tbw-grid>` (web component) and `<div data-tbw-grid>` are supported
|
|
10
|
+
* so React apps that don't import the web component can still opt in to the
|
|
11
|
+
* theme by stamping the attribute on a wrapper.
|
|
12
|
+
*
|
|
13
|
+
* Supports light/dark modes via the light-dark() CSS function. Consumers that
|
|
14
|
+
* don't support dark mode (e.g. Roma) can opt out with `color-scheme: light only`
|
|
15
|
+
* on their root.
|
|
16
|
+
*
|
|
17
|
+
* In-cell editor coexistence:
|
|
18
|
+
* - Angular: Material form fields (`.mat-mdc-*`) — chrome is stripped so the
|
|
19
|
+
* surrounding `.tbw-editor-host` paints the visual boundary.
|
|
20
|
+
* - React/EDS: native EDS `<DatePicker>` / `<Autocomplete>` wrapped with
|
|
21
|
+
* `.tbw-eds-date-editor` / `.tbw-eds-autocomplete-editor` marker classes.
|
|
8
22
|
*
|
|
9
23
|
* Reference: https://eds.equinor.com/
|
|
10
24
|
* Grid Theming: https://toolboxjs.com/?path=/docs/grid-theming--docs
|
|
11
25
|
* Requires @toolbox-web/grid v1.3.1+
|
|
12
26
|
*
|
|
13
|
-
* Usage:
|
|
27
|
+
* Usage:
|
|
28
|
+
* Angular: "@ngx-stoui/core/toolbox-grid.css" in project.json styles array
|
|
29
|
+
* React: import the compiled css, or @use this partial in a Sass entry
|
|
30
|
+
*
|
|
31
|
+
* Sections:
|
|
32
|
+
* 1. Theme Variables
|
|
33
|
+
* 2. Grid Styles (cells, editors, Material stripping, anchors, Typography reset)
|
|
34
|
+
* 3. Pinned cells & sticky group rows
|
|
35
|
+
* 4. Filter Panel
|
|
36
|
+
* 5. Context Menu
|
|
37
|
+
* 6. Overlay Panel
|
|
38
|
+
* 7. EDS in-cell editors (DatePicker / Autocomplete)
|
|
39
|
+
* 8. Empty State Overlay
|
|
40
|
+
* 9. Opt-ins (compact mode, thin header)
|
|
41
|
+
* 10. Dark Mode
|
|
14
42
|
*/
|
|
15
43
|
/* ================================================================
|
|
16
44
|
* 1. Theme Variables
|
|
@@ -22,6 +50,7 @@
|
|
|
22
50
|
* rendered in document.body, so these variables cascade properly.
|
|
23
51
|
* ================================================================ */
|
|
24
52
|
tbw-grid,
|
|
53
|
+
[data-tbw-grid],
|
|
25
54
|
.tbw-filter-panel {
|
|
26
55
|
/* --- EDS Token Aliases (cascade to all children) --- */
|
|
27
56
|
--_bg: var(--eds_ui_background__default, light-dark(#ffffff, #132634));
|
|
@@ -51,6 +80,7 @@ tbw-grid,
|
|
|
51
80
|
--tbw-font-size: var(--sto-base-font-size, 13px);
|
|
52
81
|
--tbw-font-size-header: var(--sto-base-font-size, 13px);
|
|
53
82
|
--tbw-font-weight-header: 700;
|
|
83
|
+
--tbw-aggregation-font-size: 0.9em;
|
|
54
84
|
/* --- Colors --- */
|
|
55
85
|
--tbw-color-bg: var(--_bg);
|
|
56
86
|
--tbw-color-fg: var(--_fg);
|
|
@@ -100,9 +130,16 @@ tbw-grid,
|
|
|
100
130
|
--tbw-cell-padding: 0 var(--eds_spacing_medium, 8px);
|
|
101
131
|
--tbw-cell-padding-header: 0 var(--eds_spacing_medium, 8px);
|
|
102
132
|
--tbw-button-padding: 0.375rem 0.625rem;
|
|
103
|
-
/* --- Focus ---
|
|
133
|
+
/* --- Focus ---
|
|
134
|
+
`--tbw-focus-outline` paints the focus ring; the grid applies
|
|
135
|
+
`--tbw-focus-background` as the cell tint when a cell has focus. Use an
|
|
136
|
+
alpha-blended accent so the grid's own `.cell-focus` rule produces the
|
|
137
|
+
soft tint we want — no element-targeting needed. Pinned cells need a
|
|
138
|
+
pre-composited override (see section 3) because alpha over a sticky
|
|
139
|
+
opaque panel-bg would bleed scrolling content through. */
|
|
104
140
|
--tbw-focus-outline: 0.5px dotted var(--_focus);
|
|
105
141
|
--tbw-focus-outline-offset: -1px;
|
|
142
|
+
--tbw-focus-background: rgba(from var(--_accent) r g b / 8%);
|
|
106
143
|
/* --- Resize Handle --- */
|
|
107
144
|
--tbw-resize-handle-color: transparent;
|
|
108
145
|
--tbw-resize-handle-color-hover: var(--_accent);
|
|
@@ -122,9 +159,12 @@ tbw-grid,
|
|
|
122
159
|
rgba(0, 0, 0, 0.15),
|
|
123
160
|
rgba(0, 0, 0, 0.4)
|
|
124
161
|
);
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
162
|
+
/* Filter inputs: EDS underline style. Strip the grid's default border
|
|
163
|
+
and radius via variables; the underline box-shadow itself (no variable)
|
|
164
|
+
is applied in section 4. */
|
|
165
|
+
--tbw-filter-input-bg: var(--_surface);
|
|
166
|
+
--tbw-filter-input-border: none;
|
|
167
|
+
--tbw-filter-input-radius: 0;
|
|
128
168
|
--tbw-filter-input-focus: var(--_focus);
|
|
129
169
|
--tbw-filter-accent: var(--_accent);
|
|
130
170
|
--tbw-filter-accent-fg: var(--_accent-fg);
|
|
@@ -147,17 +187,13 @@ tbw-grid,
|
|
|
147
187
|
/* ================================================================
|
|
148
188
|
* 2. Grid Styles
|
|
149
189
|
*
|
|
150
|
-
* All
|
|
151
|
-
*
|
|
190
|
+
* All grid-scoped rules: cell styling, editor hosts, anchors,
|
|
191
|
+
* Typography reset, and Angular Material overrides.
|
|
192
|
+
*
|
|
193
|
+
* Compact mode and thin-header opt-ins live in section 9.
|
|
152
194
|
* ================================================================ */
|
|
153
|
-
tbw-grid
|
|
154
|
-
|
|
155
|
-
}
|
|
156
|
-
tbw-grid.eds-compact {
|
|
157
|
-
--tbw-row-height: calc(var(--sto-base-font-size, 13px) * 1.385);
|
|
158
|
-
--tbw-header-height: calc(var(--sto-base-font-size, 13px) * 1.769);
|
|
159
|
-
}
|
|
160
|
-
tbw-grid {
|
|
195
|
+
tbw-grid,
|
|
196
|
+
[data-tbw-grid] {
|
|
161
197
|
/* --- Angular Material overrides for in-grid editors --- */
|
|
162
198
|
--mat-checkbox-state-layer-size: 20px;
|
|
163
199
|
--mdc-filled-text-field-container-color: transparent;
|
|
@@ -168,57 +204,130 @@ tbw-grid {
|
|
|
168
204
|
--mdc-outlined-text-field-focus-outline-color: transparent;
|
|
169
205
|
--mdc-outlined-text-field-hover-outline-color: transparent;
|
|
170
206
|
}
|
|
171
|
-
tbw-grid .mat-mdc-icon-button.mat-mdc-button-base
|
|
207
|
+
tbw-grid .mat-mdc-icon-button.mat-mdc-button-base,
|
|
208
|
+
[data-tbw-grid] .mat-mdc-icon-button.mat-mdc-button-base {
|
|
172
209
|
--mdc-icon-button-state-layer-size: 28px;
|
|
173
210
|
--mat-icon-button-state-layer-size: 28px;
|
|
174
211
|
}
|
|
175
|
-
tbw-grid
|
|
212
|
+
tbw-grid,
|
|
213
|
+
[data-tbw-grid] {
|
|
176
214
|
/* --- Toolbar --- */
|
|
177
215
|
}
|
|
178
|
-
tbw-grid .tbw-toolbar-content-slot
|
|
216
|
+
tbw-grid .tbw-toolbar-content-slot,
|
|
217
|
+
[data-tbw-grid] .tbw-toolbar-content-slot {
|
|
179
218
|
display: flex;
|
|
180
219
|
place-items: center;
|
|
181
220
|
}
|
|
182
|
-
tbw-grid
|
|
221
|
+
tbw-grid,
|
|
222
|
+
[data-tbw-grid] {
|
|
183
223
|
/* --- Filter button icon --- */
|
|
184
224
|
}
|
|
185
|
-
tbw-grid .tbw-filter-btn .material-icons-outlined
|
|
225
|
+
tbw-grid .tbw-filter-btn .material-icons-outlined,
|
|
226
|
+
[data-tbw-grid] .tbw-filter-btn .material-icons-outlined {
|
|
186
227
|
font-size: 1.2em;
|
|
187
228
|
width: 1.2em;
|
|
188
229
|
height: 1.2em;
|
|
189
230
|
}
|
|
190
|
-
tbw-grid
|
|
231
|
+
tbw-grid,
|
|
232
|
+
[data-tbw-grid] {
|
|
191
233
|
/* --- Cell defaults --- */
|
|
192
234
|
}
|
|
193
|
-
tbw-grid .cell
|
|
235
|
+
tbw-grid .cell,
|
|
236
|
+
[data-tbw-grid] .cell {
|
|
194
237
|
line-height: 1em;
|
|
195
238
|
}
|
|
196
|
-
tbw-grid
|
|
239
|
+
tbw-grid,
|
|
240
|
+
[data-tbw-grid] {
|
|
241
|
+
/* Anchor tags rendered inside cells (e.g. deep-link cells) should read
|
|
242
|
+
in the same color as plain text cells. Browser UA / EDS `Typography`
|
|
243
|
+
would otherwise paint them blue/teal. Underline is preserved
|
|
244
|
+
(we only override `color`). */
|
|
245
|
+
}
|
|
246
|
+
tbw-grid .cell a,
|
|
247
|
+
[data-tbw-grid] .cell a {
|
|
248
|
+
color: var(--_fg);
|
|
249
|
+
}
|
|
250
|
+
tbw-grid,
|
|
251
|
+
[data-tbw-grid] {
|
|
197
252
|
/* --- Numeric alignment --- */
|
|
198
253
|
}
|
|
199
|
-
tbw-grid .cell[data-type=number]
|
|
254
|
+
tbw-grid .cell[data-type=number],
|
|
255
|
+
[data-tbw-grid] .cell[data-type=number] {
|
|
200
256
|
text-align: right;
|
|
201
257
|
}
|
|
202
|
-
tbw-grid
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
258
|
+
tbw-grid,
|
|
259
|
+
[data-tbw-grid] {
|
|
260
|
+
/* --- Data cell styling & editor host ---
|
|
261
|
+
The grid already paints `height: var(--tbw-row-height)` and
|
|
262
|
+
`background: var(--tbw-focus-background)` on focused cells from its own
|
|
263
|
+
base layer, so we only add what the grid doesn't expose as a variable:
|
|
264
|
+
`font-weight` on cells, the sticky-cell focus override, and editor-host
|
|
265
|
+
chrome (which lives on our `.tbw-editor-host` wrapper, not on a built-in
|
|
266
|
+
grid class). */
|
|
267
|
+
}
|
|
268
|
+
tbw-grid [part=cell], tbw-grid .data-grid-row .cell,
|
|
269
|
+
[data-tbw-grid] [part=cell],
|
|
270
|
+
[data-tbw-grid] .data-grid-row .cell {
|
|
206
271
|
font-weight: 500;
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
272
|
+
/* Neutralize EDS `<Typography>` when used inside custom cell renderers.
|
|
273
|
+
Typography defaults to its own color, weight, `<p>` margin, and
|
|
274
|
+
a `1.429em` line-height, all of which break the grid's uniform
|
|
275
|
+
row appearance.
|
|
276
|
+
|
|
277
|
+
`!important` is required: EDS ships a global rule with an ID
|
|
278
|
+
selector (specificity 1,1,0) that wins over any class-based
|
|
279
|
+
chain. The third-party rule is itself a hardcoded-ID hack;
|
|
280
|
+
overriding with `!important` is the correct counter and stays
|
|
281
|
+
scoped to elements inside a grid cell. */
|
|
282
|
+
}
|
|
283
|
+
tbw-grid [part=cell] [class*=Typography__StyledTypography], tbw-grid .data-grid-row .cell [class*=Typography__StyledTypography],
|
|
284
|
+
[data-tbw-grid] [part=cell] [class*=Typography__StyledTypography],
|
|
285
|
+
[data-tbw-grid] .data-grid-row .cell [class*=Typography__StyledTypography] {
|
|
286
|
+
color: inherit !important;
|
|
287
|
+
font-family: inherit !important;
|
|
288
|
+
font-size: inherit !important;
|
|
289
|
+
font-weight: inherit !important;
|
|
290
|
+
line-height: inherit !important;
|
|
291
|
+
letter-spacing: inherit !important;
|
|
292
|
+
}
|
|
293
|
+
tbw-grid [part=cell].editing, tbw-grid .data-grid-row .cell.editing,
|
|
294
|
+
[data-tbw-grid] [part=cell].editing,
|
|
295
|
+
[data-tbw-grid] .data-grid-row .cell.editing {
|
|
210
296
|
padding: 2px 1px;
|
|
211
297
|
position: relative;
|
|
212
298
|
}
|
|
213
|
-
tbw-grid [part=cell]
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
299
|
+
tbw-grid [part=cell], tbw-grid .data-grid-row .cell,
|
|
300
|
+
[data-tbw-grid] [part=cell],
|
|
301
|
+
[data-tbw-grid] .data-grid-row .cell {
|
|
302
|
+
/* Pinned cell focus tint.
|
|
303
|
+
|
|
304
|
+
The grid's own `.cell-focus` rule already paints
|
|
305
|
+
`--tbw-focus-background` (set in section 1 to an alpha-blended
|
|
306
|
+
accent) on any focused cell. On a sticky cell the rows behind
|
|
307
|
+
would scroll through that translucent tint as the user pans
|
|
308
|
+
horizontally, so we pre-composite the same 8% accent onto the
|
|
309
|
+
pinned-cell `--tbw-color-panel-bg` to keep the result fully opaque.
|
|
310
|
+
This is the only place we still target `.cell-focus` directly
|
|
311
|
+
— `color-mix` needs the panel-bg as a second color, which a
|
|
312
|
+
single variable can't express. */
|
|
313
|
+
}
|
|
314
|
+
tbw-grid [part=cell].cell-focus.sticky-left, tbw-grid [part=cell].cell-focus.sticky-right, tbw-grid .data-grid-row .cell.cell-focus.sticky-left, tbw-grid .data-grid-row .cell.cell-focus.sticky-right,
|
|
315
|
+
[data-tbw-grid] [part=cell].cell-focus.sticky-left,
|
|
316
|
+
[data-tbw-grid] [part=cell].cell-focus.sticky-right,
|
|
317
|
+
[data-tbw-grid] .data-grid-row .cell.cell-focus.sticky-left,
|
|
318
|
+
[data-tbw-grid] .data-grid-row .cell.cell-focus.sticky-right {
|
|
319
|
+
background: color-mix(in srgb, var(--_accent) 8%, var(--tbw-color-panel-bg));
|
|
320
|
+
}
|
|
321
|
+
tbw-grid [part=cell], tbw-grid .data-grid-row .cell,
|
|
322
|
+
[data-tbw-grid] [part=cell],
|
|
323
|
+
[data-tbw-grid] .data-grid-row .cell {
|
|
217
324
|
/* Editor host — visual boundary for all editor types */
|
|
218
325
|
}
|
|
219
|
-
tbw-grid [part=cell] .tbw-editor-host, tbw-grid .data-grid-row .cell .tbw-editor-host
|
|
326
|
+
tbw-grid [part=cell] .tbw-editor-host, tbw-grid .data-grid-row .cell .tbw-editor-host,
|
|
327
|
+
[data-tbw-grid] [part=cell] .tbw-editor-host,
|
|
328
|
+
[data-tbw-grid] .data-grid-row .cell .tbw-editor-host {
|
|
220
329
|
border: 1px solid var(--_border);
|
|
221
|
-
background: var(--
|
|
330
|
+
background: var(--tbw-color-bg);
|
|
222
331
|
display: flex;
|
|
223
332
|
align-items: center;
|
|
224
333
|
width: 100%;
|
|
@@ -226,31 +335,61 @@ tbw-grid [part=cell] .tbw-editor-host, tbw-grid .data-grid-row .cell .tbw-editor
|
|
|
226
335
|
box-sizing: border-box;
|
|
227
336
|
padding: var(--tbw-cell-padding, 0 6px);
|
|
228
337
|
}
|
|
229
|
-
tbw-grid [part=cell] .tbw-editor-host:has(.mat-form-field-invalid), tbw-grid .data-grid-row .cell .tbw-editor-host:has(.mat-form-field-invalid)
|
|
338
|
+
tbw-grid [part=cell] .tbw-editor-host:has(.mat-form-field-invalid), tbw-grid .data-grid-row .cell .tbw-editor-host:has(.mat-form-field-invalid),
|
|
339
|
+
[data-tbw-grid] [part=cell] .tbw-editor-host:has(.mat-form-field-invalid),
|
|
340
|
+
[data-tbw-grid] .data-grid-row .cell .tbw-editor-host:has(.mat-form-field-invalid) {
|
|
230
341
|
border-color: var(--tbw-invalid-border-color);
|
|
231
342
|
}
|
|
232
|
-
tbw-grid [part=cell] .tbw-editor-host:focus-within, tbw-grid .data-grid-row .cell .tbw-editor-host:focus-within
|
|
343
|
+
tbw-grid [part=cell] .tbw-editor-host:focus-within, tbw-grid .data-grid-row .cell .tbw-editor-host:focus-within,
|
|
344
|
+
[data-tbw-grid] [part=cell] .tbw-editor-host:focus-within,
|
|
345
|
+
[data-tbw-grid] .data-grid-row .cell .tbw-editor-host:focus-within {
|
|
233
346
|
box-shadow: inset 0 -2px 0 0 var(--_accent);
|
|
234
347
|
outline: none;
|
|
235
348
|
}
|
|
236
|
-
tbw-grid [part=cell] .tbw-editor-host, tbw-grid .data-grid-row .cell .tbw-editor-host
|
|
349
|
+
tbw-grid [part=cell] .tbw-editor-host, tbw-grid .data-grid-row .cell .tbw-editor-host,
|
|
350
|
+
[data-tbw-grid] [part=cell] .tbw-editor-host,
|
|
351
|
+
[data-tbw-grid] .data-grid-row .cell .tbw-editor-host {
|
|
352
|
+
/* Editors that bring their own full-bleed input (e.g. EDS DatePicker /
|
|
353
|
+
Autocomplete) opt out of the host's padding so they can stretch
|
|
354
|
+
to fill the cell. See section 7. */
|
|
355
|
+
}
|
|
356
|
+
tbw-grid [part=cell] .tbw-editor-host:has(.tbw-eds-date-editor), tbw-grid [part=cell] .tbw-editor-host:has(.tbw-eds-autocomplete-editor), tbw-grid .data-grid-row .cell .tbw-editor-host:has(.tbw-eds-date-editor), tbw-grid .data-grid-row .cell .tbw-editor-host:has(.tbw-eds-autocomplete-editor),
|
|
357
|
+
[data-tbw-grid] [part=cell] .tbw-editor-host:has(.tbw-eds-date-editor),
|
|
358
|
+
[data-tbw-grid] [part=cell] .tbw-editor-host:has(.tbw-eds-autocomplete-editor),
|
|
359
|
+
[data-tbw-grid] .data-grid-row .cell .tbw-editor-host:has(.tbw-eds-date-editor),
|
|
360
|
+
[data-tbw-grid] .data-grid-row .cell .tbw-editor-host:has(.tbw-eds-autocomplete-editor) {
|
|
361
|
+
padding: 0;
|
|
362
|
+
}
|
|
363
|
+
tbw-grid [part=cell] .tbw-editor-host, tbw-grid .data-grid-row .cell .tbw-editor-host,
|
|
364
|
+
[data-tbw-grid] [part=cell] .tbw-editor-host,
|
|
365
|
+
[data-tbw-grid] .data-grid-row .cell .tbw-editor-host {
|
|
237
366
|
/* Framework component hosts: transparent for flex layout.
|
|
238
367
|
:where() for zero specificity so component :host styles can override.
|
|
239
368
|
Excludes form elements and custom editor boxes. */
|
|
240
369
|
}
|
|
241
|
-
tbw-grid [part=cell] .tbw-editor-host > :where(:not(input, select, textarea, [contenteditable], .tbw-editor-box)), tbw-grid .data-grid-row .cell .tbw-editor-host > :where(:not(input, select, textarea, [contenteditable], .tbw-editor-box))
|
|
370
|
+
tbw-grid [part=cell] .tbw-editor-host > :where(:not(input, select, textarea, [contenteditable], .tbw-editor-box)), tbw-grid .data-grid-row .cell .tbw-editor-host > :where(:not(input, select, textarea, [contenteditable], .tbw-editor-box)),
|
|
371
|
+
[data-tbw-grid] [part=cell] .tbw-editor-host > :where(:not(input, select, textarea, [contenteditable], .tbw-editor-box)),
|
|
372
|
+
[data-tbw-grid] .data-grid-row .cell .tbw-editor-host > :where(:not(input, select, textarea, [contenteditable], .tbw-editor-box)) {
|
|
242
373
|
display: contents;
|
|
243
374
|
}
|
|
244
|
-
tbw-grid [part=cell] .tbw-editor-host > .tbw-editor-box, tbw-grid .data-grid-row .cell .tbw-editor-host > .tbw-editor-box
|
|
375
|
+
tbw-grid [part=cell] .tbw-editor-host > .tbw-editor-box, tbw-grid .data-grid-row .cell .tbw-editor-host > .tbw-editor-box,
|
|
376
|
+
[data-tbw-grid] [part=cell] .tbw-editor-host > .tbw-editor-box,
|
|
377
|
+
[data-tbw-grid] .data-grid-row .cell .tbw-editor-host > .tbw-editor-box {
|
|
245
378
|
display: flex;
|
|
246
379
|
align-items: center;
|
|
247
380
|
width: 100%;
|
|
248
381
|
height: 100%;
|
|
249
382
|
}
|
|
250
|
-
tbw-grid [part=cell] .tbw-editor-host, tbw-grid .data-grid-row .cell .tbw-editor-host
|
|
383
|
+
tbw-grid [part=cell] .tbw-editor-host, tbw-grid .data-grid-row .cell .tbw-editor-host,
|
|
384
|
+
[data-tbw-grid] [part=cell] .tbw-editor-host,
|
|
385
|
+
[data-tbw-grid] .data-grid-row .cell .tbw-editor-host {
|
|
251
386
|
/* Simple text/number inputs */
|
|
252
387
|
}
|
|
253
|
-
tbw-grid [part=cell] .tbw-editor-host > input[type=text], tbw-grid [part=cell] .tbw-editor-host > input[type=number], tbw-grid .data-grid-row .cell .tbw-editor-host > input[type=text], tbw-grid .data-grid-row .cell .tbw-editor-host > input[type=number]
|
|
388
|
+
tbw-grid [part=cell] .tbw-editor-host > input[type=text], tbw-grid [part=cell] .tbw-editor-host > input[type=number], tbw-grid .data-grid-row .cell .tbw-editor-host > input[type=text], tbw-grid .data-grid-row .cell .tbw-editor-host > input[type=number],
|
|
389
|
+
[data-tbw-grid] [part=cell] .tbw-editor-host > input[type=text],
|
|
390
|
+
[data-tbw-grid] [part=cell] .tbw-editor-host > input[type=number],
|
|
391
|
+
[data-tbw-grid] .data-grid-row .cell .tbw-editor-host > input[type=text],
|
|
392
|
+
[data-tbw-grid] .data-grid-row .cell .tbw-editor-host > input[type=number] {
|
|
254
393
|
border: none;
|
|
255
394
|
background: transparent;
|
|
256
395
|
font: inherit;
|
|
@@ -260,10 +399,14 @@ tbw-grid [part=cell] .tbw-editor-host > input[type=text], tbw-grid [part=cell] .
|
|
|
260
399
|
width: 100%;
|
|
261
400
|
height: 100%;
|
|
262
401
|
}
|
|
263
|
-
tbw-grid [part=cell] .tbw-editor-host, tbw-grid .data-grid-row .cell .tbw-editor-host
|
|
402
|
+
tbw-grid [part=cell] .tbw-editor-host, tbw-grid .data-grid-row .cell .tbw-editor-host,
|
|
403
|
+
[data-tbw-grid] [part=cell] .tbw-editor-host,
|
|
404
|
+
[data-tbw-grid] .data-grid-row .cell .tbw-editor-host {
|
|
264
405
|
/* Native select */
|
|
265
406
|
}
|
|
266
|
-
tbw-grid [part=cell] .tbw-editor-host > select, tbw-grid .data-grid-row .cell .tbw-editor-host > select
|
|
407
|
+
tbw-grid [part=cell] .tbw-editor-host > select, tbw-grid .data-grid-row .cell .tbw-editor-host > select,
|
|
408
|
+
[data-tbw-grid] [part=cell] .tbw-editor-host > select,
|
|
409
|
+
[data-tbw-grid] .data-grid-row .cell .tbw-editor-host > select {
|
|
267
410
|
appearance: base-select;
|
|
268
411
|
border: none;
|
|
269
412
|
background: transparent;
|
|
@@ -276,7 +419,9 @@ tbw-grid [part=cell] .tbw-editor-host > select, tbw-grid .data-grid-row .cell .t
|
|
|
276
419
|
cursor: pointer;
|
|
277
420
|
place-items: center;
|
|
278
421
|
}
|
|
279
|
-
tbw-grid [part=cell] .tbw-editor-host > select::picker(select), tbw-grid .data-grid-row .cell .tbw-editor-host > select::picker(select)
|
|
422
|
+
tbw-grid [part=cell] .tbw-editor-host > select::picker(select), tbw-grid .data-grid-row .cell .tbw-editor-host > select::picker(select),
|
|
423
|
+
[data-tbw-grid] [part=cell] .tbw-editor-host > select::picker(select),
|
|
424
|
+
[data-tbw-grid] .data-grid-row .cell .tbw-editor-host > select::picker(select) {
|
|
280
425
|
appearance: base-select;
|
|
281
426
|
border: none;
|
|
282
427
|
border-radius: 4px;
|
|
@@ -284,7 +429,9 @@ tbw-grid [part=cell] .tbw-editor-host > select::picker(select), tbw-grid .data-g
|
|
|
284
429
|
overscroll-behavior: contain;
|
|
285
430
|
box-shadow: 0 2px 4px -1px rgba(0, 0, 0, 0.2), 0 4px 5px 0 rgba(0, 0, 0, 0.14), 0 1px 10px 0 rgba(0, 0, 0, 0.12);
|
|
286
431
|
}
|
|
287
|
-
tbw-grid [part=cell] .tbw-editor-host > select option, tbw-grid .data-grid-row .cell .tbw-editor-host > select option
|
|
432
|
+
tbw-grid [part=cell] .tbw-editor-host > select option, tbw-grid .data-grid-row .cell .tbw-editor-host > select option,
|
|
433
|
+
[data-tbw-grid] [part=cell] .tbw-editor-host > select option,
|
|
434
|
+
[data-tbw-grid] .data-grid-row .cell .tbw-editor-host > select option {
|
|
288
435
|
font: inherit;
|
|
289
436
|
padding: 8px 16px;
|
|
290
437
|
min-height: 36px;
|
|
@@ -292,41 +439,52 @@ tbw-grid [part=cell] .tbw-editor-host > select option, tbw-grid .data-grid-row .
|
|
|
292
439
|
align-items: center;
|
|
293
440
|
border-radius: 0;
|
|
294
441
|
}
|
|
295
|
-
tbw-grid [part=cell] .tbw-editor-host > select option:hover, tbw-grid .data-grid-row .cell .tbw-editor-host > select option:hover
|
|
442
|
+
tbw-grid [part=cell] .tbw-editor-host > select option:hover, tbw-grid .data-grid-row .cell .tbw-editor-host > select option:hover,
|
|
443
|
+
[data-tbw-grid] [part=cell] .tbw-editor-host > select option:hover,
|
|
444
|
+
[data-tbw-grid] .data-grid-row .cell .tbw-editor-host > select option:hover {
|
|
296
445
|
background-color: light-dark(rgba(0, 0, 0, 0.04), rgba(255, 255, 255, 0.08));
|
|
297
446
|
}
|
|
298
|
-
tbw-grid [part=cell] .tbw-editor-host > select option:checked, tbw-grid .data-grid-row .cell .tbw-editor-host > select option:checked
|
|
447
|
+
tbw-grid [part=cell] .tbw-editor-host > select option:checked, tbw-grid .data-grid-row .cell .tbw-editor-host > select option:checked,
|
|
448
|
+
[data-tbw-grid] [part=cell] .tbw-editor-host > select option:checked,
|
|
449
|
+
[data-tbw-grid] .data-grid-row .cell .tbw-editor-host > select option:checked {
|
|
299
450
|
background-color: light-dark(rgba(0, 112, 121, 0.12), rgba(151, 202, 206, 0.2));
|
|
300
451
|
color: inherit;
|
|
301
452
|
}
|
|
302
|
-
tbw-grid
|
|
453
|
+
tbw-grid,
|
|
454
|
+
[data-tbw-grid] {
|
|
303
455
|
/* --- Material form field stripping inside editor hosts ---
|
|
304
456
|
Lower specificity than cell-scoped rules above; strips
|
|
305
457
|
Angular Material chrome so .tbw-editor-host provides visuals. */
|
|
306
458
|
}
|
|
307
|
-
tbw-grid .tbw-editor-host .mat-mdc-form-field
|
|
459
|
+
tbw-grid .tbw-editor-host .mat-mdc-form-field,
|
|
460
|
+
[data-tbw-grid] .tbw-editor-host .mat-mdc-form-field {
|
|
308
461
|
width: 100%;
|
|
309
462
|
height: 100%;
|
|
310
463
|
}
|
|
311
|
-
tbw-grid .tbw-editor-host .mat-mdc-form-field .mat-mdc-text-field-wrapper
|
|
464
|
+
tbw-grid .tbw-editor-host .mat-mdc-form-field .mat-mdc-text-field-wrapper,
|
|
465
|
+
[data-tbw-grid] .tbw-editor-host .mat-mdc-form-field .mat-mdc-text-field-wrapper {
|
|
312
466
|
padding: 0 4px;
|
|
313
467
|
background: transparent;
|
|
314
468
|
height: 100%;
|
|
315
469
|
display: flex;
|
|
316
470
|
align-items: center;
|
|
317
471
|
}
|
|
318
|
-
tbw-grid .tbw-editor-host .mat-mdc-form-field .mat-mdc-form-field-flex
|
|
472
|
+
tbw-grid .tbw-editor-host .mat-mdc-form-field .mat-mdc-form-field-flex,
|
|
473
|
+
[data-tbw-grid] .tbw-editor-host .mat-mdc-form-field .mat-mdc-form-field-flex {
|
|
319
474
|
height: 100%;
|
|
320
475
|
display: flex;
|
|
321
476
|
align-items: center;
|
|
322
477
|
}
|
|
323
|
-
tbw-grid .tbw-editor-host .mat-mdc-form-field .mat-mdc-form-field-focus-overlay
|
|
478
|
+
tbw-grid .tbw-editor-host .mat-mdc-form-field .mat-mdc-form-field-focus-overlay,
|
|
479
|
+
[data-tbw-grid] .tbw-editor-host .mat-mdc-form-field .mat-mdc-form-field-focus-overlay {
|
|
324
480
|
display: none;
|
|
325
481
|
}
|
|
326
|
-
tbw-grid .tbw-editor-host .mat-mdc-form-field .mdc-line-ripple
|
|
482
|
+
tbw-grid .tbw-editor-host .mat-mdc-form-field .mdc-line-ripple,
|
|
483
|
+
[data-tbw-grid] .tbw-editor-host .mat-mdc-form-field .mdc-line-ripple {
|
|
327
484
|
display: none;
|
|
328
485
|
}
|
|
329
|
-
tbw-grid .tbw-editor-host .mat-mdc-form-field .mat-mdc-form-field-infix
|
|
486
|
+
tbw-grid .tbw-editor-host .mat-mdc-form-field .mat-mdc-form-field-infix,
|
|
487
|
+
[data-tbw-grid] .tbw-editor-host .mat-mdc-form-field .mat-mdc-form-field-infix {
|
|
330
488
|
padding: 0;
|
|
331
489
|
min-height: unset;
|
|
332
490
|
width: 100%;
|
|
@@ -334,57 +492,175 @@ tbw-grid .tbw-editor-host .mat-mdc-form-field .mat-mdc-form-field-infix {
|
|
|
334
492
|
align-items: center;
|
|
335
493
|
border: 0;
|
|
336
494
|
}
|
|
337
|
-
tbw-grid .tbw-editor-host .mat-mdc-form-field input.mat-mdc-input-element
|
|
495
|
+
tbw-grid .tbw-editor-host .mat-mdc-form-field input.mat-mdc-input-element,
|
|
496
|
+
[data-tbw-grid] .tbw-editor-host .mat-mdc-form-field input.mat-mdc-input-element {
|
|
497
|
+
/* `line-height: normal` is browser/font-dependent (≈ 1.2-1.5) which
|
|
498
|
+
inflates the `1lh + 2 * padding` floor used by `.cell.editing`
|
|
499
|
+
and pushes the editing row past `--tbw-row-height`. Locking it
|
|
500
|
+
to 1 keeps the input the height of its font-size so the cell can
|
|
501
|
+
collapse to `--tbw-row-height` in compact mode. */
|
|
338
502
|
height: auto;
|
|
339
|
-
line-height:
|
|
503
|
+
line-height: 1;
|
|
340
504
|
}
|
|
341
|
-
tbw-grid .tbw-editor-host .mat-mdc-form-field .mat-mdc-select
|
|
505
|
+
tbw-grid .tbw-editor-host .mat-mdc-form-field .mat-mdc-select,
|
|
506
|
+
[data-tbw-grid] .tbw-editor-host .mat-mdc-form-field .mat-mdc-select {
|
|
342
507
|
height: 100%;
|
|
343
508
|
display: flex;
|
|
344
509
|
align-items: center;
|
|
345
510
|
}
|
|
346
|
-
tbw-grid .tbw-editor-host .mat-mdc-form-field .mat-mdc-select-trigger
|
|
511
|
+
tbw-grid .tbw-editor-host .mat-mdc-form-field .mat-mdc-select-trigger,
|
|
512
|
+
[data-tbw-grid] .tbw-editor-host .mat-mdc-form-field .mat-mdc-select-trigger {
|
|
347
513
|
height: 100%;
|
|
348
514
|
display: flex;
|
|
349
515
|
align-items: center;
|
|
350
516
|
}
|
|
351
|
-
tbw-grid .tbw-editor-host .mat-mdc-form-field .mat-mdc-select-value
|
|
517
|
+
tbw-grid .tbw-editor-host .mat-mdc-form-field .mat-mdc-select-value,
|
|
518
|
+
[data-tbw-grid] .tbw-editor-host .mat-mdc-form-field .mat-mdc-select-value {
|
|
352
519
|
display: flex;
|
|
353
520
|
align-items: center;
|
|
354
521
|
}
|
|
355
|
-
tbw-grid .tbw-editor-host .mat-mdc-form-field-subscript-wrapper
|
|
522
|
+
tbw-grid .tbw-editor-host .mat-mdc-form-field-subscript-wrapper,
|
|
523
|
+
[data-tbw-grid] .tbw-editor-host .mat-mdc-form-field-subscript-wrapper {
|
|
356
524
|
display: none;
|
|
357
525
|
}
|
|
358
|
-
tbw-grid .tbw-editor-host .editor-checkbox
|
|
526
|
+
tbw-grid .tbw-editor-host .editor-checkbox,
|
|
527
|
+
[data-tbw-grid] .tbw-editor-host .editor-checkbox {
|
|
359
528
|
display: flex;
|
|
360
529
|
align-items: center;
|
|
361
530
|
justify-content: center;
|
|
362
531
|
height: 100%;
|
|
363
532
|
}
|
|
364
|
-
tbw-grid .tbw-editor-host .mat-mdc-option.mdc-list-item
|
|
533
|
+
tbw-grid .tbw-editor-host .mat-mdc-option.mdc-list-item,
|
|
534
|
+
[data-tbw-grid] .tbw-editor-host .mat-mdc-option.mdc-list-item {
|
|
365
535
|
background: var(--mat-autocomplete-background-color, var(--mat-sys-surface-container));
|
|
366
536
|
}
|
|
537
|
+
tbw-grid,
|
|
538
|
+
[data-tbw-grid] {
|
|
539
|
+
/* ================================================================
|
|
540
|
+
* 3. Pinned cells & sticky group rows
|
|
541
|
+
* ================================================================ */
|
|
542
|
+
/* Row hover on pinned cells.
|
|
367
543
|
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
544
|
+
Pinned cells (`.sticky-left` / `.sticky-right`) carry an opaque
|
|
545
|
+
`--tbw-color-panel-bg` so non-sticky content scrolling behind
|
|
546
|
+
them can't bleed through. That opaque fill also masks the row's
|
|
547
|
+
`:hover` tint, making pinned columns visually disconnected from
|
|
548
|
+
the rest of the row. Repaint them with the row-hover color to
|
|
549
|
+
restore continuity. Wrapped in `@media (hover: hover)` to mirror
|
|
550
|
+
the grid's own row-hover rule and avoid sticky tap-state flicker
|
|
551
|
+
on touch devices. */
|
|
552
|
+
}
|
|
553
|
+
@media (hover: hover) {
|
|
554
|
+
tbw-grid .data-grid-row:hover > .cell.sticky-left, tbw-grid .data-grid-row:hover > .cell.sticky-right,
|
|
555
|
+
[data-tbw-grid] .data-grid-row:hover > .cell.sticky-left,
|
|
556
|
+
[data-tbw-grid] .data-grid-row:hover > .cell.sticky-right {
|
|
557
|
+
background: var(--tbw-color-row-hover);
|
|
558
|
+
}
|
|
559
|
+
tbw-grid,
|
|
560
|
+
[data-tbw-grid] {
|
|
561
|
+
/* Hover + focus on a pinned cell: keep the focus tint visible by
|
|
562
|
+
flattening the same 8% accent over the row-hover color. */
|
|
563
|
+
}
|
|
564
|
+
tbw-grid .data-grid-row:hover > .cell.cell-focus.sticky-left, tbw-grid .data-grid-row:hover > .cell.cell-focus.sticky-right,
|
|
565
|
+
[data-tbw-grid] .data-grid-row:hover > .cell.cell-focus.sticky-left,
|
|
566
|
+
[data-tbw-grid] .data-grid-row:hover > .cell.cell-focus.sticky-right {
|
|
567
|
+
background: color-mix(in srgb, var(--tbw-color-accent) 8%, var(--tbw-color-row-hover));
|
|
568
|
+
}
|
|
569
|
+
}
|
|
570
|
+
tbw-grid,
|
|
571
|
+
[data-tbw-grid] {
|
|
572
|
+
/* Sticky group-row chrome.
|
|
573
|
+
|
|
574
|
+
The grouping-rows feature renders a full-width banner row for each
|
|
575
|
+
group boundary: a `.data-grid-row.group-row` whose only child is a
|
|
576
|
+
single `.cell.group-full` (spanning `grid-column: 1 / -1`) containing
|
|
577
|
+
`.group-toggle`, `.group-label`, `.group-count`, and optional
|
|
578
|
+
`.group-aggregates`. On a horizontally-scrollable grid the cell is
|
|
579
|
+
as wide as the row, so when the user scrolls right the entire chrome
|
|
580
|
+
slides off the left edge.
|
|
581
|
+
|
|
582
|
+
Approach: shrink the cell to its content width and pin it to the left
|
|
583
|
+
with `position: sticky; left: 0`. The chrome children keep their
|
|
584
|
+
inline flow — we never touch them individually, so new chrome
|
|
585
|
+
elements in a future grid version "just work".
|
|
586
|
+
|
|
587
|
+
Two things move from the cell up to the row:
|
|
588
|
+
1. Background — the cell no longer spans the row, so the row paints
|
|
589
|
+
the banner tint.
|
|
590
|
+
2. Full-row span override — the cell still has `grid-column: 1 / -1`
|
|
591
|
+
from the grid runtime; `width: max-content !important` shrinks
|
|
592
|
+
the rendered box while leaving the grid-track placement intact.
|
|
593
|
+
|
|
594
|
+
Why we override `overflow: hidden` on the cell:
|
|
595
|
+
@toolbox-web/grid sets `overflow: hidden` on every `.cell` to clip
|
|
596
|
+
content. Per the CSS Position spec, that establishes a scroll
|
|
597
|
+
container, which traps the cell's own sticky positioning inside the
|
|
598
|
+
(non-scrolling) cell box. `overflow: visible` lets the sticky context
|
|
599
|
+
bubble up past the row, past `.rows-viewport` (`overflow: clip` —
|
|
600
|
+
non-scrollable), all the way to `.tbw-scroll-area` (the actual
|
|
601
|
+
horizontal scroller) where sticky engages. */
|
|
602
|
+
}
|
|
603
|
+
tbw-grid .data-grid-row.group-row,
|
|
604
|
+
[data-tbw-grid] .data-grid-row.group-row {
|
|
605
|
+
background: var(--tbw-color-header-bg, var(--tbw-color-panel-bg, transparent));
|
|
606
|
+
}
|
|
607
|
+
tbw-grid .data-grid-row.group-row > .cell.group-full,
|
|
608
|
+
[data-tbw-grid] .data-grid-row.group-row > .cell.group-full {
|
|
609
|
+
overflow: visible;
|
|
610
|
+
position: sticky;
|
|
611
|
+
left: 0;
|
|
612
|
+
z-index: 2;
|
|
613
|
+
width: max-content !important;
|
|
614
|
+
max-width: 100%;
|
|
615
|
+
background: transparent;
|
|
616
|
+
}
|
|
617
|
+
tbw-grid .data-grid-row.group-row .group-count,
|
|
618
|
+
[data-tbw-grid] .data-grid-row.group-row .group-count {
|
|
619
|
+
padding: 0 0.5rem;
|
|
620
|
+
}
|
|
621
|
+
tbw-grid,
|
|
622
|
+
[data-tbw-grid] {
|
|
623
|
+
/* Sticky aggregation (footer) row.
|
|
624
|
+
|
|
625
|
+
The bottom aggregation row (`.tbw-footer > .tbw-aggregation-rows >
|
|
626
|
+
.tbw-aggregation-row > .tbw-aggregation-cell.tbw-aggregation-cell-full`)
|
|
627
|
+
has the same shape as a group row: a full-width cell that spans the
|
|
628
|
+
entire scrollable area (`grid-column: 1 / -1`, width = scrollWidth).
|
|
629
|
+
When the user scrolls horizontally the totals/label slide off the
|
|
630
|
+
left edge.
|
|
631
|
+
|
|
632
|
+
Same fix as `.group-row > .cell.group-full`: shrink the cell to its
|
|
633
|
+
content width, pin it to the left with `position: sticky; left: 0`,
|
|
634
|
+
and override the grid's `overflow: hidden` so the sticky context can
|
|
635
|
+
bubble up past the row to the scroll container.
|
|
636
|
+
|
|
637
|
+
`.tbw-footer` itself is already `position: sticky; bottom: 0` from
|
|
638
|
+
the grid runtime — we only need to handle horizontal stickiness. */
|
|
639
|
+
}
|
|
640
|
+
tbw-grid .tbw-aggregation-row > .tbw-aggregation-cell-full,
|
|
641
|
+
[data-tbw-grid] .tbw-aggregation-row > .tbw-aggregation-cell-full {
|
|
642
|
+
overflow: visible;
|
|
643
|
+
position: sticky;
|
|
644
|
+
left: 0;
|
|
645
|
+
z-index: 2;
|
|
646
|
+
width: max-content !important;
|
|
647
|
+
max-width: 100%;
|
|
648
|
+
background: transparent;
|
|
372
649
|
}
|
|
373
650
|
|
|
374
651
|
/* ================================================================
|
|
375
|
-
*
|
|
652
|
+
* 4. Filter Panel Styles
|
|
376
653
|
* ================================================================ */
|
|
377
654
|
.tbw-filter-panel {
|
|
378
655
|
max-width: none;
|
|
379
656
|
max-height: none;
|
|
380
|
-
/* EDS underline inputs
|
|
657
|
+
/* EDS underline inputs — the bg/border/radius are stripped via
|
|
658
|
+
`--tbw-filter-input-*` variables in section 1. The underline
|
|
659
|
+
`box-shadow` and height have no variable equivalent. */
|
|
381
660
|
}
|
|
382
661
|
.tbw-filter-panel .tbw-filter-search-input, .tbw-filter-panel .tbw-filter-range-input, .tbw-filter-panel .tbw-filter-date-input {
|
|
383
662
|
height: var(--tbw-row-height);
|
|
384
|
-
border: none;
|
|
385
|
-
border-radius: 0;
|
|
386
663
|
box-shadow: inset 0px -1px 0px 0px var(--_fg-muted);
|
|
387
|
-
background: var(--_surface);
|
|
388
664
|
outline: 1px solid transparent;
|
|
389
665
|
outline-offset: 0px;
|
|
390
666
|
}
|
|
@@ -459,7 +735,7 @@ tbw-grid .tbw-editor-host .mat-mdc-option.mdc-list-item {
|
|
|
459
735
|
}
|
|
460
736
|
|
|
461
737
|
/* ================================================================
|
|
462
|
-
*
|
|
738
|
+
* 5. Context Menu
|
|
463
739
|
*
|
|
464
740
|
* Appended to document.body (outside tbw-grid).
|
|
465
741
|
* CSS variables are copied from tbw-grid at render time.
|
|
@@ -514,7 +790,7 @@ tbw-grid .tbw-editor-host .mat-mdc-option.mdc-list-item {
|
|
|
514
790
|
}
|
|
515
791
|
|
|
516
792
|
/* ================================================================
|
|
517
|
-
*
|
|
793
|
+
* 6. Overlay Panel (BaseOverlayEditor)
|
|
518
794
|
* ================================================================ */
|
|
519
795
|
.tbw-overlay-panel {
|
|
520
796
|
--tbw-overlay-bg: var(
|
|
@@ -531,9 +807,249 @@ tbw-grid .tbw-editor-host .mat-mdc-option.mdc-list-item {
|
|
|
531
807
|
}
|
|
532
808
|
|
|
533
809
|
/* ================================================================
|
|
534
|
-
*
|
|
810
|
+
* 7. EDS in-cell editors — DatePicker and Autocomplete
|
|
811
|
+
*
|
|
812
|
+
* Marker classes:
|
|
813
|
+
* `.tbw-eds-date-editor` — wrapper around EDS <DatePicker>
|
|
814
|
+
* `.tbw-eds-autocomplete-editor` — wrapper around EDS <Autocomplete>
|
|
815
|
+
*
|
|
816
|
+
* Used by React consumers that render EDS form components inside grid
|
|
817
|
+
* cell editors (typically inside `<EdsProvider density="compact">`).
|
|
818
|
+
* EDS wraps each field in an InputWrapper with a label and helper
|
|
819
|
+
* area — none of which we want inside a row-height cell. We strip the
|
|
820
|
+
* chrome, hide the label/helper for sighted users (kept for screen
|
|
821
|
+
* readers), and stretch the inner field stack to fill the cell.
|
|
822
|
+
*
|
|
823
|
+
* Popover positioning fix (applies to both):
|
|
824
|
+
* EDS uses the native popover API (`popover="manual"`) + floating-ui
|
|
825
|
+
* to place the calendar / options dropdown. Inline EDS sets
|
|
826
|
+
* `position: absolute` with viewport-anchored top/left from the
|
|
827
|
+
* trigger's getBoundingClientRect. That works in plain DOM, but
|
|
828
|
+
* `tbw-grid` virtualises rows with `transform` which creates a
|
|
829
|
+
* containing block. Once the popover enters the browser top-layer
|
|
830
|
+
* (`.showPopover()`), the spec says its containing block is the
|
|
831
|
+
* viewport — but floating-ui's inset values assume the regular
|
|
832
|
+
* containing-block cascade. The two coordinate systems mismatch and
|
|
833
|
+
* the popover renders off-screen.
|
|
834
|
+
*
|
|
835
|
+
* Forcing `position: fixed` aligns the popover's containing block
|
|
836
|
+
* with floating-ui's viewport math. The inset reset overrides the
|
|
837
|
+
* browser's default `[popover]:popover-open { inset: 0 }` rule that
|
|
838
|
+
* would otherwise stretch the popover full-viewport.
|
|
839
|
+
*
|
|
840
|
+
* Harmless when EDS is absent (Angular consumers don't ship these
|
|
841
|
+
* markers), so safe to include in the shared theme.
|
|
842
|
+
* ================================================================ */
|
|
843
|
+
/* Shared chrome-stripping + popover-positioning rules. Applied to both
|
|
844
|
+
editor wrappers via @extend so the rules stay co-located with their
|
|
845
|
+
shared docstring above. */
|
|
846
|
+
.tbw-eds-autocomplete-editor, .tbw-eds-date-editor {
|
|
847
|
+
width: 100%;
|
|
848
|
+
height: 100%;
|
|
849
|
+
display: flex;
|
|
850
|
+
align-items: stretch;
|
|
851
|
+
/* Hide the visually-rendered EDS label/helper, keep them for a11y. */
|
|
852
|
+
}
|
|
853
|
+
.tbw-eds-autocomplete-editor label, .tbw-eds-date-editor label,
|
|
854
|
+
.tbw-eds-autocomplete-editor [class*=HelperText],
|
|
855
|
+
.tbw-eds-date-editor [class*=HelperText] {
|
|
856
|
+
position: absolute;
|
|
857
|
+
width: 1px;
|
|
858
|
+
height: 1px;
|
|
859
|
+
padding: 0;
|
|
860
|
+
margin: -1px;
|
|
861
|
+
overflow: hidden;
|
|
862
|
+
clip: rect(0, 0, 0, 0);
|
|
863
|
+
white-space: nowrap;
|
|
864
|
+
border: 0;
|
|
865
|
+
}
|
|
866
|
+
.tbw-eds-autocomplete-editor, .tbw-eds-date-editor {
|
|
867
|
+
/* Calendar / options dropdown popover — see header for rationale. */
|
|
868
|
+
}
|
|
869
|
+
.tbw-eds-autocomplete-editor [popover], .tbw-eds-date-editor [popover] {
|
|
870
|
+
position: fixed !important;
|
|
871
|
+
right: auto !important;
|
|
872
|
+
bottom: auto !important;
|
|
873
|
+
width: max-content !important;
|
|
874
|
+
margin: 0 !important;
|
|
875
|
+
}
|
|
876
|
+
|
|
877
|
+
.tbw-eds-date-editor {
|
|
878
|
+
/* Stretch the EDS field stack to fill the cell vertically and strip
|
|
879
|
+
its own background/box-shadow underline since the surrounding
|
|
880
|
+
`.tbw-editor-host:focus-within` already provides the focus indicator.
|
|
881
|
+
`!important` beats EDS's ID-scoped rule (specificity 1,1,0).
|
|
882
|
+
NOTE: do not use `> div` — the calendar popover is also a direct
|
|
883
|
+
child once `popover="manual"` opens it, and forcing it to 100%
|
|
884
|
+
height stretches it to the full viewport and breaks auto-flip. */
|
|
885
|
+
}
|
|
886
|
+
.tbw-eds-date-editor [class*=InputWrapper__Container],
|
|
887
|
+
.tbw-eds-date-editor [class*=FieldWrapper] {
|
|
888
|
+
width: 100% !important;
|
|
889
|
+
height: 100% !important;
|
|
890
|
+
}
|
|
891
|
+
.tbw-eds-date-editor [class*=FieldWrapper] {
|
|
892
|
+
background: transparent !important;
|
|
893
|
+
box-shadow: none !important;
|
|
894
|
+
border: none !important;
|
|
895
|
+
display: flex;
|
|
896
|
+
align-items: center;
|
|
897
|
+
}
|
|
898
|
+
|
|
899
|
+
.tbw-eds-autocomplete-editor {
|
|
900
|
+
/* Stretch EDS field stack to fill the cell vertically and strip its
|
|
901
|
+
own background/underline since the editor host owns the focus ring. */
|
|
902
|
+
}
|
|
903
|
+
.tbw-eds-autocomplete-editor [class*=InputWrapper__Container],
|
|
904
|
+
.tbw-eds-autocomplete-editor [class*=Container] {
|
|
905
|
+
width: 100% !important;
|
|
906
|
+
height: 100% !important;
|
|
907
|
+
}
|
|
908
|
+
.tbw-eds-autocomplete-editor [class*=Container] {
|
|
909
|
+
background: transparent !important;
|
|
910
|
+
box-shadow: none !important;
|
|
911
|
+
border: none !important;
|
|
912
|
+
}
|
|
913
|
+
|
|
914
|
+
/* ================================================================
|
|
915
|
+
* 8. Empty State Overlay
|
|
916
|
+
*
|
|
917
|
+
* The grid's empty overlay (.tbw-empty-overlay) is absolutely
|
|
918
|
+
* positioned inside .rows-container. When the grid host is sized
|
|
919
|
+
* by content (no explicit height) and there are zero rows, the
|
|
920
|
+
* rows-container collapses to height 0 — leaving the overlay
|
|
921
|
+
* with no space and stacking the column header directly on top
|
|
922
|
+
* of the pinned/aggregation footer.
|
|
923
|
+
*
|
|
924
|
+
* Reserve a sensible minimum height for the rows area whenever
|
|
925
|
+
* the empty overlay is present, so the message has room to render
|
|
926
|
+
* and the header / footer separate visually.
|
|
927
|
+
* ================================================================ */
|
|
928
|
+
tbw-grid .rows-container:has(> .tbw-empty-overlay),
|
|
929
|
+
[data-tbw-grid] .rows-container:has(> .tbw-empty-overlay) {
|
|
930
|
+
min-height: var(--tbw-empty-min-height, 120px);
|
|
931
|
+
}
|
|
932
|
+
tbw-grid .tbw-empty-overlay,
|
|
933
|
+
[data-tbw-grid] .tbw-empty-overlay {
|
|
934
|
+
min-height: var(--tbw-empty-min-height, 120px);
|
|
935
|
+
color: var(--_fg-muted);
|
|
936
|
+
}
|
|
937
|
+
|
|
938
|
+
/* ================================================================
|
|
939
|
+
* 9. Opt-ins (compact mode, thin header)
|
|
940
|
+
* ================================================================ */
|
|
941
|
+
/* Compact mode — triggers when `.eds-compact` is on the grid itself
|
|
942
|
+
(`<tbw-grid class="eds-compact">`) or on any ancestor (e.g. a wrapping
|
|
943
|
+
section that toggles density for everything inside). */
|
|
944
|
+
tbw-grid.eds-compact,
|
|
945
|
+
[data-tbw-grid].eds-compact,
|
|
946
|
+
.eds-compact tbw-grid,
|
|
947
|
+
.eds-compact [data-tbw-grid] {
|
|
948
|
+
/* Multipliers are tuned against the 13px EDS base:
|
|
949
|
+
row 13 * 1.111 ≈ 14.4px (works once in-cell mat-icons and chip
|
|
950
|
+
padding are constrained — see section 2)
|
|
951
|
+
header 13 * 1.4 ≈ 18.2px
|
|
952
|
+
Apps with a larger base (e.g. 18px) get proportionally bigger:
|
|
953
|
+
18 * 1.111 ≈ 20px / 18 * 1.4 ≈ 25px. */
|
|
954
|
+
--tbw-row-height: calc(var(--sto-base-font-size, 13px) * 1.111);
|
|
955
|
+
--tbw-header-height: calc(var(--sto-base-font-size, 13px) * 1.4);
|
|
956
|
+
/* In-cell Material icons.
|
|
957
|
+
Angular Material renders `<mat-icon>` as `<span class="mat-icon">` at a
|
|
958
|
+
hardcoded 24x24. Since `.data-grid-row` is `display: grid` and the row
|
|
959
|
+
track grows to fit the tallest cell content, a 24px icon would inflate
|
|
960
|
+
every row past `--tbw-row-height`. Constrain in-cell icons to the cell
|
|
961
|
+
font-size so they fit the compact row track.
|
|
962
|
+
|
|
963
|
+
Sizing trick: `font-size: 1em` keeps the glyph at the cell font-size
|
|
964
|
+
(13px default), then `width/height: 1em` resolves against the icon's
|
|
965
|
+
own font-size — producing a 13x13 box. Only applied under `.eds-compact`
|
|
966
|
+
so non-compact grids keep Material's standard 24px icons. */
|
|
967
|
+
}
|
|
968
|
+
tbw-grid.eds-compact .cell .mat-icon, tbw-grid.eds-compact .cell mat-icon,
|
|
969
|
+
[data-tbw-grid].eds-compact .cell .mat-icon,
|
|
970
|
+
[data-tbw-grid].eds-compact .cell mat-icon,
|
|
971
|
+
.eds-compact tbw-grid .cell .mat-icon,
|
|
972
|
+
.eds-compact tbw-grid .cell mat-icon,
|
|
973
|
+
.eds-compact [data-tbw-grid] .cell .mat-icon,
|
|
974
|
+
.eds-compact [data-tbw-grid] .cell mat-icon {
|
|
975
|
+
font-size: 1em;
|
|
976
|
+
width: 1em;
|
|
977
|
+
height: 1em;
|
|
978
|
+
line-height: 1em;
|
|
979
|
+
}
|
|
980
|
+
tbw-grid.eds-compact,
|
|
981
|
+
[data-tbw-grid].eds-compact,
|
|
982
|
+
.eds-compact tbw-grid,
|
|
983
|
+
.eds-compact [data-tbw-grid] {
|
|
984
|
+
/* In-cell editor density.
|
|
985
|
+
Active editors (`.cell.editing > .tbw-editor-host`) host Angular
|
|
986
|
+
Material form-fields. Even with all chrome stripped (see section 2),
|
|
987
|
+
a Material input renders at ~35px tall because of its intrinsic
|
|
988
|
+
padding/min-height — which then ratchets the grid's row-height
|
|
989
|
+
measurement upward and shrinks the visible-row count for every
|
|
990
|
+
other row.
|
|
991
|
+
|
|
992
|
+
In compact mode we constrain the editor to the compact row height
|
|
993
|
+
so editing a row no longer changes the row's painted height. */
|
|
994
|
+
}
|
|
995
|
+
tbw-grid.eds-compact .cell.editing,
|
|
996
|
+
[data-tbw-grid].eds-compact .cell.editing,
|
|
997
|
+
.eds-compact tbw-grid .cell.editing,
|
|
998
|
+
.eds-compact [data-tbw-grid] .cell.editing {
|
|
999
|
+
/* Eliminate the `1lh + 2 * padding` floor inherited from the base
|
|
1000
|
+
`.cell.editing` rule — the active cell follows row-height only. */
|
|
1001
|
+
min-height: var(--tbw-row-height);
|
|
1002
|
+
}
|
|
1003
|
+
tbw-grid.eds-compact .cell.editing .tbw-editor-host, tbw-grid.eds-compact .cell.editing .tbw-editor-host .mat-mdc-form-field, tbw-grid.eds-compact .cell.editing .tbw-editor-host .mat-mdc-text-field-wrapper, tbw-grid.eds-compact .cell.editing .tbw-editor-host .mat-mdc-form-field-flex, tbw-grid.eds-compact .cell.editing .tbw-editor-host .mat-mdc-form-field-infix,
|
|
1004
|
+
[data-tbw-grid].eds-compact .cell.editing .tbw-editor-host,
|
|
1005
|
+
[data-tbw-grid].eds-compact .cell.editing .tbw-editor-host .mat-mdc-form-field,
|
|
1006
|
+
[data-tbw-grid].eds-compact .cell.editing .tbw-editor-host .mat-mdc-text-field-wrapper,
|
|
1007
|
+
[data-tbw-grid].eds-compact .cell.editing .tbw-editor-host .mat-mdc-form-field-flex,
|
|
1008
|
+
[data-tbw-grid].eds-compact .cell.editing .tbw-editor-host .mat-mdc-form-field-infix,
|
|
1009
|
+
.eds-compact tbw-grid .cell.editing .tbw-editor-host,
|
|
1010
|
+
.eds-compact tbw-grid .cell.editing .tbw-editor-host .mat-mdc-form-field,
|
|
1011
|
+
.eds-compact tbw-grid .cell.editing .tbw-editor-host .mat-mdc-text-field-wrapper,
|
|
1012
|
+
.eds-compact tbw-grid .cell.editing .tbw-editor-host .mat-mdc-form-field-flex,
|
|
1013
|
+
.eds-compact tbw-grid .cell.editing .tbw-editor-host .mat-mdc-form-field-infix,
|
|
1014
|
+
.eds-compact [data-tbw-grid] .cell.editing .tbw-editor-host,
|
|
1015
|
+
.eds-compact [data-tbw-grid] .cell.editing .tbw-editor-host .mat-mdc-form-field,
|
|
1016
|
+
.eds-compact [data-tbw-grid] .cell.editing .tbw-editor-host .mat-mdc-text-field-wrapper,
|
|
1017
|
+
.eds-compact [data-tbw-grid] .cell.editing .tbw-editor-host .mat-mdc-form-field-flex,
|
|
1018
|
+
.eds-compact [data-tbw-grid] .cell.editing .tbw-editor-host .mat-mdc-form-field-infix {
|
|
1019
|
+
min-height: 0;
|
|
1020
|
+
height: 100%;
|
|
1021
|
+
}
|
|
1022
|
+
tbw-grid.eds-compact .cell.editing .tbw-editor-host input.mat-mdc-input-element, tbw-grid.eds-compact .cell.editing .tbw-editor-host .mat-mdc-select-trigger,
|
|
1023
|
+
[data-tbw-grid].eds-compact .cell.editing .tbw-editor-host input.mat-mdc-input-element,
|
|
1024
|
+
[data-tbw-grid].eds-compact .cell.editing .tbw-editor-host .mat-mdc-select-trigger,
|
|
1025
|
+
.eds-compact tbw-grid .cell.editing .tbw-editor-host input.mat-mdc-input-element,
|
|
1026
|
+
.eds-compact tbw-grid .cell.editing .tbw-editor-host .mat-mdc-select-trigger,
|
|
1027
|
+
.eds-compact [data-tbw-grid] .cell.editing .tbw-editor-host input.mat-mdc-input-element,
|
|
1028
|
+
.eds-compact [data-tbw-grid] .cell.editing .tbw-editor-host .mat-mdc-select-trigger {
|
|
1029
|
+
height: var(--tbw-row-height);
|
|
1030
|
+
min-height: 0;
|
|
1031
|
+
padding-top: 0;
|
|
1032
|
+
padding-bottom: 0;
|
|
1033
|
+
line-height: 1;
|
|
1034
|
+
}
|
|
1035
|
+
|
|
1036
|
+
/* Thin header — for grids that are sub-sections inside a larger page
|
|
1037
|
+
(e.g. a field-split table) where a full-height header competes
|
|
1038
|
+
visually with surrounding form headings.
|
|
1039
|
+
|
|
1040
|
+
Apply with: <div class="tbw-thin-header"><tbw-grid ... /></div> */
|
|
1041
|
+
.tbw-thin-header tbw-grid,
|
|
1042
|
+
.tbw-thin-header [data-tbw-grid] {
|
|
1043
|
+
--tbw-header-height: 28px;
|
|
1044
|
+
--tbw-font-weight-header: 500;
|
|
1045
|
+
--tbw-font-size-header: 0.75rem;
|
|
1046
|
+
}
|
|
1047
|
+
|
|
1048
|
+
/* ================================================================
|
|
1049
|
+
* 10. Dark Mode
|
|
535
1050
|
* ================================================================ */
|
|
536
1051
|
body.sto-dark-theme tbw-grid,
|
|
1052
|
+
body.sto-dark-theme [data-tbw-grid],
|
|
537
1053
|
body.sto-dark-theme .tbw-filter-panel,
|
|
538
1054
|
body.sto-dark-theme .tbw-context-menu,
|
|
539
1055
|
body.sto-dark-theme .tbw-overlay-panel {
|