@matteoaliano/forest-ui 1.2.4 → 1.2.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{chunk-JYITTRWG.mjs → chunk-B5MZMBLL.mjs} +178 -108
- package/dist/chunk-B5MZMBLL.mjs.map +1 -0
- package/dist/index.d.mts +21 -6
- package/dist/index.d.ts +21 -6
- package/dist/index.js +344 -154
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +377 -257
- package/dist/index.mjs.map +1 -1
- package/dist/theme.js +177 -107
- package/dist/theme.js.map +1 -1
- package/dist/theme.mjs +1 -1
- package/package.json +1 -1
- package/skills/forest-alkemy-plus/SKILL.md +2 -2
- package/skills/forest-alkemy-plus/references/components.md +2 -2
- package/dist/chunk-JYITTRWG.mjs.map +0 -1
package/dist/index.js
CHANGED
|
@@ -222,7 +222,7 @@ __export(src_exports, {
|
|
|
222
222
|
TextField: () => import_TextField.default,
|
|
223
223
|
TextareaAutosize: () => import_TextareaAutosize.default,
|
|
224
224
|
ToggleButton: () => ToggleButton,
|
|
225
|
-
ToggleButtonGroup: () =>
|
|
225
|
+
ToggleButtonGroup: () => ToggleButtonGroup,
|
|
226
226
|
Toolbar: () => import_Toolbar.default,
|
|
227
227
|
Tooltip: () => Tooltip,
|
|
228
228
|
Typography: () => import_Typography.default,
|
|
@@ -591,19 +591,13 @@ function buildComponents(tokens2) {
|
|
|
591
591
|
}
|
|
592
592
|
};
|
|
593
593
|
const bevelHover = {
|
|
594
|
-
borderTopWidth:
|
|
595
|
-
borderBottomWidth: 1
|
|
596
|
-
borderTopLeftRadius: radius4.lg,
|
|
597
|
-
borderTopRightRadius: radius4.lg,
|
|
598
|
-
borderBottomLeftRadius: radius4.md,
|
|
599
|
-
borderBottomRightRadius: radius4.md
|
|
594
|
+
borderTopWidth: 3,
|
|
595
|
+
borderBottomWidth: 1
|
|
600
596
|
};
|
|
601
597
|
const bevelPress = {
|
|
602
598
|
// Snap the press faster than the 300ms hover flip so it feels tactile.
|
|
603
599
|
transition: "border-width 120ms ease, border-radius 120ms ease, opacity 120ms ease",
|
|
604
600
|
borderTopWidth: 1,
|
|
605
|
-
borderTopLeftRadius: radius4.md,
|
|
606
|
-
borderTopRightRadius: radius4.md,
|
|
607
601
|
opacity: 0.75
|
|
608
602
|
};
|
|
609
603
|
const bevel3D = {
|
|
@@ -614,9 +608,7 @@ function buildComponents(tokens2) {
|
|
|
614
608
|
borderTopWidth: 1,
|
|
615
609
|
borderRightWidth: 1,
|
|
616
610
|
borderLeftWidth: 1,
|
|
617
|
-
borderBottomWidth:
|
|
618
|
-
borderBottomLeftRadius: radius4.lg,
|
|
619
|
-
borderBottomRightRadius: radius4.lg,
|
|
611
|
+
borderBottomWidth: 3,
|
|
620
612
|
"&::before": {
|
|
621
613
|
content: '""',
|
|
622
614
|
position: "absolute",
|
|
@@ -653,6 +645,21 @@ function buildComponents(tokens2) {
|
|
|
653
645
|
}
|
|
654
646
|
}
|
|
655
647
|
},
|
|
648
|
+
// ─── ButtonBase (global) ────────────────────────────────────────
|
|
649
|
+
// Kills MUI's TouchRipple everywhere in one place. Every clickable in the
|
|
650
|
+
// library renders through ButtonBase, so this reaches Button, IconButton,
|
|
651
|
+
// Fab, ToggleButton, CardActionArea, ListItemButton, MenuItem, Tab, Chip,
|
|
652
|
+
// PaginationItem, StepButton, BottomNavigationAction, SpeedDialAction and
|
|
653
|
+
// the Pickers' day/month/year cells without a per-component opt-out.
|
|
654
|
+
//
|
|
655
|
+
// The press feedback is the faux-3D bevel instead: the raised bottom edge
|
|
656
|
+
// collapses and the face dims on :active (see `bevelPress`). An expanding
|
|
657
|
+
// circle on top of that reads as a second, competing press affordance.
|
|
658
|
+
MuiButtonBase: {
|
|
659
|
+
defaultProps: {
|
|
660
|
+
disableRipple: true
|
|
661
|
+
}
|
|
662
|
+
},
|
|
656
663
|
// ─── Button ─────────────────────────────────────────────────────
|
|
657
664
|
MuiButton: {
|
|
658
665
|
defaultProps: {
|
|
@@ -672,7 +679,7 @@ function buildComponents(tokens2) {
|
|
|
672
679
|
const colorScales = { error: error2, warning: warning2, success: success2, info: info2 };
|
|
673
680
|
const faceScale = ownerState.color ? colorScales[ownerState.color] : void 0;
|
|
674
681
|
return {
|
|
675
|
-
borderRadius: radius4.
|
|
682
|
+
borderRadius: radius4.lg,
|
|
676
683
|
fontWeight: 600,
|
|
677
684
|
boxShadow: tokenShadows.xs,
|
|
678
685
|
height: 32,
|
|
@@ -690,12 +697,7 @@ function buildComponents(tokens2) {
|
|
|
690
697
|
borderTopWidth: 1,
|
|
691
698
|
borderRightWidth: 1,
|
|
692
699
|
borderLeftWidth: 1,
|
|
693
|
-
borderBottomWidth:
|
|
694
|
-
// Round the thick-bevel side more than the rest so the inner
|
|
695
|
-
// surface isn't squared off. Follows the bevel: bottom at rest,
|
|
696
|
-
// top on hover.
|
|
697
|
-
borderBottomLeftRadius: radius4.lg,
|
|
698
|
-
borderBottomRightRadius: radius4.lg,
|
|
700
|
+
borderBottomWidth: 3,
|
|
699
701
|
// Contained buttons have no border of their own — give them a
|
|
700
702
|
// translucent bevel. Outlined keeps its own border color.
|
|
701
703
|
...isContained && {
|
|
@@ -720,12 +722,8 @@ function buildComponents(tokens2) {
|
|
|
720
722
|
transition: "top 500ms ease-in-out"
|
|
721
723
|
},
|
|
722
724
|
"&:hover": {
|
|
723
|
-
borderTopWidth:
|
|
725
|
+
borderTopWidth: 3,
|
|
724
726
|
borderBottomWidth: 1,
|
|
725
|
-
borderTopLeftRadius: radius4.lg,
|
|
726
|
-
borderTopRightRadius: radius4.lg,
|
|
727
|
-
borderBottomLeftRadius: radius4.md,
|
|
728
|
-
borderBottomRightRadius: radius4.md,
|
|
729
727
|
// One step lighter than the default bevel (60% → 70%) so it
|
|
730
728
|
// stays visible against the brightened face on hover.
|
|
731
729
|
...isContained && {
|
|
@@ -752,8 +750,6 @@ function buildComponents(tokens2) {
|
|
|
752
750
|
// like a tactile click rather than a slow settle.
|
|
753
751
|
transition: "border-width 120ms ease, border-radius 120ms ease, opacity 120ms ease",
|
|
754
752
|
borderTopWidth: 1,
|
|
755
|
-
borderTopLeftRadius: radius4.md,
|
|
756
|
-
borderTopRightRadius: radius4.md,
|
|
757
753
|
opacity: 0.75
|
|
758
754
|
},
|
|
759
755
|
// Unified disabled treatment across the button family (Button,
|
|
@@ -768,7 +764,7 @@ function buildComponents(tokens2) {
|
|
|
768
764
|
borderTopWidth: 1,
|
|
769
765
|
borderRightWidth: 1,
|
|
770
766
|
borderLeftWidth: 1,
|
|
771
|
-
borderBottomWidth:
|
|
767
|
+
borderBottomWidth: 3
|
|
772
768
|
},
|
|
773
769
|
"@media (prefers-reduced-motion: reduce)": {
|
|
774
770
|
transition: "none",
|
|
@@ -803,7 +799,7 @@ function buildComponents(tokens2) {
|
|
|
803
799
|
},
|
|
804
800
|
styleOverrides: {
|
|
805
801
|
root: {
|
|
806
|
-
borderRadius: radius4.
|
|
802
|
+
borderRadius: radius4.lg,
|
|
807
803
|
// contained group → children already render as contained Buttons; only
|
|
808
804
|
// re-pin the bevel border color, which MUI's own grouped-contained
|
|
809
805
|
// default (palette grey) otherwise overrides away from the standalone
|
|
@@ -843,7 +839,7 @@ function buildComponents(tokens2) {
|
|
|
843
839
|
backgroundColor: "transparent",
|
|
844
840
|
color: buttonColors4.tertiaryColor.fg,
|
|
845
841
|
borderWidth: 0,
|
|
846
|
-
borderRadius: radius4.
|
|
842
|
+
borderRadius: radius4.lg,
|
|
847
843
|
boxShadow: "none",
|
|
848
844
|
"&::before": { display: "none" },
|
|
849
845
|
"&:active": { opacity: 1 },
|
|
@@ -875,17 +871,17 @@ function buildComponents(tokens2) {
|
|
|
875
871
|
MuiIconButton: {
|
|
876
872
|
styleOverrides: {
|
|
877
873
|
root: ({ theme }) => ({
|
|
878
|
-
borderRadius: radius4.
|
|
874
|
+
borderRadius: radius4.lg,
|
|
879
875
|
padding: 6,
|
|
880
876
|
"& .MuiSvgIcon-root": {
|
|
881
877
|
fontSize: 20
|
|
882
878
|
},
|
|
883
879
|
"&.ForestIconButton": {
|
|
884
880
|
...bevel3D,
|
|
885
|
-
// Square 32×32 with border-box so the faux-3D bevel (1px top +
|
|
881
|
+
// Square 32×32 with border-box so the faux-3D bevel (1px top + 3px
|
|
886
882
|
// bottom, 1px left/right) is absorbed rather than added on top —
|
|
887
|
-
// otherwise it rendered
|
|
888
|
-
// standalone Button's 32px height.
|
|
883
|
+
// otherwise it rendered an oversized control instead of matching
|
|
884
|
+
// the standalone Button's 32px height.
|
|
889
885
|
height: 32,
|
|
890
886
|
width: 32,
|
|
891
887
|
boxSizing: "border-box",
|
|
@@ -942,8 +938,7 @@ function buildComponents(tokens2) {
|
|
|
942
938
|
// ─── FAB ────────────────────────────────────────────────────────
|
|
943
939
|
// A Fab is a round contained Button: same faux-3D bevel, light sweep,
|
|
944
940
|
// brightness lift, and press. The border radii are left untouched so the
|
|
945
|
-
// circular / extended silhouettes survive the bevel flip
|
|
946
|
-
// like Button/IconButton do on their rounded corners).
|
|
941
|
+
// circular / extended silhouettes survive the bevel flip.
|
|
947
942
|
MuiFab: {
|
|
948
943
|
styleOverrides: {
|
|
949
944
|
root: ({ theme, ownerState }) => ({
|
|
@@ -959,7 +954,7 @@ function buildComponents(tokens2) {
|
|
|
959
954
|
borderTopWidth: 1,
|
|
960
955
|
borderRightWidth: 1,
|
|
961
956
|
borderLeftWidth: 1,
|
|
962
|
-
borderBottomWidth:
|
|
957
|
+
borderBottomWidth: 3,
|
|
963
958
|
"&::before": {
|
|
964
959
|
content: '""',
|
|
965
960
|
position: "absolute",
|
|
@@ -977,7 +972,7 @@ function buildComponents(tokens2) {
|
|
|
977
972
|
},
|
|
978
973
|
"&:hover": {
|
|
979
974
|
boxShadow: tokenShadows.xs,
|
|
980
|
-
borderTopWidth:
|
|
975
|
+
borderTopWidth: 3,
|
|
981
976
|
borderBottomWidth: 1,
|
|
982
977
|
// Light mode: dark face, brightness lift reads as hover. Dark
|
|
983
978
|
// mode: the face is already light — a lift blows out the top
|
|
@@ -1192,7 +1187,10 @@ function buildComponents(tokens2) {
|
|
|
1192
1187
|
MuiAutocomplete: {
|
|
1193
1188
|
styleOverrides: {
|
|
1194
1189
|
paper: {
|
|
1195
|
-
borderRadius
|
|
1190
|
+
// No borderRadius here on purpose — it inherits MuiPaper's `rounded`
|
|
1191
|
+
// (radius.lg), so the popup matches Menu, Popover and every other
|
|
1192
|
+
// Paper surface. It used to set radius.md and was the one popup in
|
|
1193
|
+
// the system with a sharper corner.
|
|
1196
1194
|
boxShadow: tokenShadows.lg,
|
|
1197
1195
|
border: `1px solid ${border4.secondary}`,
|
|
1198
1196
|
marginTop: 4
|
|
@@ -1206,10 +1204,42 @@ function buildComponents(tokens2) {
|
|
|
1206
1204
|
lineHeight: "20px"
|
|
1207
1205
|
}
|
|
1208
1206
|
},
|
|
1207
|
+
// MUI hardcodes this slot's own padding/marginRight in its source
|
|
1208
|
+
// (padding: 2, marginRight: -2), which wins over the global
|
|
1209
|
+
// MuiIconButton root override at equal specificity — left alone, the
|
|
1210
|
+
// popup toggle renders as a small 24px button that doesn't fill the
|
|
1211
|
+
// 32px input row and stops short of the edge. Restated here at the
|
|
1212
|
+
// same size/inset as the DatePicker's open-picker button (32px,
|
|
1213
|
+
// padding 6, flush against the input's 12px right padding) so both
|
|
1214
|
+
// end-of-input icon buttons match.
|
|
1215
|
+
popupIndicator: {
|
|
1216
|
+
padding: 6,
|
|
1217
|
+
// Not a straight copy of the DatePicker's -12px: that value cancels
|
|
1218
|
+
// the input row's 12px padding directly, but this button's
|
|
1219
|
+
// grandparent (`.MuiAutocomplete-endAdornment`) is itself inset 9px
|
|
1220
|
+
// from the input's true right edge by MUI's own variant styles.
|
|
1221
|
+
// -9px reaches through that inset to land flush, matching the
|
|
1222
|
+
// DatePicker's open-picker button exactly.
|
|
1223
|
+
marginRight: -9
|
|
1224
|
+
},
|
|
1225
|
+
// Same MUI-hardcoded-slot problem as popupIndicator, one size down
|
|
1226
|
+
// (padding: 4, marginRight: -2) — sized to match it here. The
|
|
1227
|
+
// popupIndicator's own marginRight anchors it to the input edge
|
|
1228
|
+
// independent of clearIndicator's box, so this needs no matching
|
|
1229
|
+
// offset: with both buttons the same size, 0 sits them edge-to-edge,
|
|
1230
|
+
// and their equal padding already reads as the gap between the icons.
|
|
1231
|
+
clearIndicator: {
|
|
1232
|
+
padding: 6,
|
|
1233
|
+
marginRight: 0
|
|
1234
|
+
},
|
|
1209
1235
|
option: {
|
|
1210
1236
|
fontSize: 14,
|
|
1211
1237
|
lineHeight: "20px",
|
|
1212
|
-
|
|
1238
|
+
// An Autocomplete option is a plain <li class="MuiAutocomplete-option">,
|
|
1239
|
+
// not a MenuItem, so MuiMenuItem's radius never reaches it. Match it
|
|
1240
|
+
// here so the hover/selected highlight reads as the same pill a Select
|
|
1241
|
+
// draws, inset by the listbox's 4px padding.
|
|
1242
|
+
borderRadius: radius4.md,
|
|
1213
1243
|
// Hover + selected backgrounds come from MUI's theme-aware action
|
|
1214
1244
|
// overlays (a light overlay on dark, so they stay visible — a solid
|
|
1215
1245
|
// dark-grey tier here reads as "no hover"). Selected keeps the text
|
|
@@ -1219,7 +1249,14 @@ function buildComponents(tokens2) {
|
|
|
1219
1249
|
}
|
|
1220
1250
|
},
|
|
1221
1251
|
listbox: {
|
|
1222
|
-
padding: 4
|
|
1252
|
+
padding: 4,
|
|
1253
|
+
// Padding has to live here, not in the `option` slot: MUI nests its
|
|
1254
|
+
// own option styles under the listbox, so a rule from `option` ties
|
|
1255
|
+
// on specificity and loses on source order. This selector outranks
|
|
1256
|
+
// it. 6px 8px matches MuiMenuItem.
|
|
1257
|
+
"& .MuiAutocomplete-option": {
|
|
1258
|
+
padding: "6px 8px"
|
|
1259
|
+
}
|
|
1223
1260
|
}
|
|
1224
1261
|
}
|
|
1225
1262
|
},
|
|
@@ -1231,7 +1268,7 @@ function buildComponents(tokens2) {
|
|
|
1231
1268
|
styleOverrides: {
|
|
1232
1269
|
root: {
|
|
1233
1270
|
color: border4.primary,
|
|
1234
|
-
borderRadius: radius4.
|
|
1271
|
+
borderRadius: radius4.sm,
|
|
1235
1272
|
padding: 0,
|
|
1236
1273
|
width: 20,
|
|
1237
1274
|
height: 20,
|
|
@@ -1248,7 +1285,7 @@ function buildComponents(tokens2) {
|
|
|
1248
1285
|
"&.Mui-focusVisible": {
|
|
1249
1286
|
outline: "none",
|
|
1250
1287
|
boxShadow: focusRings4.brand,
|
|
1251
|
-
borderRadius: radius4.
|
|
1288
|
+
borderRadius: radius4.sm
|
|
1252
1289
|
},
|
|
1253
1290
|
"&.Mui-disabled": {
|
|
1254
1291
|
color: border4.primary
|
|
@@ -1384,13 +1421,13 @@ function buildComponents(tokens2) {
|
|
|
1384
1421
|
color: buttonColors4.primary.fg,
|
|
1385
1422
|
borderTopWidth: 1,
|
|
1386
1423
|
borderBottomWidth: 1,
|
|
1387
|
-
borderTopLeftRadius: radius4.
|
|
1388
|
-
borderTopRightRadius: radius4.
|
|
1389
|
-
borderBottomLeftRadius: radius4.
|
|
1390
|
-
borderBottomRightRadius: radius4.
|
|
1424
|
+
borderTopLeftRadius: radius4.lg,
|
|
1425
|
+
borderTopRightRadius: radius4.lg,
|
|
1426
|
+
borderBottomLeftRadius: radius4.lg,
|
|
1427
|
+
borderBottomRightRadius: radius4.lg,
|
|
1391
1428
|
opacity: 0.75,
|
|
1392
1429
|
// The pressed-in cue is carried by the flattened bevel (bottom
|
|
1393
|
-
// border
|
|
1430
|
+
// border 3px -> 1px) alone in light mode. On the dark-mode face
|
|
1394
1431
|
// that geometry reads too faintly, so it keeps the inner shadow.
|
|
1395
1432
|
boxShadow: "none",
|
|
1396
1433
|
...theme.applyStyles("dark", {
|
|
@@ -1403,8 +1440,8 @@ function buildComponents(tokens2) {
|
|
|
1403
1440
|
filter: "none",
|
|
1404
1441
|
borderTopWidth: 1,
|
|
1405
1442
|
borderBottomWidth: 1,
|
|
1406
|
-
borderTopLeftRadius: radius4.
|
|
1407
|
-
borderTopRightRadius: radius4.
|
|
1443
|
+
borderTopLeftRadius: radius4.lg,
|
|
1444
|
+
borderTopRightRadius: radius4.lg
|
|
1408
1445
|
}
|
|
1409
1446
|
},
|
|
1410
1447
|
// variant="outlined" (Forest wrapper class): the outlined <Button> /
|
|
@@ -1448,7 +1485,7 @@ function buildComponents(tokens2) {
|
|
|
1448
1485
|
borderTopWidth: 1,
|
|
1449
1486
|
borderRightWidth: 1,
|
|
1450
1487
|
borderLeftWidth: 1,
|
|
1451
|
-
borderBottomWidth:
|
|
1488
|
+
borderBottomWidth: 3,
|
|
1452
1489
|
"&::before": { display: "none" },
|
|
1453
1490
|
// selected+disabled keeps the pressed-in cue, greyed.
|
|
1454
1491
|
"&.Mui-selected": {
|
|
@@ -1465,7 +1502,7 @@ function buildComponents(tokens2) {
|
|
|
1465
1502
|
MuiToggleButtonGroup: {
|
|
1466
1503
|
styleOverrides: {
|
|
1467
1504
|
root: {
|
|
1468
|
-
borderRadius: radius4.
|
|
1505
|
+
borderRadius: radius4.lg,
|
|
1469
1506
|
overflow: "hidden"
|
|
1470
1507
|
},
|
|
1471
1508
|
// The child ToggleButton's selected/hover/active rules set per-corner
|
|
@@ -1482,14 +1519,14 @@ function buildComponents(tokens2) {
|
|
|
1482
1519
|
},
|
|
1483
1520
|
"&:first-of-type": {
|
|
1484
1521
|
"&, &:hover, &:active, &.Mui-selected": {
|
|
1485
|
-
borderTopLeftRadius: radius4.
|
|
1486
|
-
borderBottomLeftRadius: radius4.
|
|
1522
|
+
borderTopLeftRadius: radius4.lg,
|
|
1523
|
+
borderBottomLeftRadius: radius4.lg
|
|
1487
1524
|
}
|
|
1488
1525
|
},
|
|
1489
1526
|
"&:last-of-type": {
|
|
1490
1527
|
"&, &:hover, &:active, &.Mui-selected": {
|
|
1491
|
-
borderTopRightRadius: radius4.
|
|
1492
|
-
borderBottomRightRadius: radius4.
|
|
1528
|
+
borderTopRightRadius: radius4.lg,
|
|
1529
|
+
borderBottomRightRadius: radius4.lg
|
|
1493
1530
|
}
|
|
1494
1531
|
}
|
|
1495
1532
|
}
|
|
@@ -1515,7 +1552,27 @@ function buildComponents(tokens2) {
|
|
|
1515
1552
|
border: `1px solid ${border4.secondary}`,
|
|
1516
1553
|
backgroundColor: bg4.primary,
|
|
1517
1554
|
boxShadow: tokenShadows.xs,
|
|
1518
|
-
overflow: "hidden"
|
|
1555
|
+
overflow: "hidden",
|
|
1556
|
+
// Which surface a wrapped CardActionArea should paint. The action
|
|
1557
|
+
// area can't read the Card's own `background-color` (the Card goes
|
|
1558
|
+
// transparent when it wraps one, see below), so the colour is handed
|
|
1559
|
+
// down as a custom property instead. `<Card color="secondary">`
|
|
1560
|
+
// overrides it alongside its own background.
|
|
1561
|
+
"--forest-card-surface": bg4.primary,
|
|
1562
|
+
// A Card wrapping a CardActionArea hands its whole frame over: the
|
|
1563
|
+
// action area already draws the border, surface, radius and shadow,
|
|
1564
|
+
// and flips the radius on hover. Keeping the Card's own stacks a
|
|
1565
|
+
// second, static border just outside the moving one.
|
|
1566
|
+
"&:has(> .MuiCardActionArea-root)": {
|
|
1567
|
+
border: "none",
|
|
1568
|
+
borderRadius: 0,
|
|
1569
|
+
backgroundColor: "transparent",
|
|
1570
|
+
boxShadow: "none",
|
|
1571
|
+
// The action area clips its own content (it has overflow: hidden
|
|
1572
|
+
// for the glaze), so the Card must not also clip — its square
|
|
1573
|
+
// corners would cut the action area's rounded ones.
|
|
1574
|
+
overflow: "visible"
|
|
1575
|
+
}
|
|
1519
1576
|
}
|
|
1520
1577
|
}
|
|
1521
1578
|
},
|
|
@@ -2613,52 +2670,67 @@ function buildComponents(tokens2) {
|
|
|
2613
2670
|
}
|
|
2614
2671
|
},
|
|
2615
2672
|
// ─── CardActionArea ─────────────────────────────────────────────
|
|
2616
|
-
// Clickable-card affordance:
|
|
2617
|
-
// that flips bottom->top on hover),
|
|
2618
|
-
//
|
|
2619
|
-
//
|
|
2673
|
+
// Clickable-card affordance: the outlined Button's interaction at card
|
|
2674
|
+
// scale. Same faux-3D bevel (thick edge that flips bottom->top on hover),
|
|
2675
|
+
// same glaze sweep, same brightness darken on hover, same press-to-sink —
|
|
2676
|
+
// the only difference is the radius, which stays on the card steps
|
|
2677
|
+
// (xl / 2xl) rather than the button's (md / lg). Use
|
|
2678
|
+
// <Card><CardActionArea>…</CardActionArea></Card> for any interactive card;
|
|
2679
|
+
// the Card hands over its border and surface when it sees one.
|
|
2620
2680
|
MuiCardActionArea: {
|
|
2621
2681
|
styleOverrides: {
|
|
2622
2682
|
root: {
|
|
2623
2683
|
position: "relative",
|
|
2624
2684
|
overflow: "hidden",
|
|
2625
|
-
borderRadius: radius4
|
|
2685
|
+
borderRadius: radius4["2xl"],
|
|
2626
2686
|
borderStyle: "solid",
|
|
2627
|
-
|
|
2687
|
+
// The token the outlined Button reads, not `border.primary`, so the
|
|
2688
|
+
// two stay identical under any preset.
|
|
2689
|
+
borderColor: buttonColors4.secondaryColor.border,
|
|
2690
|
+
// Painted here rather than on the Card, which goes transparent so its
|
|
2691
|
+
// square box can't clip these corners. Falls back to the default card
|
|
2692
|
+
// surface when a CardActionArea is used outside a Card.
|
|
2693
|
+
backgroundColor: `var(--forest-card-surface, ${bg4.primary})`,
|
|
2628
2694
|
borderTopWidth: 1,
|
|
2629
2695
|
borderRightWidth: 1,
|
|
2630
2696
|
borderLeftWidth: 1,
|
|
2631
|
-
borderBottomWidth:
|
|
2632
|
-
borderBottomLeftRadius: radius4["2xl"],
|
|
2633
|
-
borderBottomRightRadius: radius4["2xl"],
|
|
2697
|
+
borderBottomWidth: 3,
|
|
2634
2698
|
boxShadow: tokenShadows.xs,
|
|
2635
|
-
transition: "
|
|
2636
|
-
|
|
2699
|
+
transition: "filter 300ms ease, border-width 300ms ease, border-radius 300ms ease, opacity 300ms ease, background-color 300ms ease",
|
|
2700
|
+
"&:focus-visible": {
|
|
2701
|
+
boxShadow: focusRings4.brandShadowXs
|
|
2702
|
+
},
|
|
2703
|
+
// Moving glaze — a soft light streak that sweeps top->bottom on
|
|
2704
|
+
// hover. Same parameters as the outlined Button's sweep.
|
|
2637
2705
|
"&::before": {
|
|
2638
2706
|
content: '""',
|
|
2639
2707
|
position: "absolute",
|
|
2640
2708
|
left: 0,
|
|
2641
2709
|
top: "-150%",
|
|
2642
2710
|
width: "100%",
|
|
2643
|
-
height:
|
|
2711
|
+
height: 5,
|
|
2644
2712
|
borderRadius: 4,
|
|
2645
|
-
backgroundColor: "color-mix(in srgb, currentColor
|
|
2646
|
-
boxShadow: "0 0
|
|
2647
|
-
opacity: 0.
|
|
2713
|
+
backgroundColor: "color-mix(in srgb, currentColor 45%, #fff)",
|
|
2714
|
+
boxShadow: "0 0 24px 4px color-mix(in srgb, currentColor 45%, #fff)",
|
|
2715
|
+
opacity: 0.2,
|
|
2648
2716
|
filter: "blur(3px)",
|
|
2649
2717
|
pointerEvents: "none",
|
|
2650
|
-
transition: "top
|
|
2718
|
+
transition: "top 500ms ease-in-out",
|
|
2651
2719
|
zIndex: 1
|
|
2652
2720
|
},
|
|
2653
2721
|
"&:hover": {
|
|
2654
|
-
|
|
2655
|
-
|
|
2656
|
-
|
|
2657
|
-
|
|
2658
|
-
|
|
2659
|
-
|
|
2660
|
-
|
|
2661
|
-
|
|
2722
|
+
// Darken the whole surface via brightness, the same mechanism the
|
|
2723
|
+
// outlined Button uses — no border-color shift; the border stays
|
|
2724
|
+
// put and only the bevel geometry moves. Lighter than the Button's
|
|
2725
|
+
// 0.97 on purpose: the filter dims a card's media and copy along
|
|
2726
|
+
// with its surface, so the same amount reads much heavier here.
|
|
2727
|
+
filter: "brightness(0.995)",
|
|
2728
|
+
// The Button drops its resting shadow on hover (MUI's
|
|
2729
|
+
// disableElevation), so the raised edge is the only depth cue
|
|
2730
|
+
// mid-interaction. Matched here for parity.
|
|
2731
|
+
boxShadow: "none",
|
|
2732
|
+
borderTopWidth: 3,
|
|
2733
|
+
borderBottomWidth: 1
|
|
2662
2734
|
},
|
|
2663
2735
|
"&:hover::before": {
|
|
2664
2736
|
top: "150%"
|
|
@@ -2668,15 +2740,13 @@ function buildComponents(tokens2) {
|
|
|
2668
2740
|
"&:active": {
|
|
2669
2741
|
transition: "border-width 120ms ease, border-radius 120ms ease, opacity 120ms ease",
|
|
2670
2742
|
borderTopWidth: 1,
|
|
2671
|
-
|
|
2672
|
-
borderTopRightRadius: radius4.xl,
|
|
2673
|
-
opacity: 0.85
|
|
2674
|
-
},
|
|
2675
|
-
"&:hover .MuiCardActionArea-focusHighlight": {
|
|
2676
|
-
opacity: 0.04
|
|
2743
|
+
opacity: 0.75
|
|
2677
2744
|
},
|
|
2678
|
-
|
|
2679
|
-
|
|
2745
|
+
// MUI's own hover/focus tint overlay. The outlined Button has no
|
|
2746
|
+
// equivalent (it suppresses the variant hover background), so the
|
|
2747
|
+
// brightness darken above is the only hover feedback.
|
|
2748
|
+
"& .MuiCardActionArea-focusHighlight": {
|
|
2749
|
+
opacity: 0
|
|
2680
2750
|
},
|
|
2681
2751
|
"@media (prefers-reduced-motion: reduce)": {
|
|
2682
2752
|
transition: "none",
|
|
@@ -3434,8 +3504,8 @@ var container = {
|
|
|
3434
3504
|
paddingMobile: 16,
|
|
3435
3505
|
// Corner radius of the App Shell's content surface where it meets the
|
|
3436
3506
|
// chrome. Deliberately a layout value rather than a step on the `radius`
|
|
3437
|
-
// scale: that scale governs components (and the
|
|
3438
|
-
//
|
|
3507
|
+
// scale: that scale governs components (and the alkemy+ preset caps it at
|
|
3508
|
+
// 22), so a 24 sitting in it would misread as a component radius.
|
|
3439
3509
|
shellRadius: 24
|
|
3440
3510
|
};
|
|
3441
3511
|
var widths = {
|
|
@@ -3702,15 +3772,15 @@ var alpha = {
|
|
|
3702
3772
|
var highlight = magenta;
|
|
3703
3773
|
var radius2 = {
|
|
3704
3774
|
...radius,
|
|
3705
|
-
xxs:
|
|
3706
|
-
xs:
|
|
3707
|
-
sm:
|
|
3708
|
-
md:
|
|
3709
|
-
lg:
|
|
3710
|
-
xl:
|
|
3711
|
-
"2xl":
|
|
3712
|
-
"3xl":
|
|
3713
|
-
"4xl":
|
|
3775
|
+
xxs: 2,
|
|
3776
|
+
xs: 4,
|
|
3777
|
+
sm: 6,
|
|
3778
|
+
md: 8,
|
|
3779
|
+
lg: 11,
|
|
3780
|
+
xl: 14,
|
|
3781
|
+
"2xl": 16,
|
|
3782
|
+
"3xl": 20,
|
|
3783
|
+
"4xl": 22
|
|
3714
3784
|
};
|
|
3715
3785
|
var text2 = {
|
|
3716
3786
|
primary: gray[50],
|
|
@@ -4025,15 +4095,15 @@ var colors = {
|
|
|
4025
4095
|
};
|
|
4026
4096
|
var radius3 = {
|
|
4027
4097
|
...radius,
|
|
4028
|
-
xxs:
|
|
4029
|
-
xs:
|
|
4030
|
-
sm:
|
|
4031
|
-
md:
|
|
4032
|
-
lg:
|
|
4033
|
-
xl:
|
|
4034
|
-
"2xl":
|
|
4035
|
-
"3xl":
|
|
4036
|
-
"4xl":
|
|
4098
|
+
xxs: 2,
|
|
4099
|
+
xs: 4,
|
|
4100
|
+
sm: 6,
|
|
4101
|
+
md: 8,
|
|
4102
|
+
lg: 11,
|
|
4103
|
+
xl: 14,
|
|
4104
|
+
"2xl": 16,
|
|
4105
|
+
"3xl": 20,
|
|
4106
|
+
"4xl": 22
|
|
4037
4107
|
};
|
|
4038
4108
|
var text3 = {
|
|
4039
4109
|
primary: gray[900],
|
|
@@ -4367,7 +4437,7 @@ function Button({ variant = "contained", ...props }) {
|
|
|
4367
4437
|
// src/components/ButtonGroup/index.tsx
|
|
4368
4438
|
var import_ButtonGroup = __toESM(require("@mui/material/ButtonGroup"));
|
|
4369
4439
|
var import_jsx_runtime3 = require("react/jsx-runtime");
|
|
4370
|
-
function ButtonGroup({ variant = "
|
|
4440
|
+
function ButtonGroup({ variant = "outlined", ...props }) {
|
|
4371
4441
|
return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_ButtonGroup.default, { variant, ...props });
|
|
4372
4442
|
}
|
|
4373
4443
|
|
|
@@ -5119,15 +5189,28 @@ var Logo = (0, import_react3.forwardRef)(
|
|
|
5119
5189
|
Logo.displayName = "Logo";
|
|
5120
5190
|
|
|
5121
5191
|
// src/components/ToggleButton/index.tsx
|
|
5192
|
+
var import_react4 = require("react");
|
|
5122
5193
|
var import_ToggleButton = __toESM(require("@mui/material/ToggleButton"));
|
|
5123
5194
|
var import_ToggleButtonGroup = __toESM(require("@mui/material/ToggleButtonGroup"));
|
|
5124
5195
|
var import_jsx_runtime10 = require("react/jsx-runtime");
|
|
5196
|
+
var ToggleButtonVariantContext = (0, import_react4.createContext)(
|
|
5197
|
+
void 0
|
|
5198
|
+
);
|
|
5199
|
+
function ToggleButtonGroup({
|
|
5200
|
+
variant = "outlined",
|
|
5201
|
+
...props
|
|
5202
|
+
}) {
|
|
5203
|
+
return /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(ToggleButtonVariantContext.Provider, { value: variant, children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(import_ToggleButtonGroup.default, { ...props }) });
|
|
5204
|
+
}
|
|
5125
5205
|
function ToggleButton({
|
|
5126
|
-
variant
|
|
5206
|
+
variant,
|
|
5127
5207
|
className,
|
|
5128
5208
|
...props
|
|
5129
5209
|
}) {
|
|
5130
|
-
|
|
5210
|
+
var _a;
|
|
5211
|
+
const groupVariant = (0, import_react4.useContext)(ToggleButtonVariantContext);
|
|
5212
|
+
const resolved = (_a = variant != null ? variant : groupVariant) != null ? _a : "outlined";
|
|
5213
|
+
const cls = resolved === "outlined" ? ["ForestToggleButton-outlined", className].filter(Boolean).join(" ") : className;
|
|
5131
5214
|
return /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(import_ToggleButton.default, { className: cls, ...props });
|
|
5132
5215
|
}
|
|
5133
5216
|
|
|
@@ -5360,7 +5443,12 @@ function Card({ color = "primary", sx, ...props }) {
|
|
|
5360
5443
|
{
|
|
5361
5444
|
...props,
|
|
5362
5445
|
sx: [
|
|
5363
|
-
color === "secondary" && {
|
|
5446
|
+
color === "secondary" && {
|
|
5447
|
+
backgroundColor: "background.paper",
|
|
5448
|
+
// Also hand the surface to a wrapped CardActionArea, which paints the
|
|
5449
|
+
// card's background itself (the Card goes transparent around one).
|
|
5450
|
+
"--forest-card-surface": "var(--mui-palette-background-paper)"
|
|
5451
|
+
},
|
|
5364
5452
|
...Array.isArray(sx) ? sx : [sx]
|
|
5365
5453
|
]
|
|
5366
5454
|
}
|
|
@@ -5475,7 +5563,7 @@ var import_Tab = __toESM(require("@mui/material/Tab"));
|
|
|
5475
5563
|
var import_TabScrollButton = __toESM(require("@mui/material/TabScrollButton"));
|
|
5476
5564
|
|
|
5477
5565
|
// src/components/Sidebar/index.tsx
|
|
5478
|
-
var
|
|
5566
|
+
var import_react5 = require("react");
|
|
5479
5567
|
var import_Drawer2 = __toESM(require("@mui/material/Drawer"));
|
|
5480
5568
|
var import_Box = __toESM(require("@mui/material/Box"));
|
|
5481
5569
|
var import_ChevronLeftOutlined = __toESM(require("@mui/icons-material/ChevronLeftOutlined"));
|
|
@@ -5485,14 +5573,15 @@ var import_ListItemIcon2 = __toESM(require("@mui/material/ListItemIcon"));
|
|
|
5485
5573
|
var import_ListItemText3 = __toESM(require("@mui/material/ListItemText"));
|
|
5486
5574
|
var import_Tooltip2 = __toESM(require("@mui/material/Tooltip"));
|
|
5487
5575
|
var import_jsx_runtime18 = require("react/jsx-runtime");
|
|
5488
|
-
var SidebarContext = (0,
|
|
5576
|
+
var SidebarContext = (0, import_react5.createContext)({
|
|
5489
5577
|
open: true,
|
|
5490
5578
|
collapsedWidth: 48,
|
|
5491
5579
|
expandedWidth: 240
|
|
5492
5580
|
});
|
|
5493
5581
|
function useSidebar() {
|
|
5494
|
-
return (0,
|
|
5582
|
+
return (0, import_react5.useContext)(SidebarContext);
|
|
5495
5583
|
}
|
|
5584
|
+
var TOGGLE_SIZE = 28;
|
|
5496
5585
|
function SidebarNav({
|
|
5497
5586
|
open,
|
|
5498
5587
|
onOpenChange,
|
|
@@ -5503,6 +5592,7 @@ function SidebarNav({
|
|
|
5503
5592
|
children,
|
|
5504
5593
|
header,
|
|
5505
5594
|
footer,
|
|
5595
|
+
toggleEdgeAllowance = 12,
|
|
5506
5596
|
sx,
|
|
5507
5597
|
...rest
|
|
5508
5598
|
}) {
|
|
@@ -5510,6 +5600,60 @@ function SidebarNav({
|
|
|
5510
5600
|
const drawerWidth = open ? expandedWidth : collapsedWidth;
|
|
5511
5601
|
const layoutWidth = isHover ? collapsedWidth : drawerWidth;
|
|
5512
5602
|
const shouldShowToggle = showToggle != null ? showToggle : !isHover;
|
|
5603
|
+
const wrapperRef = (0, import_react5.useRef)(null);
|
|
5604
|
+
const toggleRef = (0, import_react5.useRef)(null);
|
|
5605
|
+
const edgeYRef = (0, import_react5.useRef)(null);
|
|
5606
|
+
const [edgeActive, setEdgeActive] = (0, import_react5.useState)(false);
|
|
5607
|
+
const [toggleFocused, setToggleFocused] = (0, import_react5.useState)(false);
|
|
5608
|
+
const writeY = (y) => {
|
|
5609
|
+
edgeYRef.current = y;
|
|
5610
|
+
if (y === null) return;
|
|
5611
|
+
const el = toggleRef.current;
|
|
5612
|
+
if (!el) return;
|
|
5613
|
+
el.style.top = "0px";
|
|
5614
|
+
el.style.transform = `translate3d(50%, ${y - TOGGLE_SIZE / 2}px, 0)`;
|
|
5615
|
+
};
|
|
5616
|
+
const resetY = () => {
|
|
5617
|
+
edgeYRef.current = null;
|
|
5618
|
+
const el = toggleRef.current;
|
|
5619
|
+
if (!el) return;
|
|
5620
|
+
el.style.top = "";
|
|
5621
|
+
el.style.transform = "";
|
|
5622
|
+
};
|
|
5623
|
+
(0, import_react5.useEffect)(() => {
|
|
5624
|
+
if (!shouldShowToggle) return;
|
|
5625
|
+
const onMove = (e) => {
|
|
5626
|
+
const el = wrapperRef.current;
|
|
5627
|
+
if (!el) return;
|
|
5628
|
+
const r = el.getBoundingClientRect();
|
|
5629
|
+
const withinBand = Math.abs(e.clientX - r.right) <= toggleEdgeAllowance && e.clientY >= r.top && e.clientY <= r.bottom;
|
|
5630
|
+
const half = TOGGLE_SIZE / 2;
|
|
5631
|
+
const cur = edgeYRef.current;
|
|
5632
|
+
const overToggle = cur !== null && Math.abs(e.clientX - r.right) <= half && Math.abs(e.clientY - (r.top + cur)) <= half;
|
|
5633
|
+
let next = null;
|
|
5634
|
+
if (withinBand || overToggle) {
|
|
5635
|
+
const max = Math.max(r.height - half, half);
|
|
5636
|
+
next = Math.min(Math.max(e.clientY - r.top, half), max);
|
|
5637
|
+
}
|
|
5638
|
+
const prev = edgeYRef.current;
|
|
5639
|
+
if (prev === next) return;
|
|
5640
|
+
if (prev !== null && next !== null && Math.abs(prev - next) < 0.5) return;
|
|
5641
|
+
writeY(next);
|
|
5642
|
+
if (prev === null !== (next === null)) setEdgeActive(next !== null);
|
|
5643
|
+
};
|
|
5644
|
+
const onLeave = () => {
|
|
5645
|
+
if (edgeYRef.current === null) return;
|
|
5646
|
+
writeY(null);
|
|
5647
|
+
setEdgeActive(false);
|
|
5648
|
+
};
|
|
5649
|
+
window.addEventListener("pointermove", onMove, { passive: true });
|
|
5650
|
+
document.addEventListener("pointerleave", onLeave);
|
|
5651
|
+
return () => {
|
|
5652
|
+
window.removeEventListener("pointermove", onMove);
|
|
5653
|
+
document.removeEventListener("pointerleave", onLeave);
|
|
5654
|
+
};
|
|
5655
|
+
}, [shouldShowToggle, toggleEdgeAllowance]);
|
|
5656
|
+
const toggleVisible = edgeActive || toggleFocused;
|
|
5513
5657
|
const hoverHandlers = isHover ? {
|
|
5514
5658
|
onMouseEnter: () => onOpenChange(true),
|
|
5515
5659
|
onMouseLeave: () => onOpenChange(false)
|
|
@@ -5517,6 +5661,7 @@ function SidebarNav({
|
|
|
5517
5661
|
return /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(SidebarContext.Provider, { value: { open, collapsedWidth, expandedWidth }, children: /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)(
|
|
5518
5662
|
import_Box.default,
|
|
5519
5663
|
{
|
|
5664
|
+
ref: wrapperRef,
|
|
5520
5665
|
sx: {
|
|
5521
5666
|
position: "relative",
|
|
5522
5667
|
width: layoutWidth,
|
|
@@ -5580,50 +5725,94 @@ function SidebarNav({
|
|
|
5580
5725
|
)
|
|
5581
5726
|
}
|
|
5582
5727
|
),
|
|
5583
|
-
shouldShowToggle && //
|
|
5584
|
-
//
|
|
5585
|
-
//
|
|
5586
|
-
//
|
|
5728
|
+
shouldShowToggle && // Positioning shell: pinned to the wrapper's top-right, moved down the
|
|
5729
|
+
// edge with a transform written by the pointermove handler (see
|
|
5730
|
+
// `writeY`). Only opacity transitions — position snaps to the pointer
|
|
5731
|
+
// so the toggle appears under the cursor and tracks it 1:1.
|
|
5587
5732
|
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
|
|
5588
|
-
|
|
5733
|
+
import_Box.default,
|
|
5589
5734
|
{
|
|
5590
|
-
|
|
5591
|
-
onClick: () => onOpenChange(!open),
|
|
5735
|
+
ref: toggleRef,
|
|
5592
5736
|
sx: (theme) => ({
|
|
5593
5737
|
position: "absolute",
|
|
5594
|
-
top: "50%",
|
|
5595
5738
|
right: 0,
|
|
5596
|
-
|
|
5739
|
+
width: TOGGLE_SIZE,
|
|
5740
|
+
height: TOGGLE_SIZE,
|
|
5741
|
+
// Resting spot for keyboard focus and touch, where no pointer
|
|
5742
|
+
// sets a transform: vertically centred on the edge. `writeY`
|
|
5743
|
+
// overrides both `top` and `transform` inline while tracking
|
|
5744
|
+
// and leaves them in place on hide so the exit fades in situ.
|
|
5745
|
+
top: "50%",
|
|
5746
|
+
transform: "translate3d(50%, -50%, 0)",
|
|
5747
|
+
// Hidden until the pointer reaches the edge band. Kept mounted so
|
|
5748
|
+
// it stays in the tab order and can be reached by keyboard.
|
|
5749
|
+
opacity: toggleVisible ? 1 : 0,
|
|
5750
|
+
pointerEvents: toggleVisible ? "auto" : "none",
|
|
5751
|
+
// Enter fast with a strong ease-out so it reads as "already
|
|
5752
|
+
// there"; exit a touch shorter — the user has moved on.
|
|
5753
|
+
transition: toggleVisible ? "opacity 120ms cubic-bezier(0.19, 1, 0.22, 1)" : "opacity 100ms ease",
|
|
5754
|
+
"@media (prefers-reduced-motion: reduce)": {
|
|
5755
|
+
transition: "none"
|
|
5756
|
+
},
|
|
5757
|
+
// No hover on touch: there is no pointer to bring the toggle out,
|
|
5758
|
+
// so it stays visible at its resting position.
|
|
5759
|
+
"@media (hover: none)": {
|
|
5760
|
+
opacity: 1,
|
|
5761
|
+
pointerEvents: "auto"
|
|
5762
|
+
},
|
|
5597
5763
|
// Above both the AppShell content surface (drawer + 1, which
|
|
5598
5764
|
// paints its shadow over the sidebar) and the hover-expanded
|
|
5599
5765
|
// drawer (drawer + 2) — the toggle straddles the seam and has
|
|
5600
5766
|
// to stay clickable and whole on top of both.
|
|
5601
|
-
zIndex: theme.zIndex.drawer + 3
|
|
5602
|
-
minWidth: 0,
|
|
5603
|
-
width: 28,
|
|
5604
|
-
height: 28,
|
|
5605
|
-
padding: 0,
|
|
5606
|
-
// Match the shell surface (bg.primary = lightest grey) so the
|
|
5607
|
-
// toggle reads as part of the sidebar, not a darker chip.
|
|
5608
|
-
backgroundColor: `var(--mui-palette-bg-primary, ${bg.primary})`,
|
|
5609
|
-
color: `var(--mui-palette-text-primary, ${text.primary})`,
|
|
5610
|
-
// Light-grey standard border instead of the contained bevel's
|
|
5611
|
-
// darker greyscale (fg.tertiary) — the toggle is a light utility
|
|
5612
|
-
// control, so the heavier border read too dark.
|
|
5613
|
-
borderColor: `var(--mui-palette-border-primary, ${border.primary})`,
|
|
5614
|
-
"& .MuiSvgIcon-root": {
|
|
5615
|
-
fontSize: 18
|
|
5616
|
-
},
|
|
5617
|
-
"&:hover": {
|
|
5618
|
-
backgroundColor: `var(--mui-palette-bg-quaternary, ${bg.quaternary})`,
|
|
5619
|
-
// The contained brightness lift assumes a dark face — on the
|
|
5620
|
-
// light-grey light-mode face it would blow out. In dark the
|
|
5621
|
-
// hover token matches the face, so a small lift is the cue.
|
|
5622
|
-
filter: "none",
|
|
5623
|
-
...theme.applyStyles("dark", { filter: "brightness(1.15)" })
|
|
5624
|
-
}
|
|
5767
|
+
zIndex: theme.zIndex.drawer + 3
|
|
5625
5768
|
}),
|
|
5626
|
-
children:
|
|
5769
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
|
|
5770
|
+
Button,
|
|
5771
|
+
{
|
|
5772
|
+
"aria-label": open ? "Collapse sidebar" : "Expand sidebar",
|
|
5773
|
+
onClick: (e) => {
|
|
5774
|
+
onOpenChange(!open);
|
|
5775
|
+
writeY(null);
|
|
5776
|
+
setEdgeActive(false);
|
|
5777
|
+
if (!e.currentTarget.matches(":focus-visible")) {
|
|
5778
|
+
e.currentTarget.blur();
|
|
5779
|
+
}
|
|
5780
|
+
},
|
|
5781
|
+
onFocus: (e) => {
|
|
5782
|
+
const kb = e.currentTarget.matches(":focus-visible");
|
|
5783
|
+
if (kb) resetY();
|
|
5784
|
+
setToggleFocused(kb);
|
|
5785
|
+
},
|
|
5786
|
+
onBlur: () => setToggleFocused(false),
|
|
5787
|
+
sx: (theme) => ({
|
|
5788
|
+
minWidth: 0,
|
|
5789
|
+
width: TOGGLE_SIZE,
|
|
5790
|
+
height: TOGGLE_SIZE,
|
|
5791
|
+
padding: 0,
|
|
5792
|
+
transition: "background-color 300ms ease",
|
|
5793
|
+
// Match the shell surface (bg.primary = lightest grey) so the
|
|
5794
|
+
// toggle reads as part of the sidebar, not a darker chip.
|
|
5795
|
+
backgroundColor: `var(--mui-palette-bg-primary, ${bg.primary})`,
|
|
5796
|
+
color: `var(--mui-palette-text-primary, ${text.primary})`,
|
|
5797
|
+
// Light-grey standard border instead of the contained bevel's
|
|
5798
|
+
// darker greyscale (fg.tertiary) — the toggle is a light
|
|
5799
|
+
// utility control, so the heavier border read too dark.
|
|
5800
|
+
borderColor: `var(--mui-palette-border-primary, ${border.primary})`,
|
|
5801
|
+
"& .MuiSvgIcon-root": {
|
|
5802
|
+
fontSize: 18
|
|
5803
|
+
},
|
|
5804
|
+
"&:hover": {
|
|
5805
|
+
backgroundColor: `var(--mui-palette-bg-quaternary, ${bg.quaternary})`,
|
|
5806
|
+
// The contained brightness lift assumes a dark face — on the
|
|
5807
|
+
// light-grey light-mode face it would blow out. In dark the
|
|
5808
|
+
// hover token matches the face, so a small lift is the cue.
|
|
5809
|
+
filter: "none",
|
|
5810
|
+
...theme.applyStyles("dark", { filter: "brightness(1.15)" })
|
|
5811
|
+
}
|
|
5812
|
+
}),
|
|
5813
|
+
children: open ? /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(import_ChevronLeftOutlined.default, {}) : /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(import_ChevronRightOutlined.default, {})
|
|
5814
|
+
}
|
|
5815
|
+
)
|
|
5627
5816
|
}
|
|
5628
5817
|
)
|
|
5629
5818
|
]
|
|
@@ -5631,8 +5820,9 @@ function SidebarNav({
|
|
|
5631
5820
|
) });
|
|
5632
5821
|
}
|
|
5633
5822
|
var itemSx = {
|
|
5634
|
-
//
|
|
5635
|
-
|
|
5823
|
+
// Off-scale on purpose: the alkemy+ preset's radius steps run 1→12, so 11px
|
|
5824
|
+
// sits between "3xl" (10) and "4xl" (12) with no token to name it.
|
|
5825
|
+
borderRadius: "11px",
|
|
5636
5826
|
// The MuiListItemButton override sets 12px; 8px here absorbs the container's
|
|
5637
5827
|
// new 8px gutter so the icon column stays exactly 16px from the sidebar edge,
|
|
5638
5828
|
// where it has always been.
|
|
@@ -5698,7 +5888,7 @@ function SidebarItem({
|
|
|
5698
5888
|
}
|
|
5699
5889
|
|
|
5700
5890
|
// src/components/AppShell/index.tsx
|
|
5701
|
-
var
|
|
5891
|
+
var import_react6 = require("react");
|
|
5702
5892
|
var import_Box2 = __toESM(require("@mui/material/Box"));
|
|
5703
5893
|
var import_Drawer3 = __toESM(require("@mui/material/Drawer"));
|
|
5704
5894
|
var import_List2 = __toESM(require("@mui/material/List"));
|
|
@@ -5749,8 +5939,8 @@ function AppShell({
|
|
|
5749
5939
|
}) {
|
|
5750
5940
|
const theme = (0, import_styles4.useTheme)();
|
|
5751
5941
|
const isMobile = (0, import_useMediaQuery.default)(theme.breakpoints.down("sm"));
|
|
5752
|
-
const [sidebarOpen, setSidebarOpen] = (0,
|
|
5753
|
-
const [mobileOpen, setMobileOpen] = (0,
|
|
5942
|
+
const [sidebarOpen, setSidebarOpen] = (0, import_react6.useState)(defaultSidebarOpen);
|
|
5943
|
+
const [mobileOpen, setMobileOpen] = (0, import_react6.useState)(false);
|
|
5754
5944
|
const navContent = nav != null ? nav : navItems && /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(import_List2.default, { children: navItems.map(({ label, icon, active, endAdornment, ...link }) => /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
|
|
5755
5945
|
SidebarItem,
|
|
5756
5946
|
{
|