@visns-studio/visns-components 6.3.8 → 6.3.10
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
CHANGED
|
@@ -91,7 +91,7 @@
|
|
|
91
91
|
"react-dom": "^17.0.0 || ^18.0.0"
|
|
92
92
|
},
|
|
93
93
|
"name": "@visns-studio/visns-components",
|
|
94
|
-
"version": "6.3.
|
|
94
|
+
"version": "6.3.10",
|
|
95
95
|
"description": "Various packages to assist in the development of our Custom Applications.",
|
|
96
96
|
"main": "src/index.js",
|
|
97
97
|
"files": [
|
|
@@ -75,6 +75,13 @@ import {
|
|
|
75
75
|
AlertCircle,
|
|
76
76
|
CheckCheck,
|
|
77
77
|
Plus,
|
|
78
|
+
// treeGroupBy parent rows: ChevronDown is the collapse control in BOTH
|
|
79
|
+
// states — it is rotated rather than swapped for ChevronRight, so the
|
|
80
|
+
// glyph turns between them instead of popping, and the direction it
|
|
81
|
+
// points is the state. ListPlus is the "add another to this group"
|
|
82
|
+
// affordance, which a bare Plus does not say on its own.
|
|
83
|
+
ChevronDown,
|
|
84
|
+
ListPlus,
|
|
78
85
|
} from 'lucide-react';
|
|
79
86
|
import styles from './styles/DataGrid.module.scss';
|
|
80
87
|
|
|
@@ -1826,6 +1833,10 @@ const DataGrid = forwardRef(
|
|
|
1826
1833
|
return CheckCheck;
|
|
1827
1834
|
case 'plus':
|
|
1828
1835
|
return Plus;
|
|
1836
|
+
// A separate id rather than a re-point of `plus`: every other
|
|
1837
|
+
// project's `plus` icon must keep the glyph it has always had.
|
|
1838
|
+
case 'listPlus':
|
|
1839
|
+
return ListPlus;
|
|
1829
1840
|
case 'edit':
|
|
1830
1841
|
return Edit;
|
|
1831
1842
|
case 'envelope':
|
|
@@ -3738,9 +3749,29 @@ const DataGrid = forwardRef(
|
|
|
3738
3749
|
entries.filter(isRowActionConfig);
|
|
3739
3750
|
// Per-row conditions may hide row actions at
|
|
3740
3751
|
// runtime, but the column must fit the maximum
|
|
3741
|
-
const
|
|
3742
|
-
actionSettings.length + rowActions.length
|
|
3743
|
-
|
|
3752
|
+
const actionCount =
|
|
3753
|
+
actionSettings.length + rowActions.length;
|
|
3754
|
+
const computedWidth =
|
|
3755
|
+
actionColumnWidthFor(actionCount);
|
|
3756
|
+
// An explicit config maxWidth may narrow the
|
|
3757
|
+
// column below the 100px floor (a single-icon
|
|
3758
|
+
// column doesn't need it), but never below
|
|
3759
|
+
// what the icons themselves need — tap targets
|
|
3760
|
+
// stay intact in tablet mode.
|
|
3761
|
+
const iconsNeed =
|
|
3762
|
+
actionCount *
|
|
3763
|
+
(isTabletMode ? 44 : 34) +
|
|
3764
|
+
16;
|
|
3765
|
+
const width =
|
|
3766
|
+
column.maxWidth != null
|
|
3767
|
+
? Math.max(
|
|
3768
|
+
iconsNeed,
|
|
3769
|
+
Math.min(
|
|
3770
|
+
column.maxWidth,
|
|
3771
|
+
computedWidth
|
|
3772
|
+
)
|
|
3773
|
+
)
|
|
3774
|
+
: computedWidth;
|
|
3744
3775
|
return {
|
|
3745
3776
|
...commonProps,
|
|
3746
3777
|
name: Array.isArray(column.id)
|
|
@@ -4140,9 +4171,125 @@ const DataGrid = forwardRef(
|
|
|
4140
4171
|
};
|
|
4141
4172
|
};
|
|
4142
4173
|
|
|
4174
|
+
/**
|
|
4175
|
+
* The group's collapse control.
|
|
4176
|
+
*
|
|
4177
|
+
* One glyph in both states: ChevronDown, turned a quarter
|
|
4178
|
+
* to point right when the group is shut. That is the
|
|
4179
|
+
* idiom every tree in every file manager uses, and it
|
|
4180
|
+
* animates — a "+"/"−" pair swaps two unrelated marks and
|
|
4181
|
+
* says nothing about direction. `relocated` picks the
|
|
4182
|
+
* class set, since the controls-column variant is sized
|
|
4183
|
+
* for a fingertip and must not inherit the inline one's
|
|
4184
|
+
* legacy dimensions.
|
|
4185
|
+
*
|
|
4186
|
+
* aria-expanded carries the state for assistive tech, so
|
|
4187
|
+
* the meaning does not depend on seeing the rotation.
|
|
4188
|
+
*/
|
|
4189
|
+
const renderTreeCollapseControl = (
|
|
4190
|
+
groupValue,
|
|
4191
|
+
collapsed,
|
|
4192
|
+
relocated
|
|
4193
|
+
) => (
|
|
4194
|
+
<button
|
|
4195
|
+
type="button"
|
|
4196
|
+
className={
|
|
4197
|
+
relocated
|
|
4198
|
+
? `tree-control-btn ${styles.treeControlBtn} ${styles.treeControlChevron}`
|
|
4199
|
+
: `group-expand-btn ${styles.groupExpandBtn}`
|
|
4200
|
+
}
|
|
4201
|
+
aria-expanded={!collapsed}
|
|
4202
|
+
aria-label={
|
|
4203
|
+
collapsed ? 'Expand group' : 'Collapse group'
|
|
4204
|
+
}
|
|
4205
|
+
onClick={(e) => {
|
|
4206
|
+
e.stopPropagation();
|
|
4207
|
+
toggleTreeGroup(groupValue);
|
|
4208
|
+
}}
|
|
4209
|
+
data-tooltip-id="system-tooltip"
|
|
4210
|
+
data-tooltip-content={
|
|
4211
|
+
collapsed ? 'Expand group' : 'Collapse group'
|
|
4212
|
+
}
|
|
4213
|
+
>
|
|
4214
|
+
{relocated ? (
|
|
4215
|
+
<ChevronDown
|
|
4216
|
+
className={
|
|
4217
|
+
collapsed
|
|
4218
|
+
? styles.treeChevronCollapsed
|
|
4219
|
+
: styles.treeChevronExpanded
|
|
4220
|
+
}
|
|
4221
|
+
strokeWidth={2.25}
|
|
4222
|
+
size={18}
|
|
4223
|
+
aria-hidden="true"
|
|
4224
|
+
/>
|
|
4225
|
+
) : collapsed ? (
|
|
4226
|
+
'+'
|
|
4227
|
+
) : (
|
|
4228
|
+
'−'
|
|
4229
|
+
)}
|
|
4230
|
+
</button>
|
|
4231
|
+
);
|
|
4232
|
+
|
|
4233
|
+
/** The group's treeGroupBy.icons, in either placement. */
|
|
4234
|
+
const renderTreeGroupIcons = (groupValue, relocated) =>
|
|
4235
|
+
(ajaxSetting?.treeGroupBy?.icons || []).map(
|
|
4236
|
+
(iconConfig, index) => {
|
|
4237
|
+
if (
|
|
4238
|
+
!shouldShowGroupAction(
|
|
4239
|
+
iconConfig,
|
|
4240
|
+
groupValue
|
|
4241
|
+
)
|
|
4242
|
+
) {
|
|
4243
|
+
return null;
|
|
4244
|
+
}
|
|
4245
|
+
|
|
4246
|
+
const IconComponent = getGroupIconComponent(
|
|
4247
|
+
iconConfig.id
|
|
4248
|
+
);
|
|
4249
|
+
const colour = iconConfig.colour || 'success';
|
|
4250
|
+
|
|
4251
|
+
return (
|
|
4252
|
+
<button
|
|
4253
|
+
type="button"
|
|
4254
|
+
key={`tree-action-${index}`}
|
|
4255
|
+
className={
|
|
4256
|
+
relocated
|
|
4257
|
+
? `tree-control-btn tree-control-${iconConfig.id}-btn ${styles.treeControlBtn} ${styles[colour] || ''}`
|
|
4258
|
+
: `group-action-btn ${styles.groupActionBtn} ${styles[colour] || ''}`
|
|
4259
|
+
}
|
|
4260
|
+
aria-label={iconConfig.label}
|
|
4261
|
+
onClick={(e) => {
|
|
4262
|
+
e.stopPropagation();
|
|
4263
|
+
handleGroupAction(
|
|
4264
|
+
groupValue,
|
|
4265
|
+
iconConfig
|
|
4266
|
+
);
|
|
4267
|
+
}}
|
|
4268
|
+
data-tooltip-id="system-tooltip"
|
|
4269
|
+
data-tooltip-content={iconConfig.label}
|
|
4270
|
+
>
|
|
4271
|
+
<IconComponent
|
|
4272
|
+
strokeWidth={2}
|
|
4273
|
+
size={relocated ? 18 : 14}
|
|
4274
|
+
aria-hidden="true"
|
|
4275
|
+
/>
|
|
4276
|
+
</button>
|
|
4277
|
+
);
|
|
4278
|
+
}
|
|
4279
|
+
);
|
|
4280
|
+
|
|
4143
4281
|
// The tree parent's display column doubles as the group's
|
|
4144
4282
|
// header line: expand/collapse plus any treeGroupBy.icons
|
|
4145
4283
|
// whose show/showAll conditions the group's rows satisfy.
|
|
4284
|
+
//
|
|
4285
|
+
// `controlsColumn` (opt-in) moves those controls into
|
|
4286
|
+
// ANOTHER column's cell on parent rows, leaving the label
|
|
4287
|
+
// cell to the label alone. Parent rows blank most
|
|
4288
|
+
// interactive columns (TREE_PARENT_BLOCKED_TYPES), so a
|
|
4289
|
+
// grid usually has an empty cell going spare while the
|
|
4290
|
+
// label is squeezed between two buttons — this spends that
|
|
4291
|
+
// space instead. Unset (the default) keeps the controls
|
|
4292
|
+
// inline exactly as they have always rendered.
|
|
4146
4293
|
const decorateTreeParentActions = (
|
|
4147
4294
|
gridColumn,
|
|
4148
4295
|
columnDef
|
|
@@ -4155,12 +4302,29 @@ const DataGrid = forwardRef(
|
|
|
4155
4302
|
if (
|
|
4156
4303
|
!tree?.key ||
|
|
4157
4304
|
!tree.column ||
|
|
4158
|
-
tree.column !== columnId ||
|
|
4159
4305
|
!(tree.collapsible || tree.icons?.length)
|
|
4160
4306
|
) {
|
|
4161
4307
|
return gridColumn;
|
|
4162
4308
|
}
|
|
4163
4309
|
|
|
4310
|
+
// Pointing controlsColumn at the label column is the
|
|
4311
|
+
// inline layout, so treat it as unset rather than
|
|
4312
|
+
// rendering the controls into the cell twice.
|
|
4313
|
+
const controlsColumn =
|
|
4314
|
+
tree.controlsColumn &&
|
|
4315
|
+
tree.controlsColumn !== tree.column
|
|
4316
|
+
? tree.controlsColumn
|
|
4317
|
+
: null;
|
|
4318
|
+
|
|
4319
|
+
const isLabelColumn = tree.column === columnId;
|
|
4320
|
+
const isControlsColumn =
|
|
4321
|
+
controlsColumn !== null &&
|
|
4322
|
+
controlsColumn === columnId;
|
|
4323
|
+
|
|
4324
|
+
if (!isLabelColumn && !isControlsColumn) {
|
|
4325
|
+
return gridColumn;
|
|
4326
|
+
}
|
|
4327
|
+
|
|
4164
4328
|
const originalRender = gridColumn.render;
|
|
4165
4329
|
|
|
4166
4330
|
return {
|
|
@@ -4177,28 +4341,44 @@ const DataGrid = forwardRef(
|
|
|
4177
4341
|
const groupValue = data[tree.key];
|
|
4178
4342
|
const collapsed = data.__treeCollapsed === true;
|
|
4179
4343
|
|
|
4344
|
+
// Relocated placement: this cell carries the
|
|
4345
|
+
// controls and nothing else.
|
|
4346
|
+
if (isControlsColumn) {
|
|
4347
|
+
return (
|
|
4348
|
+
<div
|
|
4349
|
+
className={
|
|
4350
|
+
styles.treeParentControls
|
|
4351
|
+
}
|
|
4352
|
+
onClick={(e) =>
|
|
4353
|
+
e.stopPropagation()
|
|
4354
|
+
}
|
|
4355
|
+
>
|
|
4356
|
+
{tree.collapsible &&
|
|
4357
|
+
renderTreeCollapseControl(
|
|
4358
|
+
groupValue,
|
|
4359
|
+
collapsed,
|
|
4360
|
+
true
|
|
4361
|
+
)}
|
|
4362
|
+
{renderTreeGroupIcons(
|
|
4363
|
+
groupValue,
|
|
4364
|
+
true
|
|
4365
|
+
)}
|
|
4366
|
+
</div>
|
|
4367
|
+
);
|
|
4368
|
+
}
|
|
4369
|
+
|
|
4180
4370
|
return (
|
|
4181
4371
|
<div
|
|
4182
4372
|
className={styles.treeParentHeader}
|
|
4183
4373
|
onClick={(e) => e.stopPropagation()}
|
|
4184
4374
|
>
|
|
4185
|
-
{
|
|
4186
|
-
|
|
4187
|
-
|
|
4188
|
-
|
|
4189
|
-
|
|
4190
|
-
|
|
4191
|
-
|
|
4192
|
-
data-tooltip-id="system-tooltip"
|
|
4193
|
-
data-tooltip-content={
|
|
4194
|
-
collapsed
|
|
4195
|
-
? 'Expand group'
|
|
4196
|
-
: 'Collapse group'
|
|
4197
|
-
}
|
|
4198
|
-
>
|
|
4199
|
-
{collapsed ? '+' : '−'}
|
|
4200
|
-
</button>
|
|
4201
|
-
)}
|
|
4375
|
+
{!controlsColumn &&
|
|
4376
|
+
tree.collapsible &&
|
|
4377
|
+
renderTreeCollapseControl(
|
|
4378
|
+
groupValue,
|
|
4379
|
+
collapsed,
|
|
4380
|
+
false
|
|
4381
|
+
)}
|
|
4202
4382
|
<strong
|
|
4203
4383
|
className={styles.treeParentLabel}
|
|
4204
4384
|
>
|
|
@@ -4207,53 +4387,11 @@ const DataGrid = forwardRef(
|
|
|
4207
4387
|
? ` (${data.__treeChildCount})`
|
|
4208
4388
|
: ''}
|
|
4209
4389
|
</strong>
|
|
4210
|
-
{
|
|
4211
|
-
(
|
|
4212
|
-
|
|
4213
|
-
|
|
4214
|
-
|
|
4215
|
-
groupValue
|
|
4216
|
-
)
|
|
4217
|
-
) {
|
|
4218
|
-
return null;
|
|
4219
|
-
}
|
|
4220
|
-
|
|
4221
|
-
const IconComponent =
|
|
4222
|
-
getGroupIconComponent(
|
|
4223
|
-
iconConfig.id
|
|
4224
|
-
);
|
|
4225
|
-
|
|
4226
|
-
return (
|
|
4227
|
-
<button
|
|
4228
|
-
key={`tree-action-${index}`}
|
|
4229
|
-
className={`group-action-btn ${
|
|
4230
|
-
styles.groupActionBtn
|
|
4231
|
-
} ${
|
|
4232
|
-
styles[
|
|
4233
|
-
iconConfig.colour ||
|
|
4234
|
-
'success'
|
|
4235
|
-
] || ''
|
|
4236
|
-
}`}
|
|
4237
|
-
onClick={(e) => {
|
|
4238
|
-
e.stopPropagation();
|
|
4239
|
-
handleGroupAction(
|
|
4240
|
-
groupValue,
|
|
4241
|
-
iconConfig
|
|
4242
|
-
);
|
|
4243
|
-
}}
|
|
4244
|
-
data-tooltip-id="system-tooltip"
|
|
4245
|
-
data-tooltip-content={
|
|
4246
|
-
iconConfig.label
|
|
4247
|
-
}
|
|
4248
|
-
>
|
|
4249
|
-
<IconComponent
|
|
4250
|
-
strokeWidth={2}
|
|
4251
|
-
size={14}
|
|
4252
|
-
/>
|
|
4253
|
-
</button>
|
|
4254
|
-
);
|
|
4255
|
-
}
|
|
4256
|
-
)}
|
|
4390
|
+
{!controlsColumn &&
|
|
4391
|
+
renderTreeGroupIcons(
|
|
4392
|
+
groupValue,
|
|
4393
|
+
false
|
|
4394
|
+
)}
|
|
4257
4395
|
</div>
|
|
4258
4396
|
);
|
|
4259
4397
|
},
|
|
@@ -1402,3 +1402,180 @@
|
|
|
1402
1402
|
opacity: var(--grid-row-complete-opacity, 0.7);
|
|
1403
1403
|
}
|
|
1404
1404
|
}
|
|
1405
|
+
|
|
1406
|
+
/* =========================================================================
|
|
1407
|
+
treeGroupBy relocated group controls (`treeGroupBy.controlsColumn`)
|
|
1408
|
+
|
|
1409
|
+
When the controls move out of the label cell they stop being decoration
|
|
1410
|
+
squeezed beside a tag and become the row's primary affordance, so they are
|
|
1411
|
+
sized as targets rather than as glyphs. They also get class names of their
|
|
1412
|
+
own rather than reusing `.groupExpandBtn` / `.groupActionBtn`: consuming
|
|
1413
|
+
projects have `!important` rules pinned to those (hartway clamps them to
|
|
1414
|
+
38px in tablet mode), and inheriting a size tuned for the cramped inline
|
|
1415
|
+
layout is exactly what this placement exists to escape.
|
|
1416
|
+
|
|
1417
|
+
Meaning never rests on colour: each control carries a glyph, the collapse
|
|
1418
|
+
state is carried by the chevron's rotation AND by aria-expanded, and the
|
|
1419
|
+
colour classes below are the same decorative palette the inline buttons
|
|
1420
|
+
use. A greyscale screen loses nothing.
|
|
1421
|
+
|
|
1422
|
+
Density hooks, per the `--nav-*` / `--grid-legend-*` convention above:
|
|
1423
|
+
|
|
1424
|
+
--grid-tree-control-size control box, pointer input. default: 32px
|
|
1425
|
+
--grid-tree-control-size-tablet control box under body.tablet-mode.
|
|
1426
|
+
default: 44px — the tap-target floor for
|
|
1427
|
+
a gloved hand on the plant floor, and the
|
|
1428
|
+
reason this placement is worth having.
|
|
1429
|
+
--grid-tree-control-gap space between controls. default: 6px
|
|
1430
|
+
========================================================================= */
|
|
1431
|
+
|
|
1432
|
+
.treeParentControls {
|
|
1433
|
+
display: flex;
|
|
1434
|
+
align-items: center;
|
|
1435
|
+
justify-content: flex-start;
|
|
1436
|
+
gap: var(--grid-tree-control-gap, 6px);
|
|
1437
|
+
width: 100%;
|
|
1438
|
+
height: 100%;
|
|
1439
|
+
}
|
|
1440
|
+
|
|
1441
|
+
.treeControlBtn {
|
|
1442
|
+
flex-shrink: 0;
|
|
1443
|
+
display: inline-flex;
|
|
1444
|
+
align-items: center;
|
|
1445
|
+
justify-content: center;
|
|
1446
|
+
box-sizing: border-box;
|
|
1447
|
+
width: var(--grid-tree-control-size, 32px);
|
|
1448
|
+
height: var(--grid-tree-control-size, 32px);
|
|
1449
|
+
min-width: var(--grid-tree-control-size, 32px);
|
|
1450
|
+
min-height: var(--grid-tree-control-size, 32px);
|
|
1451
|
+
padding: 0;
|
|
1452
|
+
border: none;
|
|
1453
|
+
border-radius: var(--radius-sm, 6px);
|
|
1454
|
+
background: var(--primary-color, #3b82f6);
|
|
1455
|
+
color: white;
|
|
1456
|
+
cursor: pointer;
|
|
1457
|
+
box-shadow: 0 1px 2px rgba(0, 0, 0, 0.12);
|
|
1458
|
+
transition: background 0.2s ease, box-shadow 0.2s ease,
|
|
1459
|
+
transform 0.1s ease;
|
|
1460
|
+
|
|
1461
|
+
&:hover {
|
|
1462
|
+
box-shadow: 0 3px 6px rgba(0, 0, 0, 0.18);
|
|
1463
|
+
}
|
|
1464
|
+
|
|
1465
|
+
&:active {
|
|
1466
|
+
transform: scale(0.94);
|
|
1467
|
+
}
|
|
1468
|
+
|
|
1469
|
+
// A keyboard user has to be able to see which control is theirs; the grid
|
|
1470
|
+
// suppresses its own outline inside cells, so state it here.
|
|
1471
|
+
&:focus-visible {
|
|
1472
|
+
outline: 2px solid var(--primary-color, #3b82f6);
|
|
1473
|
+
outline-offset: 2px;
|
|
1474
|
+
}
|
|
1475
|
+
|
|
1476
|
+
// Colour variants, matching `.groupActionBtn`'s set so an icon config
|
|
1477
|
+
// reads the same in either placement.
|
|
1478
|
+
&.success {
|
|
1479
|
+
background: var(--success-color, #10b981);
|
|
1480
|
+
&:hover {
|
|
1481
|
+
background: var(--success-hover-color, #059669);
|
|
1482
|
+
}
|
|
1483
|
+
}
|
|
1484
|
+
|
|
1485
|
+
&.warning {
|
|
1486
|
+
background: var(--warning-color, #f59e0b);
|
|
1487
|
+
&:hover {
|
|
1488
|
+
background: var(--warning-hover-color, #d97706);
|
|
1489
|
+
}
|
|
1490
|
+
}
|
|
1491
|
+
|
|
1492
|
+
&.info {
|
|
1493
|
+
background: var(--info-color, #3b82f6);
|
|
1494
|
+
&:hover {
|
|
1495
|
+
background: var(--info-hover-color, #2563eb);
|
|
1496
|
+
}
|
|
1497
|
+
}
|
|
1498
|
+
|
|
1499
|
+
&.purple {
|
|
1500
|
+
background: var(--purple-color, #8b5cf6);
|
|
1501
|
+
&:hover {
|
|
1502
|
+
background: var(--purple-hover-color, #7c3aed);
|
|
1503
|
+
}
|
|
1504
|
+
}
|
|
1505
|
+
|
|
1506
|
+
&.pink {
|
|
1507
|
+
background: var(--pink-color, #ec4899);
|
|
1508
|
+
&:hover {
|
|
1509
|
+
background: var(--pink-hover-color, #db2777);
|
|
1510
|
+
}
|
|
1511
|
+
}
|
|
1512
|
+
}
|
|
1513
|
+
|
|
1514
|
+
/* The collapse control is deliberately quieter than the action buttons: it
|
|
1515
|
+
changes what you can see, not what the plant has done, so it reads as
|
|
1516
|
+
chrome rather than as a fourth coloured button competing with them. */
|
|
1517
|
+
.treeControlChevron {
|
|
1518
|
+
background: rgba(var(--paragraph-color-rgb, 34, 30, 51), 0.08);
|
|
1519
|
+
color: var(--paragraph-color, #374151);
|
|
1520
|
+
box-shadow: none;
|
|
1521
|
+
|
|
1522
|
+
&:hover {
|
|
1523
|
+
background: rgba(var(--paragraph-color-rgb, 34, 30, 51), 0.16);
|
|
1524
|
+
box-shadow: none;
|
|
1525
|
+
}
|
|
1526
|
+
}
|
|
1527
|
+
|
|
1528
|
+
.treeChevronExpanded,
|
|
1529
|
+
.treeChevronCollapsed {
|
|
1530
|
+
transition: transform 0.18s ease;
|
|
1531
|
+
}
|
|
1532
|
+
|
|
1533
|
+
.treeChevronExpanded {
|
|
1534
|
+
transform: rotate(0deg);
|
|
1535
|
+
}
|
|
1536
|
+
|
|
1537
|
+
/* Shut: the chevron points at the row it would open, the same way every
|
|
1538
|
+
file tree in the world points at a closed folder. */
|
|
1539
|
+
.treeChevronCollapsed {
|
|
1540
|
+
transform: rotate(-90deg);
|
|
1541
|
+
}
|
|
1542
|
+
|
|
1543
|
+
@media (prefers-reduced-motion: reduce) {
|
|
1544
|
+
.treeChevronExpanded,
|
|
1545
|
+
.treeChevronCollapsed {
|
|
1546
|
+
transition: none;
|
|
1547
|
+
}
|
|
1548
|
+
}
|
|
1549
|
+
|
|
1550
|
+
/* Tablet mode is a bench at arm's length worked with gloves on, so the
|
|
1551
|
+
controls step up to the 44px tap-target floor. Scoped to body.tablet-mode,
|
|
1552
|
+
the same signal the package already styles against in global-datagrid.css.
|
|
1553
|
+
The grid's tablet rows are 52px, so 44px still clears the row edges. */
|
|
1554
|
+
:global(body.tablet-mode) {
|
|
1555
|
+
.treeControlBtn {
|
|
1556
|
+
width: var(--grid-tree-control-size-tablet, 44px);
|
|
1557
|
+
height: var(--grid-tree-control-size-tablet, 44px);
|
|
1558
|
+
min-width: var(--grid-tree-control-size-tablet, 44px);
|
|
1559
|
+
min-height: var(--grid-tree-control-size-tablet, 44px);
|
|
1560
|
+
border-radius: var(--radius-md, 8px);
|
|
1561
|
+
}
|
|
1562
|
+
|
|
1563
|
+
.treeParentControls {
|
|
1564
|
+
gap: var(--grid-tree-control-gap, 8px);
|
|
1565
|
+
|
|
1566
|
+
/* A tablet row is a fixed 52px and the grid pads its cells 6px top
|
|
1567
|
+
and bottom, leaving a 40px content box — 4px short of the floor
|
|
1568
|
+
this placement exists to clear. This strip IS the whole cell's
|
|
1569
|
+
content and its buttons carry their own spacing, so it reclaims
|
|
1570
|
+
that padding rather than letting the control shrink to fit.
|
|
1571
|
+
Negative margin rather than overflow: the 44px control then sits
|
|
1572
|
+
inside the row's own 52px border box, so a cell that hides its
|
|
1573
|
+
overflow has nothing to clip.
|
|
1574
|
+
|
|
1575
|
+
--grid-tree-control-cell-inset cell padding to reclaim.
|
|
1576
|
+
default: 6px */
|
|
1577
|
+
margin-block: calc(
|
|
1578
|
+
-1 * var(--grid-tree-control-cell-inset, 6px)
|
|
1579
|
+
);
|
|
1580
|
+
}
|
|
1581
|
+
}
|