pinokiod 7.3.9 → 7.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 +1 -1
- package/server/public/common.js +7 -17
- package/server/public/nav.js +3 -1
- package/server/public/style.css +23 -10
- package/server/public/task-launcher.css +94 -40
- package/server/public/terminal-settings.js +106 -5
- package/server/views/app.ejs +125 -46
- package/server/views/index.ejs +12 -7
- package/server/views/install.ejs +15 -46
- package/server/views/logs.ejs +1 -1
- package/server/views/partials/main_sidebar.ejs +12 -12
- package/server/views/terminal.ejs +143 -59
package/package.json
CHANGED
package/server/public/common.js
CHANGED
|
@@ -2886,7 +2886,10 @@ const compactLayoutMedia = window.matchMedia(COMPACT_LAYOUT_QUERY);
|
|
|
2886
2886
|
|
|
2887
2887
|
function initTippy() {
|
|
2888
2888
|
try {
|
|
2889
|
-
|
|
2889
|
+
const targets = Array.from(document.querySelectorAll("[data-tippy-content]")).filter((target) => {
|
|
2890
|
+
return !target.closest('aside');
|
|
2891
|
+
});
|
|
2892
|
+
tippyInstances = tippy(targets, {
|
|
2890
2893
|
theme: "pointer",
|
|
2891
2894
|
onCreate(instance) {
|
|
2892
2895
|
updateTippyPlacement(instance);
|
|
@@ -2898,13 +2901,9 @@ function initTippy() {
|
|
|
2898
2901
|
|
|
2899
2902
|
function updateTippyPlacement(instance) {
|
|
2900
2903
|
const isCompact = compactLayoutMedia.matches;
|
|
2901
|
-
const isHeaderElement = instance.reference.closest('header.navheader');
|
|
2902
|
-
const isSidebarTab = instance.reference.closest('aside') && instance.reference.classList.contains('tab');
|
|
2903
2904
|
|
|
2904
2905
|
if (isCompact) {
|
|
2905
2906
|
instance.setProps({ placement: 'right' });
|
|
2906
|
-
} else if (isSidebarTab) {
|
|
2907
|
-
instance.setProps({ placement: 'left' });
|
|
2908
2907
|
} else {
|
|
2909
2908
|
instance.setProps({ placement: 'top' });
|
|
2910
2909
|
}
|
|
@@ -2914,17 +2913,6 @@ function updateAllTooltips() {
|
|
|
2914
2913
|
tippyInstances.forEach(updateTippyPlacement);
|
|
2915
2914
|
}
|
|
2916
2915
|
|
|
2917
|
-
function setTabTooltips() {
|
|
2918
|
-
// Set data-tippy-content for sidebar tabs based on their .caption text
|
|
2919
|
-
const tabs = document.querySelectorAll('aside .tab');
|
|
2920
|
-
tabs.forEach(tab => {
|
|
2921
|
-
const caption = tab.querySelector('.caption');
|
|
2922
|
-
if (caption && caption.textContent.trim()) {
|
|
2923
|
-
tab.setAttribute('data-tippy-content', caption.textContent.trim());
|
|
2924
|
-
}
|
|
2925
|
-
});
|
|
2926
|
-
}
|
|
2927
|
-
|
|
2928
2916
|
document.addEventListener("DOMContentLoaded", () => {
|
|
2929
2917
|
if (typeof initUrlDropdown === 'function' && !window.PinokioUrlDropdown) {
|
|
2930
2918
|
try {
|
|
@@ -3019,7 +3007,6 @@ document.addEventListener("DOMContentLoaded", () => {
|
|
|
3019
3007
|
return null;
|
|
3020
3008
|
};
|
|
3021
3009
|
|
|
3022
|
-
setTabTooltips();
|
|
3023
3010
|
initTippy();
|
|
3024
3011
|
|
|
3025
3012
|
// if (window !== window.top) {
|
|
@@ -3240,11 +3227,14 @@ document.addEventListener("DOMContentLoaded", () => {
|
|
|
3240
3227
|
})
|
|
3241
3228
|
}
|
|
3242
3229
|
|
|
3230
|
+
/*
|
|
3231
|
+
// Screen capture toolbar handling is disabled while the button is hidden.
|
|
3243
3232
|
if (document.querySelector("#screenshot")) {
|
|
3244
3233
|
document.querySelector("#screenshot").addEventListener("click", (e) => {
|
|
3245
3234
|
screenshot()
|
|
3246
3235
|
})
|
|
3247
3236
|
}
|
|
3237
|
+
*/
|
|
3248
3238
|
bindHistoryButton("#back", -1)
|
|
3249
3239
|
bindHistoryButton("#forward", 1)
|
|
3250
3240
|
if (document.querySelector("#refresh-page")) {
|
package/server/public/nav.js
CHANGED
|
@@ -500,7 +500,8 @@ document.addEventListener("DOMContentLoaded", () => {
|
|
|
500
500
|
|
|
501
501
|
}
|
|
502
502
|
|
|
503
|
-
|
|
503
|
+
/*
|
|
504
|
+
// Inspector handling is disabled while the X-ray toolbar button is hidden.
|
|
504
505
|
const inspectorButton = document.querySelector('#inspector');
|
|
505
506
|
const isDesktop = agent === 'electron';
|
|
506
507
|
|
|
@@ -600,6 +601,7 @@ document.addEventListener("DOMContentLoaded", () => {
|
|
|
600
601
|
}
|
|
601
602
|
}, true);
|
|
602
603
|
}
|
|
604
|
+
*/
|
|
603
605
|
|
|
604
606
|
|
|
605
607
|
});
|
package/server/public/style.css
CHANGED
|
@@ -1348,16 +1348,16 @@ body.main-sidebar-page main > :not(.main-sidebar) {
|
|
|
1348
1348
|
body.main-sidebar-page main > .container,
|
|
1349
1349
|
body.main-sidebar-page main > .task-container {
|
|
1350
1350
|
box-sizing: border-box;
|
|
1351
|
-
padding-left:
|
|
1351
|
+
padding-left: 12px;
|
|
1352
1352
|
}
|
|
1353
1353
|
.main-sidebar {
|
|
1354
1354
|
order: -1;
|
|
1355
|
-
width:
|
|
1355
|
+
width: 180px;
|
|
1356
1356
|
display: flex;
|
|
1357
1357
|
flex-direction: column;
|
|
1358
1358
|
flex-shrink: 0;
|
|
1359
1359
|
min-height: 0;
|
|
1360
|
-
padding: 8px
|
|
1360
|
+
padding: 8px 5px;
|
|
1361
1361
|
box-sizing: border-box;
|
|
1362
1362
|
background: transparent;
|
|
1363
1363
|
color: var(--pinokio-sidebar-tab-muted);
|
|
@@ -1399,7 +1399,7 @@ body.main-sidebar-page main > .task-container {
|
|
|
1399
1399
|
display: flex;
|
|
1400
1400
|
align-items: flex-end;
|
|
1401
1401
|
box-sizing: border-box;
|
|
1402
|
-
padding: 5px
|
|
1402
|
+
padding: 5px 5px 4px;
|
|
1403
1403
|
color: var(--pinokio-sidebar-action-muted);
|
|
1404
1404
|
font-size: 11px;
|
|
1405
1405
|
font-weight: 500;
|
|
@@ -1415,9 +1415,9 @@ body.main-sidebar-page main > .task-container {
|
|
|
1415
1415
|
display: grid !important;
|
|
1416
1416
|
grid-template-columns: 16px minmax(0, 1fr) auto;
|
|
1417
1417
|
align-items: center !important;
|
|
1418
|
-
column-gap:
|
|
1418
|
+
column-gap: 6px !important;
|
|
1419
1419
|
margin: 0;
|
|
1420
|
-
padding: 3px
|
|
1420
|
+
padding: 3px 5px !important;
|
|
1421
1421
|
box-sizing: border-box;
|
|
1422
1422
|
border: 0 !important;
|
|
1423
1423
|
border-left: 0 !important;
|
|
@@ -1445,6 +1445,11 @@ body.main-sidebar-page main > .task-container {
|
|
|
1445
1445
|
color: var(--pinokio-sidebar-tab-active-color) !important;
|
|
1446
1446
|
font-weight: 600 !important;
|
|
1447
1447
|
}
|
|
1448
|
+
body.main-sidebar-page aside.main-sidebar .tab:hover,
|
|
1449
|
+
body.main-sidebar-page aside.main-sidebar .tab:focus-visible,
|
|
1450
|
+
body.main-sidebar-page aside.main-sidebar .tab.selected {
|
|
1451
|
+
color: var(--pinokio-sidebar-tab-active-color) !important;
|
|
1452
|
+
}
|
|
1448
1453
|
.main-sidebar .tab i,
|
|
1449
1454
|
.main-sidebar .tab .main-sidebar-action-icon {
|
|
1450
1455
|
grid-column: 1;
|
|
@@ -1467,7 +1472,15 @@ body.main-sidebar-page main > .task-container {
|
|
|
1467
1472
|
.main-sidebar .tab.selected .main-sidebar-action-icon {
|
|
1468
1473
|
color: var(--pinokio-sidebar-icon-active) !important;
|
|
1469
1474
|
}
|
|
1470
|
-
.main-sidebar .
|
|
1475
|
+
body.main-sidebar-page aside.main-sidebar .tab:hover i,
|
|
1476
|
+
body.main-sidebar-page aside.main-sidebar .tab:focus-visible i,
|
|
1477
|
+
body.main-sidebar-page aside.main-sidebar .tab.selected i,
|
|
1478
|
+
body.main-sidebar-page aside.main-sidebar .tab:hover .main-sidebar-action-icon,
|
|
1479
|
+
body.main-sidebar-page aside.main-sidebar .tab:focus-visible .main-sidebar-action-icon,
|
|
1480
|
+
body.main-sidebar-page aside.main-sidebar .tab.selected .main-sidebar-action-icon {
|
|
1481
|
+
color: var(--pinokio-sidebar-icon-active) !important;
|
|
1482
|
+
}
|
|
1483
|
+
.main-sidebar .tab .caption {
|
|
1471
1484
|
grid-column: 2;
|
|
1472
1485
|
min-width: 0;
|
|
1473
1486
|
width: auto !important;
|
|
@@ -1479,7 +1492,7 @@ body.main-sidebar-page main > .task-container {
|
|
|
1479
1492
|
word-wrap: normal !important;
|
|
1480
1493
|
}
|
|
1481
1494
|
.main-sidebar .tab.submenu {
|
|
1482
|
-
padding-left:
|
|
1495
|
+
padding-left: 14px !important;
|
|
1483
1496
|
}
|
|
1484
1497
|
.main-sidebar .universal-create-menu {
|
|
1485
1498
|
width: 100%;
|
|
@@ -1947,7 +1960,7 @@ header .runner.terminal-runner-minimal .btn span {
|
|
|
1947
1960
|
margin-left: auto;
|
|
1948
1961
|
display: flex;
|
|
1949
1962
|
align-items: center;
|
|
1950
|
-
gap:
|
|
1963
|
+
gap: 6px;
|
|
1951
1964
|
flex-wrap: wrap;
|
|
1952
1965
|
justify-content: flex-end;
|
|
1953
1966
|
min-width: 0;
|
|
@@ -3940,7 +3953,7 @@ aside .qr {
|
|
|
3940
3953
|
font-size: 12px;
|
|
3941
3954
|
}
|
|
3942
3955
|
|
|
3943
|
-
body.main-sidebar-page .main-sidebar .caption {
|
|
3956
|
+
body.main-sidebar-page .main-sidebar .tab .caption {
|
|
3944
3957
|
width: auto !important;
|
|
3945
3958
|
text-align: left !important;
|
|
3946
3959
|
word-wrap: normal !important;
|
|
@@ -1628,15 +1628,51 @@ body.dark .task-link-button.danger {
|
|
|
1628
1628
|
}
|
|
1629
1629
|
|
|
1630
1630
|
.setup-shell {
|
|
1631
|
-
width: min(
|
|
1631
|
+
width: min(1080px, 100%);
|
|
1632
|
+
}
|
|
1633
|
+
|
|
1634
|
+
body.setup-page .task-shell-header {
|
|
1635
|
+
padding-bottom: 16px;
|
|
1636
|
+
}
|
|
1637
|
+
|
|
1638
|
+
body.setup-page .task-shell-header-main {
|
|
1639
|
+
max-width: 820px;
|
|
1640
|
+
}
|
|
1641
|
+
|
|
1642
|
+
body.setup-page .task-eyebrow {
|
|
1643
|
+
color: var(--task-muted);
|
|
1644
|
+
letter-spacing: 0;
|
|
1645
|
+
}
|
|
1646
|
+
|
|
1647
|
+
body.setup-page .task-title {
|
|
1648
|
+
font-size: clamp(24px, 2.4vw, 30px);
|
|
1649
|
+
line-height: 1.1;
|
|
1650
|
+
letter-spacing: 0;
|
|
1651
|
+
}
|
|
1652
|
+
|
|
1653
|
+
body.setup-page .task-description {
|
|
1654
|
+
max-width: 76ch;
|
|
1655
|
+
font-size: 13px;
|
|
1656
|
+
line-height: 1.5;
|
|
1657
|
+
}
|
|
1658
|
+
|
|
1659
|
+
body.setup-page .task-badge {
|
|
1660
|
+
min-height: 22px;
|
|
1661
|
+
border-radius: 7px;
|
|
1662
|
+
}
|
|
1663
|
+
|
|
1664
|
+
body.setup-page .task-badge-warning {
|
|
1665
|
+
border-color: color-mix(in srgb, var(--task-accent) 20%, var(--task-border));
|
|
1666
|
+
background: color-mix(in srgb, var(--task-accent) 7%, var(--task-panel));
|
|
1667
|
+
color: color-mix(in srgb, var(--task-accent) 58%, var(--task-text));
|
|
1632
1668
|
}
|
|
1633
1669
|
|
|
1634
1670
|
.setup-layout {
|
|
1635
1671
|
display: grid;
|
|
1636
|
-
grid-template-columns: minmax(0, 1fr)
|
|
1637
|
-
gap:
|
|
1672
|
+
grid-template-columns: minmax(0, 1fr) 300px;
|
|
1673
|
+
gap: 32px;
|
|
1638
1674
|
align-items: start;
|
|
1639
|
-
padding-top:
|
|
1675
|
+
padding-top: 16px;
|
|
1640
1676
|
}
|
|
1641
1677
|
|
|
1642
1678
|
.setup-requirements-section {
|
|
@@ -1646,23 +1682,23 @@ body.dark .task-link-button.danger {
|
|
|
1646
1682
|
|
|
1647
1683
|
.setup-requirement-list {
|
|
1648
1684
|
display: grid;
|
|
1649
|
-
gap:
|
|
1685
|
+
gap: 8px;
|
|
1650
1686
|
}
|
|
1651
1687
|
|
|
1652
1688
|
.setup-requirement-row {
|
|
1653
1689
|
display: grid;
|
|
1654
1690
|
grid-template-columns: minmax(0, 1fr) auto;
|
|
1655
|
-
gap:
|
|
1691
|
+
gap: 14px;
|
|
1656
1692
|
align-items: center;
|
|
1657
|
-
padding:
|
|
1693
|
+
padding: 11px 12px;
|
|
1658
1694
|
border: 1px solid var(--task-border);
|
|
1659
|
-
border-radius:
|
|
1660
|
-
background: color-mix(in srgb, var(--task-panel)
|
|
1695
|
+
border-radius: 8px;
|
|
1696
|
+
background: color-mix(in srgb, var(--task-panel) 97%, var(--task-soft));
|
|
1661
1697
|
}
|
|
1662
1698
|
|
|
1663
1699
|
.setup-requirement-row.needs-update {
|
|
1664
|
-
border-color:
|
|
1665
|
-
background: color-mix(in srgb, var(--task-
|
|
1700
|
+
border-color: var(--task-border-strong);
|
|
1701
|
+
background: color-mix(in srgb, var(--task-panel) 95%, var(--task-soft));
|
|
1666
1702
|
}
|
|
1667
1703
|
|
|
1668
1704
|
.setup-requirement-copy {
|
|
@@ -1670,17 +1706,17 @@ body.dark .task-link-button.danger {
|
|
|
1670
1706
|
}
|
|
1671
1707
|
|
|
1672
1708
|
.setup-requirement-name {
|
|
1673
|
-
font-size:
|
|
1709
|
+
font-size: 13px;
|
|
1674
1710
|
font-weight: 700;
|
|
1675
|
-
letter-spacing:
|
|
1711
|
+
letter-spacing: 0;
|
|
1676
1712
|
color: var(--task-text);
|
|
1677
1713
|
word-break: break-word;
|
|
1678
1714
|
}
|
|
1679
1715
|
|
|
1680
1716
|
.setup-requirement-detail {
|
|
1681
|
-
margin-top:
|
|
1717
|
+
margin-top: 3px;
|
|
1682
1718
|
color: var(--task-muted);
|
|
1683
|
-
font-size:
|
|
1719
|
+
font-size: 11px;
|
|
1684
1720
|
line-height: 1.45;
|
|
1685
1721
|
}
|
|
1686
1722
|
|
|
@@ -1688,50 +1724,63 @@ body.dark .task-link-button.danger {
|
|
|
1688
1724
|
display: inline-flex;
|
|
1689
1725
|
align-items: center;
|
|
1690
1726
|
justify-content: center;
|
|
1691
|
-
gap:
|
|
1692
|
-
min-height:
|
|
1693
|
-
padding: 0
|
|
1727
|
+
gap: 6px;
|
|
1728
|
+
min-height: 26px;
|
|
1729
|
+
padding: 0 9px;
|
|
1694
1730
|
border: 1px solid var(--task-border);
|
|
1695
|
-
border-radius:
|
|
1696
|
-
background:
|
|
1731
|
+
border-radius: 7px;
|
|
1732
|
+
background: transparent;
|
|
1697
1733
|
color: var(--task-muted);
|
|
1698
|
-
font-size:
|
|
1734
|
+
font-size: 10px;
|
|
1699
1735
|
font-weight: 700;
|
|
1700
1736
|
letter-spacing: 0.01em;
|
|
1701
1737
|
white-space: nowrap;
|
|
1702
1738
|
}
|
|
1703
1739
|
|
|
1740
|
+
.setup-requirement-state i {
|
|
1741
|
+
font-size: 10px;
|
|
1742
|
+
}
|
|
1743
|
+
|
|
1704
1744
|
.setup-requirement-row.is-installed .setup-requirement-state {
|
|
1745
|
+
border-color: color-mix(in srgb, var(--task-border) 72%, transparent);
|
|
1705
1746
|
color: var(--task-text);
|
|
1706
1747
|
}
|
|
1707
1748
|
|
|
1708
1749
|
.setup-requirement-row.needs-update .setup-requirement-state {
|
|
1709
|
-
border-color: color-mix(in srgb, var(--task-accent)
|
|
1710
|
-
background: color-mix(in srgb, var(--task-accent)
|
|
1711
|
-
color: color-mix(in srgb, var(--task-accent)
|
|
1750
|
+
border-color: color-mix(in srgb, var(--task-accent) 22%, var(--task-border-strong));
|
|
1751
|
+
background: color-mix(in srgb, var(--task-accent) 6%, var(--task-panel));
|
|
1752
|
+
color: color-mix(in srgb, var(--task-accent) 56%, var(--task-text));
|
|
1712
1753
|
}
|
|
1713
1754
|
|
|
1714
1755
|
.setup-actions-column {
|
|
1715
1756
|
position: sticky;
|
|
1716
|
-
top:
|
|
1757
|
+
top: 20px;
|
|
1717
1758
|
align-self: start;
|
|
1759
|
+
padding-left: 24px;
|
|
1760
|
+
border-left: 1px solid var(--task-border);
|
|
1718
1761
|
}
|
|
1719
1762
|
|
|
1720
1763
|
.setup-action-card {
|
|
1721
1764
|
margin: 0;
|
|
1722
|
-
padding:
|
|
1765
|
+
padding: 0;
|
|
1723
1766
|
border-top: 0;
|
|
1724
1767
|
}
|
|
1725
1768
|
|
|
1726
1769
|
.setup-summary-grid {
|
|
1727
|
-
margin-top:
|
|
1770
|
+
margin-top: 4px;
|
|
1771
|
+
}
|
|
1772
|
+
|
|
1773
|
+
.setup-summary-grid .task-meta-chip {
|
|
1774
|
+
border-radius: 8px;
|
|
1775
|
+
background: color-mix(in srgb, var(--task-panel) 96%, var(--task-soft));
|
|
1728
1776
|
}
|
|
1729
1777
|
|
|
1730
1778
|
.setup-primary-button {
|
|
1731
1779
|
width: 100%;
|
|
1732
1780
|
min-height: 40px;
|
|
1733
|
-
margin-top:
|
|
1781
|
+
margin-top: 16px;
|
|
1734
1782
|
font-size: 12px;
|
|
1783
|
+
border-radius: 8px;
|
|
1735
1784
|
}
|
|
1736
1785
|
|
|
1737
1786
|
.setup-install-form {
|
|
@@ -1740,9 +1789,9 @@ body.dark .task-link-button.danger {
|
|
|
1740
1789
|
|
|
1741
1790
|
.setup-secondary-actions {
|
|
1742
1791
|
display: grid;
|
|
1743
|
-
gap:
|
|
1744
|
-
padding-top:
|
|
1745
|
-
margin-top:
|
|
1792
|
+
gap: 8px;
|
|
1793
|
+
padding-top: 14px;
|
|
1794
|
+
margin-top: 14px;
|
|
1746
1795
|
border-top: 1px solid var(--task-border);
|
|
1747
1796
|
}
|
|
1748
1797
|
|
|
@@ -1752,6 +1801,9 @@ body.dark .task-link-button.danger {
|
|
|
1752
1801
|
|
|
1753
1802
|
.setup-secondary-actions .task-button {
|
|
1754
1803
|
justify-content: flex-start;
|
|
1804
|
+
min-height: 30px;
|
|
1805
|
+
border-radius: 7px;
|
|
1806
|
+
color: var(--task-muted);
|
|
1755
1807
|
}
|
|
1756
1808
|
|
|
1757
1809
|
.setup-reset-loading {
|
|
@@ -1782,26 +1834,26 @@ body.dark .task-link-button.danger {
|
|
|
1782
1834
|
width: min(480px, 100%);
|
|
1783
1835
|
display: flex;
|
|
1784
1836
|
align-items: center;
|
|
1785
|
-
gap:
|
|
1786
|
-
padding:
|
|
1837
|
+
gap: 14px;
|
|
1838
|
+
padding: 16px;
|
|
1787
1839
|
border: 1px solid var(--task-border);
|
|
1788
|
-
border-radius:
|
|
1789
|
-
background: color-mix(in srgb, var(--task-panel)
|
|
1840
|
+
border-radius: 10px;
|
|
1841
|
+
background: color-mix(in srgb, var(--task-panel) 96%, var(--task-soft));
|
|
1790
1842
|
box-sizing: border-box;
|
|
1791
1843
|
}
|
|
1792
1844
|
|
|
1793
1845
|
.setup-loading-icon {
|
|
1794
|
-
width:
|
|
1795
|
-
height:
|
|
1846
|
+
width: 36px;
|
|
1847
|
+
height: 36px;
|
|
1796
1848
|
flex: 0 0 auto;
|
|
1797
1849
|
display: inline-flex;
|
|
1798
1850
|
align-items: center;
|
|
1799
1851
|
justify-content: center;
|
|
1800
1852
|
border: 1px solid var(--task-border);
|
|
1801
|
-
border-radius:
|
|
1802
|
-
background: color-mix(in srgb, var(--task-panel)
|
|
1853
|
+
border-radius: 8px;
|
|
1854
|
+
background: color-mix(in srgb, var(--task-panel) 96%, var(--task-soft));
|
|
1803
1855
|
color: var(--task-accent);
|
|
1804
|
-
font-size:
|
|
1856
|
+
font-size: 14px;
|
|
1805
1857
|
}
|
|
1806
1858
|
|
|
1807
1859
|
.setup-loading-copy {
|
|
@@ -3049,6 +3101,8 @@ body.dark .plugin-option .option-icon {
|
|
|
3049
3101
|
top: 12px;
|
|
3050
3102
|
order: -1;
|
|
3051
3103
|
z-index: 2;
|
|
3104
|
+
padding-left: 0;
|
|
3105
|
+
border-left: 0;
|
|
3052
3106
|
}
|
|
3053
3107
|
|
|
3054
3108
|
.setup-action-card {
|
|
@@ -730,6 +730,9 @@
|
|
|
730
730
|
: null;
|
|
731
731
|
this.forceResizeButtons = new WeakMap();
|
|
732
732
|
this.forceResizeHandler = null;
|
|
733
|
+
this.tooltipElement = null;
|
|
734
|
+
this.activeTooltipTarget = null;
|
|
735
|
+
this.boundTooltipReposition = () => this.positionTerminalTooltip();
|
|
733
736
|
this.minimalRunnerMode = detectMinimalRunnerMode();
|
|
734
737
|
this.currentFontFamily = typeof this.preferences.fontFamily === 'string' ? this.preferences.fontFamily.trim() : '';
|
|
735
738
|
if (typeof document !== 'undefined') {
|
|
@@ -1287,15 +1290,111 @@
|
|
|
1287
1290
|
return false;
|
|
1288
1291
|
}
|
|
1289
1292
|
|
|
1293
|
+
getTerminalTooltipElement() {
|
|
1294
|
+
if (typeof document === 'undefined' || !document.body) {
|
|
1295
|
+
return null;
|
|
1296
|
+
}
|
|
1297
|
+
if (this.tooltipElement && document.body.contains(this.tooltipElement)) {
|
|
1298
|
+
return this.tooltipElement;
|
|
1299
|
+
}
|
|
1300
|
+
const tooltip = document.createElement('div');
|
|
1301
|
+
tooltip.className = 'terminal-tooltip';
|
|
1302
|
+
tooltip.setAttribute('role', 'tooltip');
|
|
1303
|
+
tooltip.setAttribute('aria-hidden', 'true');
|
|
1304
|
+
document.body.appendChild(tooltip);
|
|
1305
|
+
this.tooltipElement = tooltip;
|
|
1306
|
+
return tooltip;
|
|
1307
|
+
}
|
|
1308
|
+
|
|
1309
|
+
attachTerminalTooltip(target, text) {
|
|
1310
|
+
if (!target || typeof text !== 'string' || !text.trim()) {
|
|
1311
|
+
return;
|
|
1312
|
+
}
|
|
1313
|
+
target.setAttribute('data-terminal-tooltip', text);
|
|
1314
|
+
target.addEventListener('mouseenter', () => this.showTerminalTooltip(target));
|
|
1315
|
+
target.addEventListener('focus', () => this.showTerminalTooltip(target));
|
|
1316
|
+
target.addEventListener('mouseleave', () => this.hideTerminalTooltip(target));
|
|
1317
|
+
target.addEventListener('blur', () => this.hideTerminalTooltip(target));
|
|
1318
|
+
target.addEventListener('click', () => this.hideTerminalTooltip(target));
|
|
1319
|
+
target.addEventListener('keydown', (event) => {
|
|
1320
|
+
if (event && event.key === 'Escape') {
|
|
1321
|
+
this.hideTerminalTooltip(target);
|
|
1322
|
+
}
|
|
1323
|
+
});
|
|
1324
|
+
}
|
|
1325
|
+
|
|
1326
|
+
showTerminalTooltip(target) {
|
|
1327
|
+
if (typeof window === 'undefined' || !target) {
|
|
1328
|
+
return;
|
|
1329
|
+
}
|
|
1330
|
+
const text = target.getAttribute('data-terminal-tooltip') || '';
|
|
1331
|
+
if (!text.trim()) {
|
|
1332
|
+
return;
|
|
1333
|
+
}
|
|
1334
|
+
const tooltip = this.getTerminalTooltipElement();
|
|
1335
|
+
if (!tooltip) {
|
|
1336
|
+
return;
|
|
1337
|
+
}
|
|
1338
|
+
this.activeTooltipTarget = target;
|
|
1339
|
+
tooltip.textContent = text;
|
|
1340
|
+
tooltip.setAttribute('aria-hidden', 'false');
|
|
1341
|
+
tooltip.classList.remove('is-visible');
|
|
1342
|
+
this.positionTerminalTooltip();
|
|
1343
|
+
tooltip.classList.add('is-visible');
|
|
1344
|
+
window.addEventListener('resize', this.boundTooltipReposition);
|
|
1345
|
+
window.addEventListener('scroll', this.boundTooltipReposition, true);
|
|
1346
|
+
}
|
|
1347
|
+
|
|
1348
|
+
hideTerminalTooltip(target) {
|
|
1349
|
+
if (target && this.activeTooltipTarget && target !== this.activeTooltipTarget) {
|
|
1350
|
+
return;
|
|
1351
|
+
}
|
|
1352
|
+
if (typeof window !== 'undefined') {
|
|
1353
|
+
window.removeEventListener('resize', this.boundTooltipReposition);
|
|
1354
|
+
window.removeEventListener('scroll', this.boundTooltipReposition, true);
|
|
1355
|
+
}
|
|
1356
|
+
this.activeTooltipTarget = null;
|
|
1357
|
+
if (this.tooltipElement) {
|
|
1358
|
+
this.tooltipElement.classList.remove('is-visible');
|
|
1359
|
+
this.tooltipElement.setAttribute('aria-hidden', 'true');
|
|
1360
|
+
}
|
|
1361
|
+
}
|
|
1362
|
+
|
|
1363
|
+
positionTerminalTooltip() {
|
|
1364
|
+
if (typeof window === 'undefined' || !this.activeTooltipTarget || !this.tooltipElement) {
|
|
1365
|
+
return;
|
|
1366
|
+
}
|
|
1367
|
+
const targetRect = this.activeTooltipTarget.getBoundingClientRect();
|
|
1368
|
+
const tooltipRect = this.tooltipElement.getBoundingClientRect();
|
|
1369
|
+
const viewportWidth = window.innerWidth || document.documentElement.clientWidth || 0;
|
|
1370
|
+
const viewportHeight = window.innerHeight || document.documentElement.clientHeight || 0;
|
|
1371
|
+
const margin = 8;
|
|
1372
|
+
const gap = 8;
|
|
1373
|
+
const tooltipWidth = tooltipRect.width || this.tooltipElement.offsetWidth || 0;
|
|
1374
|
+
const tooltipHeight = tooltipRect.height || this.tooltipElement.offsetHeight || 0;
|
|
1375
|
+
let left = targetRect.right - tooltipWidth;
|
|
1376
|
+
let top = targetRect.bottom + gap;
|
|
1377
|
+
|
|
1378
|
+
if (top + tooltipHeight + margin > viewportHeight && targetRect.top - tooltipHeight - gap >= margin) {
|
|
1379
|
+
top = targetRect.top - tooltipHeight - gap;
|
|
1380
|
+
}
|
|
1381
|
+
left = Math.max(margin, Math.min(left, viewportWidth - tooltipWidth - margin));
|
|
1382
|
+
top = Math.max(margin, Math.min(top, viewportHeight - tooltipHeight - margin));
|
|
1383
|
+
|
|
1384
|
+
this.tooltipElement.style.left = `${Math.round(left)}px`;
|
|
1385
|
+
this.tooltipElement.style.top = `${Math.round(top)}px`;
|
|
1386
|
+
}
|
|
1387
|
+
|
|
1290
1388
|
attachForceResizeButton(runner, host) {
|
|
1291
1389
|
if (typeof document === 'undefined' || !runner || !host || this.forceResizeButtons.has(runner)) {
|
|
1292
1390
|
return;
|
|
1293
1391
|
}
|
|
1294
1392
|
const button = document.createElement('button');
|
|
1295
1393
|
button.type = 'button';
|
|
1296
|
-
button.className = 'btn terminal-resize-button';
|
|
1297
|
-
button.innerHTML = '<i class="fa-solid fa-
|
|
1298
|
-
button.
|
|
1394
|
+
button.className = 'btn terminal-utility-button terminal-resize-button';
|
|
1395
|
+
button.innerHTML = '<i class="fa-solid fa-ruler-combined" aria-hidden="true"></i>';
|
|
1396
|
+
button.setAttribute('aria-label', 'Sync terminal to current viewport');
|
|
1397
|
+
this.attachTerminalTooltip(button, 'Sync terminal to current viewport');
|
|
1299
1398
|
button.addEventListener('click', (event) => {
|
|
1300
1399
|
if (event) {
|
|
1301
1400
|
event.preventDefault();
|
|
@@ -1390,10 +1489,12 @@
|
|
|
1390
1489
|
|
|
1391
1490
|
const button = document.createElement('button');
|
|
1392
1491
|
button.type = 'button';
|
|
1393
|
-
button.className = 'btn terminal-config-button';
|
|
1394
|
-
button.innerHTML = '<span class="terminal-config-label"><i class="fa-solid fa-sliders"></i
|
|
1492
|
+
button.className = 'btn terminal-utility-button terminal-config-button';
|
|
1493
|
+
button.innerHTML = '<span class="terminal-config-label"><i class="fa-solid fa-sliders" aria-hidden="true"></i></span>';
|
|
1395
1494
|
button.setAttribute('aria-haspopup', 'true');
|
|
1396
1495
|
button.setAttribute('aria-expanded', 'false');
|
|
1496
|
+
button.setAttribute('aria-label', 'Terminal appearance');
|
|
1497
|
+
this.attachTerminalTooltip(button, 'Terminal appearance');
|
|
1397
1498
|
|
|
1398
1499
|
const menu = document.createElement('div');
|
|
1399
1500
|
menu.className = 'terminal-config-menu';
|