seemore 1.10.3 → 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.3",
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",
@@ -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
  }