seemore 1.10.2 → 1.10.4
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
|
@@ -305,7 +305,7 @@ const RUNTIME = `(function () {
|
|
|
305
305
|
|
|
306
306
|
// Wide enough for the rail: open the collapsible so it reads as a list, not a disclosure.
|
|
307
307
|
var tocDetails = document.querySelector('.seemore-export-toc details');
|
|
308
|
-
if (tocDetails && window.matchMedia('(min-width:
|
|
308
|
+
if (tocDetails && window.matchMedia('(min-width: 1024px)').matches) tocDetails.open = true;
|
|
309
309
|
|
|
310
310
|
var main = document.querySelector('main');
|
|
311
311
|
var overlay = document.createElement('div');
|
|
@@ -124,7 +124,7 @@ function bindBehaviors(): void {
|
|
|
124
124
|
|
|
125
125
|
// Wide enough for the rail: open the collapsible so it reads as a list, not a disclosure.
|
|
126
126
|
const tocDetails = document.querySelector<HTMLDetailsElement>('.seemore-export-toc details');
|
|
127
|
-
if (tocDetails && window.matchMedia('(min-width:
|
|
127
|
+
if (tocDetails && window.matchMedia('(min-width: 1024px)').matches) tocDetails.open = true;
|
|
128
128
|
|
|
129
129
|
const overlay = document.createElement('div');
|
|
130
130
|
overlay.className = 'seemore-export-overlay';
|
package/src/app/index.html
CHANGED
|
@@ -9,6 +9,15 @@
|
|
|
9
9
|
artwork the editor extension ships as its icon. Inlined rather than linked so the
|
|
10
10
|
built site needs no extra request and no file in the user's folder. -->
|
|
11
11
|
<link rel="icon" href="data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 128 128'%3E%3Crect width='128' height='128' rx='28' fill='%236D5EF5'/%3E%3Crect x='30' y='26' width='52' height='68' rx='8' fill='%23ffffff' opacity='0.35' transform='rotate(-8 56 60)'/%3E%3Crect x='38' y='22' width='52' height='68' rx='8' fill='%23ffffff' opacity='0.6' transform='rotate(-3 64 56)'/%3E%3Crect x='46' y='24' width='52' height='72' rx='8' fill='%23ffffff'/%3E%3Cg stroke-linecap='round'%3E%3Cline x1='56' y1='42' x2='82' y2='42' stroke='%236D5EF5' stroke-width='6'/%3E%3Cline x1='56' y1='56' x2='88' y2='56' stroke='%23C6C8E6' stroke-width='4'/%3E%3Cline x1='56' y1='66' x2='80' y2='66' stroke='%23C6C8E6' stroke-width='4'/%3E%3Cline x1='56' y1='76' x2='88' y2='76' stroke='%236D5EF5' stroke-width='4'/%3E%3Cline x1='56' y1='86' x2='74' y2='86' stroke='%23C6C8E6' stroke-width='4'/%3E%3C/g%3E%3C/svg%3E" />
|
|
12
|
+
<!-- Runs before body paints, so a remembered sidebar collapse applies on the very first
|
|
13
|
+
frame instead of flashing the rail open and then closing it once React hydrates. -->
|
|
14
|
+
<script>
|
|
15
|
+
try {
|
|
16
|
+
if (localStorage.getItem('seemore:sidebar-collapsed') === 'true') {
|
|
17
|
+
document.documentElement.dataset.sidebarCollapsed = 'true';
|
|
18
|
+
}
|
|
19
|
+
} catch {}
|
|
20
|
+
</script>
|
|
12
21
|
<!--seemore-head-->
|
|
13
22
|
</head>
|
|
14
23
|
<body>
|
|
@@ -44,11 +44,23 @@ const styled = {
|
|
|
44
44
|
const renderPageTree = createPageTreeRenderer(styled);
|
|
45
45
|
|
|
46
46
|
const COLLAPSE_KEY = 'seemore:sidebar-collapsed';
|
|
47
|
+
const COLLAPSE_ATTR = 'sidebarCollapsed';
|
|
47
48
|
|
|
48
49
|
/* `useLayoutEffect` does nothing on the server and says so in a warning; the prerender pass
|
|
49
50
|
takes `useEffect`, which it never runs either. */
|
|
50
51
|
const useIsomorphicLayoutEffect = typeof document === 'undefined' ? useEffect : useLayoutEffect;
|
|
51
52
|
|
|
53
|
+
/**
|
|
54
|
+
* Mirrors the collapse choice onto `<html data-sidebar-collapsed>`, the attribute the blocking
|
|
55
|
+
* script in `index.html` sets from `localStorage` before React ever runs. Once hydrated, this
|
|
56
|
+
* component's own state is authoritative and must keep that attribute in sync — otherwise a
|
|
57
|
+
* later un-collapse would leave the attribute (and the CSS rule keyed on it) stuck on `true`.
|
|
58
|
+
*/
|
|
59
|
+
function syncCollapseAttr(collapsed: boolean): void {
|
|
60
|
+
if (collapsed) document.documentElement.dataset[COLLAPSE_ATTR] = 'true';
|
|
61
|
+
else delete document.documentElement.dataset[COLLAPSE_ATTR];
|
|
62
|
+
}
|
|
63
|
+
|
|
52
64
|
/**
|
|
53
65
|
* Hiding the rail is a reader's preference, like the theme, so it outlives the page rather
|
|
54
66
|
* than resetting on the next load. fumadocs owns the state itself — every primitive reads
|
|
@@ -65,6 +77,7 @@ export function useSidebarCollapse(): { collapsed: boolean; toggle: () => void }
|
|
|
65
77
|
} catch {
|
|
66
78
|
// Storage blocked, private window: the choice just does not outlive the page.
|
|
67
79
|
}
|
|
80
|
+
syncCollapseAttr(next);
|
|
68
81
|
setCollapsed(next);
|
|
69
82
|
}, [collapsed, setCollapsed]);
|
|
70
83
|
|
|
@@ -77,9 +90,14 @@ function useRestoreCollapse(): void {
|
|
|
77
90
|
|
|
78
91
|
useIsomorphicLayoutEffect(() => {
|
|
79
92
|
try {
|
|
80
|
-
|
|
93
|
+
const restored = localStorage.getItem(COLLAPSE_KEY) === 'true';
|
|
94
|
+
if (restored) setCollapsed(true);
|
|
95
|
+
// Reconciles the head script's guess with the real value — clears it if storage was
|
|
96
|
+
// wiped or disagrees, so a stale attribute never outlives the state it was priming.
|
|
97
|
+
syncCollapseAttr(restored);
|
|
81
98
|
} catch {
|
|
82
99
|
// Nothing readable is nothing to restore; the rail stays open.
|
|
100
|
+
syncCollapseAttr(false);
|
|
83
101
|
}
|
|
84
102
|
}, [setCollapsed]);
|
|
85
103
|
}
|
|
@@ -181,6 +181,13 @@
|
|
|
181
181
|
@apply md:hidden;
|
|
182
182
|
}
|
|
183
183
|
|
|
184
|
+
/* Matches the rule above but keyed off the attribute the blocking head script sets, so a
|
|
185
|
+
remembered collapse hides the rail on the very first paint, before React has hydrated and
|
|
186
|
+
taken over via `data-collapsed`. */
|
|
187
|
+
:root[data-sidebar-collapsed='true'] .seemore-sidebar-column {
|
|
188
|
+
@apply md:hidden;
|
|
189
|
+
}
|
|
190
|
+
|
|
184
191
|
.seemore-sidebar-backdrop {
|
|
185
192
|
@apply fixed inset-0 z-30 bg-black/40 md:hidden;
|
|
186
193
|
}
|
|
@@ -622,15 +629,53 @@
|
|
|
622
629
|
color: var(--color-fd-foreground, #111827);
|
|
623
630
|
}
|
|
624
631
|
|
|
625
|
-
/* From
|
|
626
|
-
|
|
632
|
+
/* From 1024px up — the live page's own `lg` breakpoint for showing its TOC rail — there is
|
|
633
|
+
enough room for the rail if the reading column gives up its centring and narrows to make
|
|
634
|
+
space; below that the rail would ride over the text at any column width, so the
|
|
635
|
+
collapsible stays in flow there.
|
|
636
|
+
|
|
637
|
+
Two tiers because a centred 56rem column plus the rail's 14rem + 2rem gap needs
|
|
638
|
+
1152px+ to coexist without narrowing: from 1024px the column is pinned to the left
|
|
639
|
+
with a right-hand reservation sized exactly for the rail, gap and outer margin; once
|
|
640
|
+
there is enough width (1440px) for the column to sit at its full 56rem *and* stay
|
|
641
|
+
centred with that same 2rem gap to the rail, it switches back to centred — matching
|
|
642
|
+
the live page's `md:px-8` column padding either way. */
|
|
643
|
+
@media (min-width: 1024px) and (max-width: 1439.98px) {
|
|
644
|
+
.seemore-export-main {
|
|
645
|
+
margin-inline: 0;
|
|
646
|
+
max-width: none;
|
|
647
|
+
padding-inline-end: 18rem;
|
|
648
|
+
padding-inline-start: 2rem;
|
|
649
|
+
}
|
|
650
|
+
|
|
651
|
+
.seemore-export-toc {
|
|
652
|
+
inset-inline-end: 2rem;
|
|
653
|
+
margin-block: 0;
|
|
654
|
+
max-height: calc(100vh - 8rem);
|
|
655
|
+
overflow-y: auto;
|
|
656
|
+
position: fixed;
|
|
657
|
+
top: 5rem;
|
|
658
|
+
width: 14rem;
|
|
659
|
+
z-index: 40;
|
|
660
|
+
}
|
|
661
|
+
|
|
662
|
+
.seemore-export-toc summary {
|
|
663
|
+
cursor: default;
|
|
664
|
+
margin-bottom: 0.75rem;
|
|
665
|
+
}
|
|
666
|
+
|
|
667
|
+
.seemore-export-toc summary::after {
|
|
668
|
+
display: none;
|
|
669
|
+
}
|
|
670
|
+
}
|
|
627
671
|
|
|
628
|
-
The rail's `inset-inline-end` is pinned to the article's own centring math (its
|
|
629
|
-
56rem/2 half-width) rather than a flat viewport offset, so the gap between the
|
|
630
|
-
article's right edge and the rail stays a fixed 2rem at any width above the
|
|
631
|
-
breakpoint — matching the live page's `md:px-8` column padding — instead of shrinking
|
|
632
|
-
toward zero as the viewport narrows toward the breakpoint. */
|
|
633
672
|
@media (min-width: 1440px) {
|
|
673
|
+
.seemore-export-main {
|
|
674
|
+
margin-inline: auto;
|
|
675
|
+
max-width: 56rem;
|
|
676
|
+
padding-inline: 1rem;
|
|
677
|
+
}
|
|
678
|
+
|
|
634
679
|
.seemore-export-toc {
|
|
635
680
|
inset-inline-end: calc((100vw - 56rem) / 2 - 14rem - 2rem);
|
|
636
681
|
margin-block: 0;
|