@jfrader/storybook-docs 0.5.0 → 0.6.0
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/index.css +7 -3
- package/dist/index.js +112 -51
- package/dist/rail.d.ts +1 -0
- package/dist/styles.css +46 -9
- package/dist/toc.d.ts +0 -6
- package/package.json +1 -1
package/dist/index.css
CHANGED
|
@@ -106,16 +106,20 @@
|
|
|
106
106
|
.toc {
|
|
107
107
|
display: none;
|
|
108
108
|
}
|
|
109
|
+
.toc-track {
|
|
110
|
+
display: none;
|
|
111
|
+
}
|
|
109
112
|
@media (min-width: 1180px) {
|
|
110
113
|
.app.has-toc {
|
|
111
114
|
grid-template-columns: 276px minmax(0, 1fr) 224px;
|
|
112
115
|
}
|
|
113
|
-
.toc {
|
|
116
|
+
.toc-track {
|
|
114
117
|
display: block;
|
|
115
118
|
grid-column: 3;
|
|
116
119
|
grid-row: 2;
|
|
117
|
-
|
|
118
|
-
|
|
120
|
+
}
|
|
121
|
+
.toc {
|
|
122
|
+
display: block;
|
|
119
123
|
padding: 34px 18px 40px 6px;
|
|
120
124
|
font-size: 12.5px;
|
|
121
125
|
}
|
package/dist/index.js
CHANGED
|
@@ -5,7 +5,7 @@ import { createRoot } from "react-dom/client";
|
|
|
5
5
|
import { site as site3, themeCss, theme as theme2 } from "virtual:storybook-docs/site";
|
|
6
6
|
|
|
7
7
|
// src/app.tsx
|
|
8
|
-
import { useEffect as useEffect8, useRef as useRef5, useState as useState9 } from "react";
|
|
8
|
+
import { Children, useEffect as useEffect8, useRef as useRef5, useState as useState9 } from "react";
|
|
9
9
|
import { catalog as catalog3, groups as groups2 } from "virtual:storybook-docs/catalog";
|
|
10
10
|
import { pages, site as site2, theme } from "virtual:storybook-docs/site";
|
|
11
11
|
|
|
@@ -511,6 +511,77 @@ function LazySection({ children, placeholder = "\u2026" }) {
|
|
|
511
511
|
|
|
512
512
|
// src/toc.tsx
|
|
513
513
|
import { useCallback, useEffect as useEffect3, useRef as useRef2, useState as useState3 } from "react";
|
|
514
|
+
|
|
515
|
+
// src/rail.ts
|
|
516
|
+
var RAIL_MEDIA = "(min-width: 1180px)";
|
|
517
|
+
var RAIL_GAP = 20;
|
|
518
|
+
function followRail(rail, header) {
|
|
519
|
+
const track = rail.parentElement;
|
|
520
|
+
if (!track) return () => {
|
|
521
|
+
};
|
|
522
|
+
const media = window.matchMedia(RAIL_MEDIA);
|
|
523
|
+
let lastY = window.scrollY;
|
|
524
|
+
let direction = "down";
|
|
525
|
+
let spacer = 0;
|
|
526
|
+
const geometry = () => {
|
|
527
|
+
const top = header.offsetHeight + RAIL_GAP;
|
|
528
|
+
const viewportBottom = window.innerHeight - RAIL_GAP;
|
|
529
|
+
const height = rail.offsetHeight;
|
|
530
|
+
return {
|
|
531
|
+
top,
|
|
532
|
+
viewportBottom,
|
|
533
|
+
height,
|
|
534
|
+
fits: top + height <= viewportBottom,
|
|
535
|
+
trackTop: track.getBoundingClientRect().top + window.scrollY,
|
|
536
|
+
maxOffset: Math.max(0, track.clientHeight - height)
|
|
537
|
+
};
|
|
538
|
+
};
|
|
539
|
+
const clear = () => {
|
|
540
|
+
rail.removeAttribute("style");
|
|
541
|
+
track.removeAttribute("style");
|
|
542
|
+
};
|
|
543
|
+
const arm = (g = geometry()) => {
|
|
544
|
+
if (!media.matches) {
|
|
545
|
+
clear();
|
|
546
|
+
return;
|
|
547
|
+
}
|
|
548
|
+
spacer = g.fits ? 0 : Math.min(spacer, g.maxOffset);
|
|
549
|
+
track.style.setProperty("--sd-rail-offset", `${spacer}px`);
|
|
550
|
+
rail.style.position = "sticky";
|
|
551
|
+
rail.style.top = g.fits ? `${g.top}px` : direction === "down" ? `${g.viewportBottom - g.height}px` : "auto";
|
|
552
|
+
rail.style.bottom = g.fits || direction === "down" ? "auto" : `${window.innerHeight - g.top - g.height}px`;
|
|
553
|
+
};
|
|
554
|
+
const onScroll = () => {
|
|
555
|
+
const y = window.scrollY;
|
|
556
|
+
const next = y > lastY ? "down" : y < lastY ? "up" : direction;
|
|
557
|
+
if (next !== direction && media.matches) {
|
|
558
|
+
const g = geometry();
|
|
559
|
+
spacer = direction === "down" ? Math.min(Math.max(spacer, lastY + g.viewportBottom - g.height - g.trackTop), g.maxOffset) : Math.max(Math.min(spacer, lastY + g.top - g.trackTop), 0);
|
|
560
|
+
direction = next;
|
|
561
|
+
arm(g);
|
|
562
|
+
}
|
|
563
|
+
direction = next;
|
|
564
|
+
lastY = y;
|
|
565
|
+
};
|
|
566
|
+
const relayout = () => arm();
|
|
567
|
+
const observer = new ResizeObserver(relayout);
|
|
568
|
+
observer.observe(rail);
|
|
569
|
+
observer.observe(track);
|
|
570
|
+
observer.observe(header);
|
|
571
|
+
window.addEventListener("scroll", onScroll, { passive: true });
|
|
572
|
+
window.addEventListener("resize", relayout);
|
|
573
|
+
media.addEventListener("change", relayout);
|
|
574
|
+
arm();
|
|
575
|
+
return () => {
|
|
576
|
+
observer.disconnect();
|
|
577
|
+
window.removeEventListener("scroll", onScroll);
|
|
578
|
+
window.removeEventListener("resize", relayout);
|
|
579
|
+
media.removeEventListener("change", relayout);
|
|
580
|
+
clear();
|
|
581
|
+
};
|
|
582
|
+
}
|
|
583
|
+
|
|
584
|
+
// src/toc.tsx
|
|
514
585
|
import { Fragment, jsx as jsx5, jsxs as jsxs3 } from "react/jsx-runtime";
|
|
515
586
|
var STORY_PARAM = "story";
|
|
516
587
|
var SCROLL_OFFSET_PX = 76;
|
|
@@ -535,34 +606,9 @@ var slugify = (text) => text.normalize("NFKD").replace(/[̀-ͯ]/g, "").toLowerCa
|
|
|
535
606
|
function useRailFollow(ref, ready = true) {
|
|
536
607
|
useEffect3(() => {
|
|
537
608
|
const element = ref.current;
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
const limit = () => window.innerHeight - (Number.parseFloat(getComputedStyle(document.documentElement).getPropertyValue("--sd-header-height")) || 56) - 20;
|
|
542
|
-
const apply = () => {
|
|
543
|
-
frame = 0;
|
|
544
|
-
const bottomInDocument = element.getBoundingClientRect().bottom + window.scrollY - applied;
|
|
545
|
-
const crossing = bottomInDocument - limit();
|
|
546
|
-
const next = Math.max(0, window.scrollY - crossing);
|
|
547
|
-
if (next !== applied) {
|
|
548
|
-
applied = next;
|
|
549
|
-
element.style.setProperty("--sd-rail-follow", `${next}px`);
|
|
550
|
-
}
|
|
551
|
-
};
|
|
552
|
-
const schedule = () => {
|
|
553
|
-
if (!frame) frame = requestAnimationFrame(apply);
|
|
554
|
-
};
|
|
555
|
-
apply();
|
|
556
|
-
window.addEventListener("scroll", schedule, { passive: true });
|
|
557
|
-
window.addEventListener("resize", schedule);
|
|
558
|
-
const observer = new ResizeObserver(schedule);
|
|
559
|
-
observer.observe(element);
|
|
560
|
-
return () => {
|
|
561
|
-
window.removeEventListener("scroll", schedule);
|
|
562
|
-
window.removeEventListener("resize", schedule);
|
|
563
|
-
observer.disconnect();
|
|
564
|
-
if (frame) cancelAnimationFrame(frame);
|
|
565
|
-
};
|
|
609
|
+
const header = element?.closest(".app")?.querySelector(".top");
|
|
610
|
+
if (!element || !header) return;
|
|
611
|
+
return followRail(element, header);
|
|
566
612
|
}, [ready, ref]);
|
|
567
613
|
}
|
|
568
614
|
function scanPage(root, pageKey) {
|
|
@@ -706,7 +752,7 @@ function PageRail({ pageKey }) {
|
|
|
706
752
|
const active = useActiveIds(scan);
|
|
707
753
|
const go = useCallback((element) => scrollToElement(element), []);
|
|
708
754
|
if (!scan) return null;
|
|
709
|
-
return /* @__PURE__ */ jsx5(Fragment, { children: scan.sections.length > 0 ? /* @__PURE__ */ jsxs3("aside", { className: "toc", "aria-label": "On this page", ref: railRef, children: [
|
|
755
|
+
return /* @__PURE__ */ jsx5(Fragment, { children: scan.sections.length > 0 ? /* @__PURE__ */ jsx5("div", { className: "rail-track toc-track", children: /* @__PURE__ */ jsxs3("aside", { className: "toc", "aria-label": "On this page", ref: railRef, children: [
|
|
710
756
|
/* @__PURE__ */ jsx5("div", { className: "toc-title", children: "On this page" }),
|
|
711
757
|
/* @__PURE__ */ jsx5("ul", { children: scan.sections.map((section) => /* @__PURE__ */ jsxs3("li", { children: [
|
|
712
758
|
/* @__PURE__ */ jsx5(
|
|
@@ -731,7 +777,7 @@ function PageRail({ pageKey }) {
|
|
|
731
777
|
}
|
|
732
778
|
) }, story.id)) }) : null
|
|
733
779
|
] }, section.id)) })
|
|
734
|
-
] }) : null });
|
|
780
|
+
] }) }) : null });
|
|
735
781
|
}
|
|
736
782
|
|
|
737
783
|
// src/component-demo.tsx
|
|
@@ -1801,6 +1847,23 @@ function SearchBox() {
|
|
|
1801
1847
|
import { releases as releases2 } from "virtual:storybook-docs/releases";
|
|
1802
1848
|
import { jsx as jsx16, jsxs as jsxs13 } from "react/jsx-runtime";
|
|
1803
1849
|
var routeHref = (path) => `#${hrefFor(path)}`;
|
|
1850
|
+
var NAV_GROUP_WINDOW = 12;
|
|
1851
|
+
function NavGroup({ id, title, active, activeIndex = -1, children }) {
|
|
1852
|
+
const [open, setOpen] = useState9(false);
|
|
1853
|
+
const [showAll, setShowAll] = useState9(false);
|
|
1854
|
+
const expanded = active || open;
|
|
1855
|
+
const links = Children.toArray(children);
|
|
1856
|
+
const capped = active && links.length > NAV_GROUP_WINDOW;
|
|
1857
|
+
const start2 = Math.min(Math.max(activeIndex - NAV_GROUP_WINDOW / 2, 0), Math.max(0, links.length - NAV_GROUP_WINDOW));
|
|
1858
|
+
const visibleLinks = capped && !showAll ? links.slice(start2, start2 + NAV_GROUP_WINDOW) : links;
|
|
1859
|
+
return /* @__PURE__ */ jsxs13("div", { role: "group", "aria-labelledby": id, children: [
|
|
1860
|
+
/* @__PURE__ */ jsx16("button", { type: "button", className: "grp", id, "aria-expanded": expanded, "aria-controls": `${id}-links`, disabled: active, onClick: () => setOpen(!open), children: title }),
|
|
1861
|
+
/* @__PURE__ */ jsxs13("div", { id: `${id}-links`, hidden: !expanded, children: [
|
|
1862
|
+
/* @__PURE__ */ jsx16("div", { id: `${id}-window`, children: visibleLinks }),
|
|
1863
|
+
capped ? /* @__PURE__ */ jsx16("button", { type: "button", className: "nav-more", "aria-expanded": showAll, "aria-controls": `${id}-window`, onClick: () => setShowAll(!showAll), children: showAll ? "Show less" : `Show all ${links.length}` }) : null
|
|
1864
|
+
] })
|
|
1865
|
+
] });
|
|
1866
|
+
}
|
|
1804
1867
|
function parseRoute(hash) {
|
|
1805
1868
|
const path = hashPath(hash).replace(new RegExp(`^#?\\/?${STORYBOOK_DOCS_BASE}`), "").replace(/^\/+/, "");
|
|
1806
1869
|
if (path.startsWith("components/")) {
|
|
@@ -1909,7 +1972,7 @@ function DocsApp() {
|
|
|
1909
1972
|
/* @__PURE__ */ jsx16("span", { "aria-hidden": "true", children: "\u2197" })
|
|
1910
1973
|
] }, link.href))
|
|
1911
1974
|
] }),
|
|
1912
|
-
/* @__PURE__ */ jsxs13("nav", { id: "docs-nav", className: navOpen ? "nav open" : "nav", "aria-label": "Documentation", ref: navRef, children: [
|
|
1975
|
+
/* @__PURE__ */ jsx16("div", { className: "rail-track nav-track", children: /* @__PURE__ */ jsxs13("nav", { id: "docs-nav", className: navOpen ? "nav open" : "nav", "aria-label": "Documentation", ref: navRef, children: [
|
|
1913
1976
|
/* @__PURE__ */ jsx16("a", { href: routeHref("/"), className: route.kind === "overview" ? "on" : void 0, "aria-current": route.kind === "overview" ? "page" : void 0, children: "Overview" }),
|
|
1914
1977
|
releases2.changelog ? /* @__PURE__ */ jsxs13(
|
|
1915
1978
|
"a",
|
|
@@ -1926,22 +1989,20 @@ function DocsApp() {
|
|
|
1926
1989
|
]
|
|
1927
1990
|
}
|
|
1928
1991
|
) : null,
|
|
1929
|
-
foundations.length > 0 ? /* @__PURE__ */
|
|
1930
|
-
|
|
1931
|
-
|
|
1932
|
-
|
|
1933
|
-
|
|
1934
|
-
|
|
1935
|
-
|
|
1936
|
-
|
|
1937
|
-
|
|
1938
|
-
|
|
1939
|
-
|
|
1940
|
-
))
|
|
1941
|
-
|
|
1942
|
-
|
|
1943
|
-
/* @__PURE__ */ jsx16("div", { className: "grp", id: `nav-grp-${index}`, children: group }),
|
|
1944
|
-
catalog3.filter((entry) => entry.group === group).map((entry) => /* @__PURE__ */ jsx16(
|
|
1992
|
+
foundations.length > 0 ? /* @__PURE__ */ jsx16(NavGroup, { id: "nav-grp-foundations", title: "Foundations", active: foundations.some((item) => route.kind === item.kind), children: foundations.map((item) => /* @__PURE__ */ jsx16(
|
|
1993
|
+
"a",
|
|
1994
|
+
{
|
|
1995
|
+
href: item.href,
|
|
1996
|
+
className: route.kind === item.kind ? "on" : void 0,
|
|
1997
|
+
"aria-current": route.kind === item.kind ? "page" : void 0,
|
|
1998
|
+
children: item.label
|
|
1999
|
+
},
|
|
2000
|
+
item.href
|
|
2001
|
+
)) }, `foundations-${activeSlug ?? route.kind}`) : null,
|
|
2002
|
+
groups2.map((group, index) => {
|
|
2003
|
+
const entries = catalog3.filter((entry) => entry.group === group);
|
|
2004
|
+
const activeIndex = entries.findIndex((entry) => entry.slug === activeSlug);
|
|
2005
|
+
return /* @__PURE__ */ jsx16(NavGroup, { id: `nav-grp-${index}`, title: group, active: activeIndex !== -1, activeIndex, children: entries.map((entry) => /* @__PURE__ */ jsx16(
|
|
1945
2006
|
"a",
|
|
1946
2007
|
{
|
|
1947
2008
|
href: routeHref(`/components/${entry.slug}`),
|
|
@@ -1952,9 +2013,9 @@ function DocsApp() {
|
|
|
1952
2013
|
children: entry.name
|
|
1953
2014
|
},
|
|
1954
2015
|
entry.slug
|
|
1955
|
-
))
|
|
1956
|
-
|
|
1957
|
-
] }),
|
|
2016
|
+
)) }, `${group}-${activeSlug ?? route.kind}`);
|
|
2017
|
+
})
|
|
2018
|
+
] }) }),
|
|
1958
2019
|
/* @__PURE__ */ jsx16("main", { id: "main", className: "main", tabIndex: -1, ref: mainRef, children: route.kind === "component" ? /* @__PURE__ */ jsx16(ComponentPage, { entry: catalog3.find((entry) => entry.slug === route.slug) }) : route.kind === "color" ? /* @__PURE__ */ jsx16(ColorPage, {}) : route.kind === "typography" ? /* @__PURE__ */ jsx16(TypePage, {}) : route.kind === "spacing" ? /* @__PURE__ */ jsx16(SpacingPage, {}) : route.kind === "effects" ? /* @__PURE__ */ jsx16(EffectsPage, {}) : route.kind === "releases" ? /* @__PURE__ */ jsx16(ReleasesPage, {}) : /* @__PURE__ */ jsx16(OverviewPage, {}) }),
|
|
1959
2020
|
route.kind !== "overview" ? /* @__PURE__ */ jsx16(PageRail, { pageKey: activeSlug ?? route.kind }) : null
|
|
1960
2021
|
] });
|
package/dist/rail.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function followRail(rail: HTMLElement, header: HTMLElement): () => void;
|
package/dist/styles.css
CHANGED
|
@@ -186,23 +186,44 @@ body {
|
|
|
186
186
|
outline-offset: 2px;
|
|
187
187
|
}
|
|
188
188
|
|
|
189
|
+
.rail-track {
|
|
190
|
+
overflow-anchor: none;
|
|
191
|
+
min-width: 0;
|
|
192
|
+
}
|
|
193
|
+
@media (min-width: 1180px) {
|
|
194
|
+
.rail-track::before {
|
|
195
|
+
content: '';
|
|
196
|
+
display: block;
|
|
197
|
+
height: var(--sd-rail-offset, 0px);
|
|
198
|
+
}
|
|
199
|
+
}
|
|
189
200
|
.nav {
|
|
190
201
|
border-right: 0;
|
|
191
202
|
background: var(--sd-surface);
|
|
192
|
-
padding: 14px 12px
|
|
193
|
-
/* Follows the document like the right rail, parking when its own end is visible. */
|
|
194
|
-
align-self: start;
|
|
195
|
-
transform: translateY(var(--sd-rail-follow, 0px));
|
|
203
|
+
padding: 14px 12px 12px;
|
|
196
204
|
}
|
|
197
|
-
.nav a
|
|
198
|
-
|
|
199
|
-
|
|
205
|
+
.nav a,
|
|
206
|
+
.nav-more {
|
|
207
|
+
display: flex;
|
|
208
|
+
align-items: center;
|
|
209
|
+
box-sizing: border-box;
|
|
210
|
+
min-height: 28px;
|
|
211
|
+
padding: 4px 10px;
|
|
200
212
|
border-radius: 8px;
|
|
201
213
|
color: var(--sd-text-muted);
|
|
202
214
|
font-size: 13.5px;
|
|
203
215
|
text-decoration: none;
|
|
204
216
|
}
|
|
205
|
-
.nav
|
|
217
|
+
.nav-more {
|
|
218
|
+
width: 100%;
|
|
219
|
+
background: none;
|
|
220
|
+
border: 0;
|
|
221
|
+
font-family: inherit;
|
|
222
|
+
cursor: pointer;
|
|
223
|
+
text-align: left;
|
|
224
|
+
}
|
|
225
|
+
.nav a:hover,
|
|
226
|
+
.nav-more:hover {
|
|
206
227
|
background: var(--sd-surface-hover);
|
|
207
228
|
color: var(--sd-text);
|
|
208
229
|
}
|
|
@@ -212,13 +233,26 @@ body {
|
|
|
212
233
|
font-weight: 600;
|
|
213
234
|
}
|
|
214
235
|
.grp {
|
|
215
|
-
margin:
|
|
236
|
+
margin: 3px 0 2px;
|
|
216
237
|
padding: 0 10px;
|
|
217
238
|
font-size: 10.5px;
|
|
218
239
|
letter-spacing: 0.09em;
|
|
219
240
|
text-transform: uppercase;
|
|
220
241
|
color: var(--sd-text-muted);
|
|
221
242
|
font-weight: 700;
|
|
243
|
+
display: block;
|
|
244
|
+
width: 100%;
|
|
245
|
+
text-align: left;
|
|
246
|
+
font-family: inherit;
|
|
247
|
+
background: none;
|
|
248
|
+
border: 0;
|
|
249
|
+
cursor: pointer;
|
|
250
|
+
min-height: 28px;
|
|
251
|
+
}
|
|
252
|
+
.grp:focus-visible,
|
|
253
|
+
.nav-more:focus-visible {
|
|
254
|
+
outline: 2px solid var(--sd-focus-ring);
|
|
255
|
+
outline-offset: 2px;
|
|
222
256
|
}
|
|
223
257
|
|
|
224
258
|
.main {
|
|
@@ -618,6 +652,9 @@ code.type {
|
|
|
618
652
|
.nav-toggle {
|
|
619
653
|
display: inline-block;
|
|
620
654
|
}
|
|
655
|
+
.nav-track {
|
|
656
|
+
display: contents;
|
|
657
|
+
}
|
|
621
658
|
.search {
|
|
622
659
|
order: 10;
|
|
623
660
|
flex: 1 1 100%;
|
package/dist/toc.d.ts
CHANGED
|
@@ -6,12 +6,6 @@ export declare function hashPath(hash: string): string;
|
|
|
6
6
|
/** The `?story=` deep-link target of a hash, if any. */
|
|
7
7
|
export declare function storyFromHash(hash: string): string | null;
|
|
8
8
|
export declare function storyLink(location: Location, story: string): string;
|
|
9
|
-
/**
|
|
10
|
-
* A rail travels with the document until its own end would pass the fold, then it parks there —
|
|
11
|
-
* the reader keeps seeing where it continues, and scrolling up lets it fall back into flow. This is
|
|
12
|
-
* the scroll-linked translation docs sites use, because `position: sticky` cannot move an element
|
|
13
|
-
* taller than the viewport.
|
|
14
|
-
*/
|
|
15
9
|
export declare function useRailFollow(ref: RefObject<HTMLElement | null>, ready?: boolean): void;
|
|
16
10
|
/** The "On this page" rail and the `?story=` deep-link landing. */
|
|
17
11
|
export declare function PageRail({ pageKey }: {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@jfrader/storybook-docs",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.6.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "A documentation front for any design system that has Storybook: navigation, live examples and API tables are generated from the story files themselves.",
|
|
6
6
|
"exports": {
|