@coldsmirk/ledger-mantine 0.1.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 +49 -0
- package/dist/index.cjs +7338 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +1189 -0
- package/dist/index.d.ts +1189 -0
- package/dist/index.js +7295 -0
- package/dist/index.js.map +1 -0
- package/dist/labels-ChBqD1II.d.cts +107 -0
- package/dist/labels-ChBqD1II.d.ts +107 -0
- package/dist/locales.cjs +55 -0
- package/dist/locales.cjs.map +1 -0
- package/dist/locales.d.cts +7 -0
- package/dist/locales.d.ts +7 -0
- package/dist/locales.js +54 -0
- package/dist/locales.js.map +1 -0
- package/dist/styles.css +904 -0
- package/package.json +95 -0
package/dist/styles.css
ADDED
|
@@ -0,0 +1,904 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* @coldsmirk/ledger-mantine — layered stylesheet.
|
|
3
|
+
*
|
|
4
|
+
* Contract (docs/styling.md):
|
|
5
|
+
* - every class is kebab-case under the `ledger-` prefix, mapped 1:1 from a camelCase
|
|
6
|
+
* Styles API selector (root -> .ledger-root, headerCell -> .ledger-header-cell);
|
|
7
|
+
* - state is expressed through data-attributes (data-selected, data-pinned="start"),
|
|
8
|
+
* never through state classes;
|
|
9
|
+
* - custom properties use the `--ledger-*` prefix;
|
|
10
|
+
* - colors and metrics consume Mantine CSS variables only, so dark mode and RTL follow
|
|
11
|
+
* the host theme with no rules of our own.
|
|
12
|
+
* Everything lives in the `ledger` layer; cross-library layer order is the app's call.
|
|
13
|
+
*/
|
|
14
|
+
|
|
15
|
+
@layer ledger {
|
|
16
|
+
/* ------------------------------------------------------------------------------------------
|
|
17
|
+
* Adaptive sizing (docs/sizing.md): the root fills whatever the parent gives it and
|
|
18
|
+
* degrades to content height when the parent is indefinite. min-width/min-height: 0
|
|
19
|
+
* pre-defuse the flex/grid min-size:auto shrink trap; overflow only ever appears on the
|
|
20
|
+
* internal scroller.
|
|
21
|
+
* ------------------------------------------------------------------------------------------ */
|
|
22
|
+
.ledger-root {
|
|
23
|
+
position: relative;
|
|
24
|
+
display: flex;
|
|
25
|
+
flex-direction: column;
|
|
26
|
+
width: 100%;
|
|
27
|
+
min-width: 0;
|
|
28
|
+
height: 100%;
|
|
29
|
+
min-height: 0;
|
|
30
|
+
overflow: hidden;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/* The frame around header + body — the elastic middle; carries the outer table border
|
|
34
|
+
(painted in the Borders section: three real sides + an inset overlay bottom). */
|
|
35
|
+
.ledger-main {
|
|
36
|
+
position: relative;
|
|
37
|
+
display: flex;
|
|
38
|
+
flex: 1 1 auto;
|
|
39
|
+
flex-direction: column;
|
|
40
|
+
min-width: 0;
|
|
41
|
+
min-height: 0;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/* The header viewport never scrolls by itself; its scrollLeft mirrors the body scroller. */
|
|
45
|
+
.ledger-header {
|
|
46
|
+
flex: none;
|
|
47
|
+
overflow: hidden;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
/* The one elastic region — the Mantine ScrollArea hosting the body table. Its bottom seam
|
|
51
|
+
line is an inset overlay (Borders section), so it needs a positioning context. */
|
|
52
|
+
.ledger-scroller {
|
|
53
|
+
position: relative;
|
|
54
|
+
flex: 1 1 auto;
|
|
55
|
+
min-height: 0;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
/* An empty (or errored-out) body has no rows to give the region height — keep a readable
|
|
59
|
+
floor under indefinite parents; the overlaid state block itself adds none. */
|
|
60
|
+
.ledger-root[data-empty] .ledger-scroller,
|
|
61
|
+
.ledger-root[data-error] .ledger-scroller {
|
|
62
|
+
min-height: 16rem;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
/* Scrollbars (the ScrollArea children carrying data-orientation) are transient chrome and
|
|
66
|
+
float ABOVE pinned cells/rows (z-index 2), matching native overlay scrollbars and EP
|
|
67
|
+
(fixed columns +1, scrollbar bar +2). Mantine gives them no z-index of their own, so a
|
|
68
|
+
covered track stretch would be unreachable — the pinned cell intercepts the pointer — and
|
|
69
|
+
the thumb would vanish under a pinned column exactly at the scroll extremes. */
|
|
70
|
+
.ledger-scroller > [data-orientation] {
|
|
71
|
+
z-index: 3;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
/* With the active row enabled the body viewport is a keyboard focus stop — show it. */
|
|
75
|
+
.ledger-scroller > [tabindex="0"]:focus-visible {
|
|
76
|
+
outline: 2px solid var(--mantine-primary-color-filled);
|
|
77
|
+
outline-offset: -2px;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
/* The footer viewport (totals): always visible below the scroller, scrollLeft-mirrored.
|
|
81
|
+
Its separators live in the Borders section — the top seam belongs to the scroller. */
|
|
82
|
+
.ledger-footer {
|
|
83
|
+
flex: none;
|
|
84
|
+
overflow: hidden;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
.ledger-table {
|
|
88
|
+
width: 100%;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
/* ------------------------------------------------------------------------------------------
|
|
92
|
+
* Header: rendered outside the body scroller (never occludes its scrollbar, never bounces
|
|
93
|
+
* with overscroll); cells only stick horizontally when pinned. Actions reveal on hover/focus.
|
|
94
|
+
* ------------------------------------------------------------------------------------------ */
|
|
95
|
+
.ledger-header-cell {
|
|
96
|
+
position: relative;
|
|
97
|
+
vertical-align: middle;
|
|
98
|
+
background-color: var(--ledger-header-bg, var(--mantine-color-body));
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
.ledger-header-cell[data-pinned] {
|
|
102
|
+
position: sticky;
|
|
103
|
+
z-index: 2;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
.ledger-header-cell[data-align="center"],
|
|
107
|
+
.ledger-cell[data-align="center"],
|
|
108
|
+
.ledger-footer-cell[data-align="center"] {
|
|
109
|
+
text-align: center;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
.ledger-header-cell[data-align="end"],
|
|
113
|
+
.ledger-cell[data-align="end"],
|
|
114
|
+
.ledger-footer-cell[data-align="end"] {
|
|
115
|
+
text-align: end;
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
.ledger-header-label {
|
|
119
|
+
display: inline-flex;
|
|
120
|
+
gap: 6px;
|
|
121
|
+
align-items: center;
|
|
122
|
+
max-width: 100%;
|
|
123
|
+
font: inherit;
|
|
124
|
+
color: inherit;
|
|
125
|
+
text-align: inherit;
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
/* The sort control is a NATIVE button (matched via its type attribute) reset here: layered
|
|
129
|
+
author rules always beat UA button styles, whereas Mantine's UnstyledButton carries an
|
|
130
|
+
unlayered font-size that would defeat the layered `font: inherit` above (the unlayered-host
|
|
131
|
+
rule, docs/styling.md). */
|
|
132
|
+
.ledger-header-label[type="button"] {
|
|
133
|
+
padding: 0;
|
|
134
|
+
appearance: none;
|
|
135
|
+
cursor: pointer;
|
|
136
|
+
background: none;
|
|
137
|
+
border: 0;
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
.ledger-header-label[data-align="center"] {
|
|
141
|
+
justify-content: center;
|
|
142
|
+
width: 100%;
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
.ledger-header-label[data-align="end"] {
|
|
146
|
+
justify-content: flex-end;
|
|
147
|
+
width: 100%;
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
.ledger-header-label:focus-visible {
|
|
151
|
+
outline: 2px solid var(--mantine-primary-color-filled);
|
|
152
|
+
outline-offset: -2px;
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
.ledger-header-label [data-truncate],
|
|
156
|
+
.ledger-cell [data-truncate] {
|
|
157
|
+
display: block;
|
|
158
|
+
min-width: 0;
|
|
159
|
+
overflow: hidden;
|
|
160
|
+
text-overflow: ellipsis;
|
|
161
|
+
white-space: nowrap;
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
/* Sort affordance: invisible until hover on unsorted columns, always visible once sorted. */
|
|
165
|
+
.ledger-sort-indicator {
|
|
166
|
+
display: inline-flex;
|
|
167
|
+
align-items: center;
|
|
168
|
+
color: var(--mantine-color-dimmed);
|
|
169
|
+
opacity: 0;
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
.ledger-header-cell:hover .ledger-sort-indicator,
|
|
173
|
+
.ledger-header-label:focus-visible .ledger-sort-indicator {
|
|
174
|
+
opacity: 0.6;
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
.ledger-sort-indicator[data-sorted] {
|
|
178
|
+
color: inherit;
|
|
179
|
+
opacity: 1;
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
.ledger-sort-indicator sup {
|
|
183
|
+
font-size: 0.7em;
|
|
184
|
+
font-weight: 600;
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
/* Actions overlay the trailing edge of the header cell and reveal on interaction. */
|
|
188
|
+
.ledger-header-actions {
|
|
189
|
+
position: absolute;
|
|
190
|
+
inset-inline-end: 4px;
|
|
191
|
+
top: 50%;
|
|
192
|
+
display: flex;
|
|
193
|
+
gap: 2px;
|
|
194
|
+
align-items: center;
|
|
195
|
+
padding-inline-start: 4px;
|
|
196
|
+
background-color: inherit;
|
|
197
|
+
opacity: 0;
|
|
198
|
+
translate: 0 -50%;
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
.ledger-header-actions:has([data-active]),
|
|
202
|
+
.ledger-header-actions:has([aria-expanded="true"]),
|
|
203
|
+
.ledger-header-cell:hover .ledger-header-actions,
|
|
204
|
+
.ledger-header-cell:focus-within .ledger-header-actions {
|
|
205
|
+
opacity: 1;
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
/* The resizer owns the cell's trailing strip (8px, z-index above the actions), so actions
|
|
209
|
+
clear out of it entirely: without this the filter button's outer pixels LOOK clickable but
|
|
210
|
+
hit the invisible resizer, and the button crowds within 1px of the drag line. */
|
|
211
|
+
.ledger-header-cell:has(.ledger-resizer) .ledger-header-actions {
|
|
212
|
+
inset-inline-end: 12px;
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
/* Resize handle on the trailing edge; the visible line appears on hover or while dragging. */
|
|
216
|
+
.ledger-resizer {
|
|
217
|
+
position: absolute;
|
|
218
|
+
inset-inline-end: 0;
|
|
219
|
+
top: 0;
|
|
220
|
+
z-index: 1;
|
|
221
|
+
width: 8px;
|
|
222
|
+
height: 100%;
|
|
223
|
+
touch-action: none;
|
|
224
|
+
cursor: col-resize;
|
|
225
|
+
user-select: none;
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
.ledger-resizer::after {
|
|
229
|
+
position: absolute;
|
|
230
|
+
inset-block: 15%;
|
|
231
|
+
inset-inline-end: 3px;
|
|
232
|
+
width: 2px;
|
|
233
|
+
content: "";
|
|
234
|
+
background-color: transparent;
|
|
235
|
+
border-radius: 1px;
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
/* Resting tick, only where the handle would otherwise be invisible: a borderless table marks
|
|
239
|
+
each resizable boundary with a faint mid-height line (precedent: MUI DataGrid's header
|
|
240
|
+
separators), so finding the handle takes no guessing. Column borders already say where
|
|
241
|
+
columns end, so bordered tables skip it; hover and drag swap in the taller primary line
|
|
242
|
+
either way — a two-step tell, like the Tooltip's delay. */
|
|
243
|
+
:where(.ledger-root:not([data-with-column-borders])) .ledger-resizer::after {
|
|
244
|
+
inset-block: 30%;
|
|
245
|
+
background-color: var(--mantine-color-default-border);
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
.ledger-resizer:hover::after,
|
|
249
|
+
.ledger-resizer[data-resizing]::after {
|
|
250
|
+
inset-block: 15%;
|
|
251
|
+
background-color: var(--mantine-primary-color-filled);
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
/* Drag-reorder feedback. */
|
|
255
|
+
.ledger-header-cell[data-dragging] {
|
|
256
|
+
opacity: 0.4;
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
.ledger-header-cell[data-drop-side]::before {
|
|
260
|
+
position: absolute;
|
|
261
|
+
inset-block: 0;
|
|
262
|
+
z-index: 3;
|
|
263
|
+
width: 2px;
|
|
264
|
+
content: "";
|
|
265
|
+
background-color: var(--mantine-primary-color-filled);
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
.ledger-header-cell[data-drop-side="before"]::before {
|
|
269
|
+
inset-inline-start: 0;
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
.ledger-header-cell[data-drop-side="after"]::before {
|
|
273
|
+
inset-inline-end: 0;
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
/* ------------------------------------------------------------------------------------------
|
|
277
|
+
* Rows: every background flows through --ledger-row-bg, and pinned cells reference the same
|
|
278
|
+
* pipeline — a pinned column that fails to cover stripes/hover is unrepresentable.
|
|
279
|
+
* The paint site is the CELL, never the <tr>: Mantine ships an unlayered
|
|
280
|
+
* `tr { background-color: transparent }`, and unlayered author styles defeat any layered
|
|
281
|
+
* row-level paint regardless of specificity.
|
|
282
|
+
* Ancestry and extra state in these selectors is wrapped in :where() so every rule stays at
|
|
283
|
+
* (0,2,0) — SOURCE ORDER alone is the precedence ladder: stripes < hover < selected/active <
|
|
284
|
+
* their hover step < the cursor inside a selection < pinned < the editing row (below).
|
|
285
|
+
* ------------------------------------------------------------------------------------------ */
|
|
286
|
+
.ledger-row {
|
|
287
|
+
--ledger-pinned-bg: var(--ledger-row-bg, var(--mantine-color-body));
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
.ledger-row > td {
|
|
291
|
+
background-color: var(--ledger-row-bg, transparent);
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
:where(.ledger-root[data-striped="odd"] .ledger-tbody) .ledger-row[data-parity="odd"],
|
|
295
|
+
:where(.ledger-root[data-striped="even"] .ledger-tbody) .ledger-row[data-parity="even"] {
|
|
296
|
+
--ledger-row-bg: var(--ledger-striped-color, var(--mantine-color-default-hover));
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
:where(.ledger-root[data-highlight-on-hover] .ledger-tbody) .ledger-row:hover {
|
|
300
|
+
--ledger-row-bg: var(--ledger-hover-color, var(--mantine-color-default-hover));
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
/* Selection and the active (keyboard-cursor) row rest at Mantine's calm light step; hovering
|
|
304
|
+
either takes the light-hover step — hover deepens a state, it never replaces it. */
|
|
305
|
+
.ledger-row[data-selected] {
|
|
306
|
+
--ledger-row-bg: var(--mantine-primary-color-light);
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
.ledger-row[data-active] {
|
|
310
|
+
--ledger-row-bg: var(--mantine-primary-color-light);
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
:where(.ledger-root[data-highlight-on-hover] .ledger-tbody) .ledger-row:where([data-selected], [data-active]):hover {
|
|
314
|
+
--ledger-row-bg: var(--mantine-primary-color-light-hover);
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
/* The cursor inside a selected block rests one step deeper — exactly one row is ever current,
|
|
318
|
+
and it has to stay findable there without an accent bar. */
|
|
319
|
+
.ledger-row[data-active]:where([data-selected]) {
|
|
320
|
+
--ledger-row-bg: var(--mantine-primary-color-light-hover);
|
|
321
|
+
}
|
|
322
|
+
|
|
323
|
+
.ledger-row[data-clickable] {
|
|
324
|
+
cursor: pointer;
|
|
325
|
+
}
|
|
326
|
+
|
|
327
|
+
/* Sticky pinned rows sit at the body scroller's edges, above the flow (the header lives
|
|
328
|
+
outside the scroller, so top offsets start at 0). */
|
|
329
|
+
.ledger-row[data-pinned-row] {
|
|
330
|
+
--ledger-row-bg: var(--mantine-color-body);
|
|
331
|
+
position: sticky;
|
|
332
|
+
z-index: 2;
|
|
333
|
+
}
|
|
334
|
+
|
|
335
|
+
.ledger-row[data-pinned-row="top"] {
|
|
336
|
+
top: 0;
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
.ledger-row[data-pinned-row="bottom"] {
|
|
340
|
+
bottom: 0;
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
/* Virtualization spacers carry geometry only — no borders, no background. */
|
|
344
|
+
.ledger-table tr[data-ledger-spacer] {
|
|
345
|
+
background: none;
|
|
346
|
+
border: 0;
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
/* ------------------------------------------------------------------------------------------
|
|
350
|
+
* Cells
|
|
351
|
+
* ------------------------------------------------------------------------------------------ */
|
|
352
|
+
.ledger-cell[data-pinned],
|
|
353
|
+
.ledger-selection-cell[data-pinned],
|
|
354
|
+
.ledger-expander-cell[data-pinned],
|
|
355
|
+
.ledger-row-drag-cell[data-pinned],
|
|
356
|
+
.ledger-footer-cell[data-pinned] {
|
|
357
|
+
position: sticky;
|
|
358
|
+
z-index: 2;
|
|
359
|
+
background-color: var(--ledger-pinned-bg, var(--mantine-color-body));
|
|
360
|
+
}
|
|
361
|
+
|
|
362
|
+
/* Pinned-edge scroll shadows, visible only while content is actually scrolled past. */
|
|
363
|
+
[data-pinned-edge]::after {
|
|
364
|
+
position: absolute;
|
|
365
|
+
inset-block: 0;
|
|
366
|
+
width: 8px;
|
|
367
|
+
pointer-events: none;
|
|
368
|
+
content: "";
|
|
369
|
+
opacity: 0;
|
|
370
|
+
}
|
|
371
|
+
|
|
372
|
+
[data-pinned-edge="start"]::after {
|
|
373
|
+
inset-inline-end: 0;
|
|
374
|
+
background: linear-gradient(to right, rgb(0 0 0 / 10%), transparent);
|
|
375
|
+
translate: 100% 0;
|
|
376
|
+
}
|
|
377
|
+
|
|
378
|
+
[data-pinned-edge="end"]::after {
|
|
379
|
+
inset-inline-start: 0;
|
|
380
|
+
background: linear-gradient(to left, rgb(0 0 0 / 10%), transparent);
|
|
381
|
+
translate: -100% 0;
|
|
382
|
+
}
|
|
383
|
+
|
|
384
|
+
[dir="rtl"] [data-pinned-edge="start"]::after {
|
|
385
|
+
background: linear-gradient(to left, rgb(0 0 0 / 10%), transparent);
|
|
386
|
+
translate: -100% 0;
|
|
387
|
+
}
|
|
388
|
+
|
|
389
|
+
[dir="rtl"] [data-pinned-edge="end"]::after {
|
|
390
|
+
background: linear-gradient(to right, rgb(0 0 0 / 10%), transparent);
|
|
391
|
+
translate: 100% 0;
|
|
392
|
+
}
|
|
393
|
+
|
|
394
|
+
.ledger-root[data-scrolled-start] [data-pinned-edge="start"]::after,
|
|
395
|
+
.ledger-root[data-scrolled-end] [data-pinned-edge="end"]::after {
|
|
396
|
+
opacity: 1;
|
|
397
|
+
}
|
|
398
|
+
|
|
399
|
+
.ledger-selection-cell,
|
|
400
|
+
.ledger-expander-cell,
|
|
401
|
+
.ledger-row-drag-cell {
|
|
402
|
+
vertical-align: middle;
|
|
403
|
+
text-align: center;
|
|
404
|
+
}
|
|
405
|
+
|
|
406
|
+
/* The reorder handle: grab affordance while live, quiet dim while something else controls
|
|
407
|
+
the order (the tooltip says what — labels.rowOrderingUnavailable). */
|
|
408
|
+
.ledger-row-drag-cell button {
|
|
409
|
+
vertical-align: middle;
|
|
410
|
+
cursor: grab;
|
|
411
|
+
}
|
|
412
|
+
|
|
413
|
+
.ledger-row-drag-cell button[aria-disabled] {
|
|
414
|
+
cursor: default;
|
|
415
|
+
opacity: 0.4;
|
|
416
|
+
}
|
|
417
|
+
|
|
418
|
+
/* An icon-only ActionIcon is an inline-flex box whose baseline is its bottom edge, so the
|
|
419
|
+
default `vertical-align: baseline` rides it a few pixels high of the middle-aligned cell's
|
|
420
|
+
center — the row chevron and the tree header's expand-all both need pinning to the middle. */
|
|
421
|
+
.ledger-expander-cell button,
|
|
422
|
+
.ledger-header-cell[data-ledger-column-id="ledger:expander"] button {
|
|
423
|
+
vertical-align: middle;
|
|
424
|
+
}
|
|
425
|
+
|
|
426
|
+
/* Expander chevrons rotate open (rows, groups, expand-all). */
|
|
427
|
+
.ledger-expander-cell button svg,
|
|
428
|
+
[data-group-cell] button svg,
|
|
429
|
+
.ledger-header-cell button[data-expanded] svg,
|
|
430
|
+
.ledger-expander-cell button[data-expanded] svg {
|
|
431
|
+
transition: rotate 150ms ease;
|
|
432
|
+
}
|
|
433
|
+
|
|
434
|
+
.ledger-expander-cell button[data-expanded] svg,
|
|
435
|
+
[data-group-cell] button[data-expanded] svg,
|
|
436
|
+
.ledger-header-cell button[data-expanded] svg {
|
|
437
|
+
rotate: 90deg;
|
|
438
|
+
}
|
|
439
|
+
|
|
440
|
+
[data-group-cell] {
|
|
441
|
+
display: inline-flex;
|
|
442
|
+
gap: 6px;
|
|
443
|
+
align-items: center;
|
|
444
|
+
font-weight: 500;
|
|
445
|
+
}
|
|
446
|
+
|
|
447
|
+
[data-group-count] {
|
|
448
|
+
font-size: var(--mantine-font-size-xs);
|
|
449
|
+
color: var(--mantine-color-dimmed);
|
|
450
|
+
}
|
|
451
|
+
|
|
452
|
+
.ledger-cell[data-editing] {
|
|
453
|
+
padding-block: 2px;
|
|
454
|
+
}
|
|
455
|
+
|
|
456
|
+
.ledger-cell-editor {
|
|
457
|
+
display: flex;
|
|
458
|
+
gap: 4px;
|
|
459
|
+
align-items: center;
|
|
460
|
+
width: 100%;
|
|
461
|
+
}
|
|
462
|
+
|
|
463
|
+
.ledger-cell-editor[data-pending] {
|
|
464
|
+
opacity: 0.7;
|
|
465
|
+
}
|
|
466
|
+
|
|
467
|
+
/* Instant columns: the live control keeps its place while its write is out — the pending
|
|
468
|
+
spinner hangs off the host, outside the flow the cell centers. */
|
|
469
|
+
.ledger-instant-cell {
|
|
470
|
+
position: relative;
|
|
471
|
+
display: inline-flex;
|
|
472
|
+
gap: 4px;
|
|
473
|
+
align-items: center;
|
|
474
|
+
vertical-align: middle;
|
|
475
|
+
}
|
|
476
|
+
|
|
477
|
+
.ledger-instant-spinner {
|
|
478
|
+
position: absolute;
|
|
479
|
+
inset-block-start: 50%;
|
|
480
|
+
inset-inline-start: calc(100% + 6px);
|
|
481
|
+
transform: translateY(-50%);
|
|
482
|
+
}
|
|
483
|
+
|
|
484
|
+
/* Row-mode editing: the whole row reads as one open form — a quiet primary wash plus a
|
|
485
|
+
hairline above and below drawn by the cells, so pinned cells carry the frame too. */
|
|
486
|
+
.ledger-row[data-editing-row] {
|
|
487
|
+
--ledger-row-bg: var(--mantine-primary-color-light);
|
|
488
|
+
}
|
|
489
|
+
|
|
490
|
+
.ledger-row[data-editing-row] > * {
|
|
491
|
+
box-shadow:
|
|
492
|
+
inset 0 1px 0 0 var(--mantine-primary-color-filled),
|
|
493
|
+
inset 0 -1px 0 0 var(--mantine-primary-color-filled);
|
|
494
|
+
}
|
|
495
|
+
|
|
496
|
+
/* Row reordering (docs/rows.md#row-ordering): the lifted row dims in place, and the target
|
|
497
|
+
row draws the drop edge — on its cells, so pinned cells carry the line too. */
|
|
498
|
+
.ledger-row[data-dragging] {
|
|
499
|
+
opacity: 0.4;
|
|
500
|
+
}
|
|
501
|
+
|
|
502
|
+
.ledger-row[data-drop-side="before"] > * {
|
|
503
|
+
box-shadow: inset 0 2px 0 0 var(--mantine-primary-color-filled);
|
|
504
|
+
}
|
|
505
|
+
|
|
506
|
+
.ledger-row[data-drop-side="after"] > * {
|
|
507
|
+
box-shadow: inset 0 -2px 0 0 var(--mantine-primary-color-filled);
|
|
508
|
+
}
|
|
509
|
+
|
|
510
|
+
/* The pointer ghost: a snapshot of the whole lifted row (row-reorder.tsx clones it under
|
|
511
|
+
per-column pixel widths), positioned imperatively and portaled to the body — never part
|
|
512
|
+
of the table's flow. */
|
|
513
|
+
.ledger-row-drag-overlay {
|
|
514
|
+
position: fixed;
|
|
515
|
+
inset-block-start: 0;
|
|
516
|
+
inset-inline-start: 0;
|
|
517
|
+
z-index: var(--mantine-z-index-popover);
|
|
518
|
+
overflow: hidden;
|
|
519
|
+
pointer-events: none;
|
|
520
|
+
background-color: var(--mantine-color-body);
|
|
521
|
+
border: 1px solid var(--mantine-color-default-border);
|
|
522
|
+
border-radius: var(--mantine-radius-default);
|
|
523
|
+
box-shadow: var(--mantine-shadow-md);
|
|
524
|
+
}
|
|
525
|
+
|
|
526
|
+
/* ------------------------------------------------------------------------------------------
|
|
527
|
+
* Detail panels, footer, states, chrome
|
|
528
|
+
* ------------------------------------------------------------------------------------------ */
|
|
529
|
+
.ledger-detail-panel {
|
|
530
|
+
padding: var(--mantine-spacing-sm) var(--mantine-spacing-md);
|
|
531
|
+
}
|
|
532
|
+
|
|
533
|
+
.ledger-footer-cell {
|
|
534
|
+
font-weight: 600;
|
|
535
|
+
background-color: var(--mantine-color-body);
|
|
536
|
+
}
|
|
537
|
+
|
|
538
|
+
/* Overlaid on the whole body region (the scroller is its positioning context): centered in
|
|
539
|
+
the VISIBLE area, and immune to horizontal scrolling of the empty table underneath.
|
|
540
|
+
The EmptyState variables soften Mantine's stock indicator (gray-1 disc, dimmed icon) —
|
|
541
|
+
inside a bare table body it reads heavy; both substitutes are color-scheme-adaptive. */
|
|
542
|
+
.ledger-empty {
|
|
543
|
+
--empty-state-indicator-bg: var(--mantine-color-default-hover);
|
|
544
|
+
--empty-state-indicator-color: var(--mantine-color-placeholder);
|
|
545
|
+
position: absolute;
|
|
546
|
+
inset: 0;
|
|
547
|
+
display: flex;
|
|
548
|
+
align-items: center;
|
|
549
|
+
justify-content: center;
|
|
550
|
+
padding: var(--mantine-spacing-xl) var(--mantine-spacing-md);
|
|
551
|
+
}
|
|
552
|
+
|
|
553
|
+
/* The error panel keeps the quiet disc but tints it with the light error pair, both
|
|
554
|
+
color-scheme-adaptive. */
|
|
555
|
+
.ledger-empty[data-variant="error"] {
|
|
556
|
+
--empty-state-indicator-bg: var(--mantine-color-red-light);
|
|
557
|
+
--empty-state-indicator-color: var(--mantine-color-red-light-color);
|
|
558
|
+
}
|
|
559
|
+
|
|
560
|
+
/* Error over stale rows: a body-tinted scrim. Weighted for the message, not the rows — the
|
|
561
|
+
panel's own text sits on top of them, so the scrim has to win that contrast outright; the
|
|
562
|
+
rows survive as a ghost that says "still here, not current". */
|
|
563
|
+
.ledger-empty[data-over-rows] {
|
|
564
|
+
z-index: 2;
|
|
565
|
+
background-color: color-mix(in srgb, var(--mantine-color-body) 92%, transparent);
|
|
566
|
+
}
|
|
567
|
+
|
|
568
|
+
.ledger-loader-row td {
|
|
569
|
+
padding-block: var(--mantine-spacing-sm);
|
|
570
|
+
color: var(--mantine-color-dimmed);
|
|
571
|
+
border-bottom: 0;
|
|
572
|
+
}
|
|
573
|
+
|
|
574
|
+
/* The cell holds a centred pair — spinner + text, or message + retry — so it is laid out as
|
|
575
|
+
one flex line rather than as inline boxes. Inline layout aligns them on the BASELINE, which
|
|
576
|
+
leaves a text run and a button a pixel or two apart and drifts further whenever either
|
|
577
|
+
changes height (adding the retry icon moved it again). The cell itself cannot be the flex
|
|
578
|
+
container: that would strip the `<td>` of its table-cell box and with it the colSpan that
|
|
579
|
+
makes this row span the table. */
|
|
580
|
+
.ledger-loader-row-content {
|
|
581
|
+
display: flex;
|
|
582
|
+
gap: 8px;
|
|
583
|
+
align-items: center;
|
|
584
|
+
justify-content: center;
|
|
585
|
+
font-size: var(--mantine-font-size-sm);
|
|
586
|
+
}
|
|
587
|
+
|
|
588
|
+
/* The retry button carries its own horizontal padding, so the pair needs less between them. */
|
|
589
|
+
.ledger-loader-row[data-error] .ledger-loader-row-content {
|
|
590
|
+
gap: 4px;
|
|
591
|
+
}
|
|
592
|
+
|
|
593
|
+
.ledger-pagination-bar {
|
|
594
|
+
flex: none;
|
|
595
|
+
}
|
|
596
|
+
|
|
597
|
+
.ledger-root > .ledger-pagination-bar {
|
|
598
|
+
padding: var(--mantine-spacing-xs) var(--mantine-spacing-sm);
|
|
599
|
+
border-block-start: 1px solid var(--mantine-color-default-border);
|
|
600
|
+
}
|
|
601
|
+
|
|
602
|
+
/* The seam above the bar is owned by the table's own bottom edge (frame overlay, footer
|
|
603
|
+
trailing border, or scroller seam — Borders section); the bar draws its own line only in
|
|
604
|
+
the fully borderless look, where no other edge exists. */
|
|
605
|
+
.ledger-root[data-with-row-borders] > .ledger-pagination-bar,
|
|
606
|
+
.ledger-root[data-with-table-border] > .ledger-pagination-bar {
|
|
607
|
+
border-block-start: 0;
|
|
608
|
+
}
|
|
609
|
+
|
|
610
|
+
.ledger-selection-bar {
|
|
611
|
+
padding: var(--mantine-spacing-xs) 0;
|
|
612
|
+
}
|
|
613
|
+
|
|
614
|
+
/* The columns panel (docs/columns.md) is bare content whose host owns its box: it fills a
|
|
615
|
+
definite one (a drawer) and degrades to content height in an indefinite one (a popover) —
|
|
616
|
+
the same adaptive contract the table root follows. The list is the only elastic region, so
|
|
617
|
+
a long column set scrolls inside the panel instead of overflowing it.
|
|
618
|
+
|
|
619
|
+
Presentation contract: at rest a row is identity — checkbox and name — plus dimmed marks
|
|
620
|
+
where the layout deviates from default (captions over pinned zones, an overridden width, a
|
|
621
|
+
grouped column, a dimmed hidden name). The machinery — handle, width field, pin segment,
|
|
622
|
+
group toggle — reveals on the hovered or keyboard-focused row as an overlaid toolbar, so
|
|
623
|
+
resting names keep the full row width. Where hover does not exist the toolbar sits inline
|
|
624
|
+
(the hover-none block after the base panel rules). */
|
|
625
|
+
.ledger-columns-panel {
|
|
626
|
+
display: flex;
|
|
627
|
+
flex-direction: column;
|
|
628
|
+
width: 100%;
|
|
629
|
+
min-width: 280px;
|
|
630
|
+
max-height: 100%;
|
|
631
|
+
padding: var(--mantine-spacing-xs);
|
|
632
|
+
}
|
|
633
|
+
|
|
634
|
+
/* No inline padding: the title and the reset button align to the zone slabs' edges below,
|
|
635
|
+
which are the panel's visual frame — the rows' own 8px inset is interior to that frame. */
|
|
636
|
+
|
|
637
|
+
/* The gap under the hairline repeats the panel's own padding token, so the content block
|
|
638
|
+
sits at the same distance from all four of its frame edges. */
|
|
639
|
+
.ledger-columns-panel-header {
|
|
640
|
+
padding: 4px 0 10px;
|
|
641
|
+
margin-block-end: var(--mantine-spacing-xs);
|
|
642
|
+
border-block-end: 1px solid var(--mantine-color-default-border);
|
|
643
|
+
}
|
|
644
|
+
|
|
645
|
+
.ledger-columns-panel-list {
|
|
646
|
+
display: flex;
|
|
647
|
+
flex: 1;
|
|
648
|
+
flex-direction: column;
|
|
649
|
+
min-height: 0;
|
|
650
|
+
overflow-y: auto;
|
|
651
|
+
}
|
|
652
|
+
|
|
653
|
+
.ledger-columns-panel-zone {
|
|
654
|
+
display: flex;
|
|
655
|
+
flex-direction: column;
|
|
656
|
+
gap: 2px;
|
|
657
|
+
}
|
|
658
|
+
|
|
659
|
+
/* Pinned zones are shelves: the tinted slab marks the drag boundary (a column sorts only
|
|
660
|
+
among its own kind) the way the pinned columns' own opaque background marks them in the
|
|
661
|
+
table. Nothing pinned means one flat list and zero chrome. Block padding only — inline
|
|
662
|
+
padding would shift the rows' handle/checkbox/name columns off the center zone's. */
|
|
663
|
+
.ledger-columns-panel-zone[data-pinned] {
|
|
664
|
+
padding-block: 4px;
|
|
665
|
+
background-color: var(--mantine-color-gray-light);
|
|
666
|
+
border-radius: var(--mantine-radius-default);
|
|
667
|
+
}
|
|
668
|
+
|
|
669
|
+
.ledger-columns-panel-zone + .ledger-columns-panel-zone {
|
|
670
|
+
margin-block-start: 8px;
|
|
671
|
+
}
|
|
672
|
+
|
|
673
|
+
/* The caption pairs the zone's pin glyph with its name, tying the shelf to the same vocabulary
|
|
674
|
+
the row's pin segments speak. It is a ledger-owned div (Mantine's unlayered Text reset would
|
|
675
|
+
zero a padding set here), so its type and color live here too; line-height 1 collapses the
|
|
676
|
+
text's line box onto the glyph's 12px so flex centering aligns their midlines exactly. */
|
|
677
|
+
.ledger-columns-panel-zone-label {
|
|
678
|
+
display: flex;
|
|
679
|
+
gap: 4px;
|
|
680
|
+
align-items: center;
|
|
681
|
+
padding: 4px 8px;
|
|
682
|
+
font-size: var(--mantine-font-size-xs);
|
|
683
|
+
font-weight: 500;
|
|
684
|
+
line-height: 1;
|
|
685
|
+
color: var(--mantine-color-dimmed);
|
|
686
|
+
}
|
|
687
|
+
|
|
688
|
+
/* Radii across the panel — the tinted shelves, this hover pill, and the toolbar backdrop —
|
|
689
|
+
follow the theme's default radius, the same token the toolbar's Mantine controls resolve
|
|
690
|
+
with no radius prop, so the whole cluster rounds as one under any host theme. */
|
|
691
|
+
.ledger-columns-panel-item {
|
|
692
|
+
position: relative;
|
|
693
|
+
min-height: 36px;
|
|
694
|
+
padding: 2px 8px;
|
|
695
|
+
border-radius: var(--mantine-radius-default);
|
|
696
|
+
}
|
|
697
|
+
|
|
698
|
+
/* focus-within matches :hover because the toolbar below reveals on both. */
|
|
699
|
+
.ledger-columns-panel-item:hover,
|
|
700
|
+
.ledger-columns-panel-item:focus-within {
|
|
701
|
+
background-color: var(--mantine-color-default-hover);
|
|
702
|
+
}
|
|
703
|
+
|
|
704
|
+
/* The row keeps its seat, greyed, while dnd-kit's clone follows the pointer. */
|
|
705
|
+
.ledger-columns-panel-item[data-dragging] {
|
|
706
|
+
opacity: 0.4;
|
|
707
|
+
}
|
|
708
|
+
|
|
709
|
+
/* A translucent grip is enough of a "this list reorders" hint; the hovered row sharpens it. */
|
|
710
|
+
.ledger-columns-panel-handle {
|
|
711
|
+
cursor: grab;
|
|
712
|
+
opacity: 0.3;
|
|
713
|
+
transition: opacity 120ms ease;
|
|
714
|
+
}
|
|
715
|
+
|
|
716
|
+
.ledger-columns-panel-item:hover .ledger-columns-panel-handle,
|
|
717
|
+
.ledger-columns-panel-item:focus-within .ledger-columns-panel-handle {
|
|
718
|
+
opacity: 1;
|
|
719
|
+
}
|
|
720
|
+
|
|
721
|
+
.ledger-columns-panel-item[data-dragging] .ledger-columns-panel-handle {
|
|
722
|
+
cursor: grabbing;
|
|
723
|
+
}
|
|
724
|
+
|
|
725
|
+
/* The checkbox's label wrapper. Mantine already clears min-width on the body between them, so
|
|
726
|
+
this is the last link in the chain that must be allowed to shrink; without it the nowrap
|
|
727
|
+
title below sets an unshrinkable floor and shoves the rest of the row out of alignment. */
|
|
728
|
+
.ledger-columns-panel-label {
|
|
729
|
+
min-width: 0;
|
|
730
|
+
}
|
|
731
|
+
|
|
732
|
+
/* Long titles ellipse rather than wrap — a two-line row among one-line rows reads as a break
|
|
733
|
+
in the list. */
|
|
734
|
+
.ledger-columns-panel-label > label {
|
|
735
|
+
display: block;
|
|
736
|
+
overflow: hidden;
|
|
737
|
+
text-overflow: ellipsis;
|
|
738
|
+
white-space: nowrap;
|
|
739
|
+
}
|
|
740
|
+
|
|
741
|
+
/* Hidden columns stay listed — bringing them back is the point — but read as absent. The
|
|
742
|
+
color sits on OUR wrapper, not on Mantine's label: that label declares `color: inherit` in
|
|
743
|
+
a stylesheet the host may load unlayered, where it would beat anything the ledger layer
|
|
744
|
+
says — but inheritance it can only obey. */
|
|
745
|
+
.ledger-columns-panel-item[data-hidden] .ledger-columns-panel-label {
|
|
746
|
+
color: var(--mantine-color-dimmed);
|
|
747
|
+
}
|
|
748
|
+
|
|
749
|
+
.ledger-columns-panel-indicators {
|
|
750
|
+
display: flex;
|
|
751
|
+
flex: none;
|
|
752
|
+
gap: 6px;
|
|
753
|
+
align-items: center;
|
|
754
|
+
font-variant-numeric: tabular-nums;
|
|
755
|
+
color: var(--mantine-color-dimmed);
|
|
756
|
+
white-space: nowrap;
|
|
757
|
+
}
|
|
758
|
+
|
|
759
|
+
/* The revealed toolbar. Overlaid rather than inline so resting rows spend the space on the
|
|
760
|
+
name; its own backdrop matches the hovered row and fades in over the name's tail. */
|
|
761
|
+
.ledger-columns-panel-controls {
|
|
762
|
+
position: absolute;
|
|
763
|
+
inset-block: 0;
|
|
764
|
+
inset-inline-end: 0;
|
|
765
|
+
display: flex;
|
|
766
|
+
gap: 6px;
|
|
767
|
+
align-items: center;
|
|
768
|
+
padding-inline: 8px;
|
|
769
|
+
pointer-events: none;
|
|
770
|
+
background-color: var(--mantine-color-default-hover);
|
|
771
|
+
border-start-end-radius: var(--mantine-radius-default);
|
|
772
|
+
border-end-end-radius: var(--mantine-radius-default);
|
|
773
|
+
opacity: 0;
|
|
774
|
+
transition: opacity 120ms ease;
|
|
775
|
+
}
|
|
776
|
+
|
|
777
|
+
.ledger-columns-panel-controls::before {
|
|
778
|
+
position: absolute;
|
|
779
|
+
inset-block: 0;
|
|
780
|
+
inset-inline-start: -24px;
|
|
781
|
+
width: 24px;
|
|
782
|
+
content: "";
|
|
783
|
+
background: linear-gradient(to right, transparent, var(--mantine-color-default-hover));
|
|
784
|
+
}
|
|
785
|
+
|
|
786
|
+
[dir="rtl"] .ledger-columns-panel-controls::before {
|
|
787
|
+
background: linear-gradient(to left, transparent, var(--mantine-color-default-hover));
|
|
788
|
+
}
|
|
789
|
+
|
|
790
|
+
.ledger-columns-panel-item:hover .ledger-columns-panel-controls,
|
|
791
|
+
.ledger-columns-panel-item:focus-within .ledger-columns-panel-controls {
|
|
792
|
+
pointer-events: auto;
|
|
793
|
+
opacity: 1;
|
|
794
|
+
}
|
|
795
|
+
|
|
796
|
+
/* Widths are numbers the table's own cells would show right-aligned and tabular. */
|
|
797
|
+
.ledger-columns-panel-width-input {
|
|
798
|
+
font-variant-numeric: tabular-nums;
|
|
799
|
+
text-align: end;
|
|
800
|
+
}
|
|
801
|
+
|
|
802
|
+
/* ------------------------------------------------------------------------------------------
|
|
803
|
+
* Borders — ledger-owned at cell level. The host paints row borders on <tr> under
|
|
804
|
+
* border-collapse: collapse, and Chrome does not repaint collapsed borders at stuck sticky
|
|
805
|
+
* positions; our tables are border-collapse: separate (inline), so every cell carries its
|
|
806
|
+
* border wherever it sticks.
|
|
807
|
+
* ------------------------------------------------------------------------------------------ */
|
|
808
|
+
.ledger-root[data-with-row-borders] .ledger-thead th,
|
|
809
|
+
.ledger-root[data-with-row-borders] .ledger-tbody .ledger-row > td {
|
|
810
|
+
border-block-end: 1px solid var(--ledger-border-color, var(--mantine-color-default-border));
|
|
811
|
+
}
|
|
812
|
+
|
|
813
|
+
/* Header and footer rows always render every position, so DOM order IS column order there.
|
|
814
|
+
Body rows do not: `spanRows` drops the cells a merged run covers, which promotes whatever
|
|
815
|
+
renders next to `:first-child` and would strip the border off a mid-table column. The cell
|
|
816
|
+
carries `data-leading` for its real (pinning-aware) display position instead. */
|
|
817
|
+
.ledger-root[data-with-column-borders] .ledger-table th:not(:first-child),
|
|
818
|
+
.ledger-root[data-with-column-borders] .ledger-table td:not([data-leading]) {
|
|
819
|
+
border-inline-start: 1px solid var(--ledger-border-color, var(--mantine-color-default-border));
|
|
820
|
+
}
|
|
821
|
+
|
|
822
|
+
/* Seam ownership below the body (EP's inner-wrapper overlay technique): at scroll end the
|
|
823
|
+
last row's border occupies the viewport's LAST pixel, so any line stacked outside the
|
|
824
|
+
scroller would read as one thick border. Seam lines therefore paint as inset overlays that
|
|
825
|
+
COINCIDE with that pixel — never as leading borders on the next region. */
|
|
826
|
+
|
|
827
|
+
/* z-index 2 = the pinned-cell tier: the overlay is generated after every cell, so it paints
|
|
828
|
+
over scrolling pinned cells (their opaque backgrounds would erase the line mid-scroll)
|
|
829
|
+
while staying under the scrollbars (3). */
|
|
830
|
+
.ledger-root[data-with-row-borders] .ledger-scroller::after {
|
|
831
|
+
position: absolute;
|
|
832
|
+
inset-block-end: 0;
|
|
833
|
+
inset-inline: 0;
|
|
834
|
+
z-index: 2;
|
|
835
|
+
height: 1px;
|
|
836
|
+
pointer-events: none;
|
|
837
|
+
content: "";
|
|
838
|
+
background-color: var(--ledger-border-color, var(--mantine-color-default-border));
|
|
839
|
+
}
|
|
840
|
+
|
|
841
|
+
/* The footer separates with its TRAILING edge only (the top seam is the scroller overlay);
|
|
842
|
+
under the frame this pixel coincides with the frame's bottom overlay. */
|
|
843
|
+
.ledger-root[data-with-row-borders] .ledger-footer {
|
|
844
|
+
border-block-end: 1px solid var(--ledger-border-color, var(--mantine-color-default-border));
|
|
845
|
+
}
|
|
846
|
+
|
|
847
|
+
/* The frame: three real sides; the bottom edge is an inset overlay for the same coincidence
|
|
848
|
+
reason — it lands on the scroller's (or footer's) last pixel instead of adding one below. */
|
|
849
|
+
.ledger-root[data-with-table-border] .ledger-main {
|
|
850
|
+
border: 1px solid var(--ledger-border-color, var(--mantine-color-default-border));
|
|
851
|
+
border-block-end: 0;
|
|
852
|
+
}
|
|
853
|
+
|
|
854
|
+
.ledger-root[data-with-table-border] .ledger-main::after {
|
|
855
|
+
position: absolute;
|
|
856
|
+
inset-block-end: 0;
|
|
857
|
+
inset-inline: 0;
|
|
858
|
+
z-index: 2;
|
|
859
|
+
height: 1px;
|
|
860
|
+
pointer-events: none;
|
|
861
|
+
content: "";
|
|
862
|
+
background-color: var(--ledger-border-color, var(--mantine-color-default-border));
|
|
863
|
+
}
|
|
864
|
+
}
|
|
865
|
+
|
|
866
|
+
/* Interaction overrides reopen the same layer after every base rule, so equal-specificity base
|
|
867
|
+
declarations cannot win through source order. */
|
|
868
|
+
@layer ledger {
|
|
869
|
+
/* No hover, no reveal: the toolbar lives inline and the rest-state marks stand down — the
|
|
870
|
+
controls sitting right there already say the same thing. */
|
|
871
|
+
@media (hover: none) {
|
|
872
|
+
.ledger-columns-panel-handle {
|
|
873
|
+
opacity: 1;
|
|
874
|
+
}
|
|
875
|
+
|
|
876
|
+
.ledger-columns-panel-indicators {
|
|
877
|
+
display: none;
|
|
878
|
+
}
|
|
879
|
+
|
|
880
|
+
.ledger-columns-panel-controls {
|
|
881
|
+
position: static;
|
|
882
|
+
flex: none;
|
|
883
|
+
padding-inline: 0;
|
|
884
|
+
pointer-events: auto;
|
|
885
|
+
background-color: transparent;
|
|
886
|
+
opacity: 1;
|
|
887
|
+
}
|
|
888
|
+
|
|
889
|
+
.ledger-columns-panel-controls::before {
|
|
890
|
+
content: none;
|
|
891
|
+
}
|
|
892
|
+
}
|
|
893
|
+
|
|
894
|
+
@media (prefers-reduced-motion: reduce) {
|
|
895
|
+
.ledger-expander-cell button svg,
|
|
896
|
+
[data-group-cell] button svg,
|
|
897
|
+
.ledger-expander-cell button[data-expanded] svg,
|
|
898
|
+
.ledger-header-cell button[data-expanded] svg,
|
|
899
|
+
.ledger-columns-panel-handle,
|
|
900
|
+
.ledger-columns-panel-controls {
|
|
901
|
+
transition: none;
|
|
902
|
+
}
|
|
903
|
+
}
|
|
904
|
+
}
|