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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "seemore",
3
- "version": "1.10.2",
3
+ "version": "1.10.4",
4
4
  "description": "Let AI write the Markdown. Let seemore show it better — zero config documentation framework.",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -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: 1440px)').matches) tocDetails.open = true;
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: 1440px)').matches) tocDetails.open = true;
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';
@@ -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
- if (localStorage.getItem(COLLAPSE_KEY) === 'true') setCollapsed(true);
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 1440px up there is room for both the reading column and the rail side by side;
626
- below that the rail would ride over the text, so the collapsible stays in flow.
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;