@jfrader/storybook-docs 0.4.3 → 0.4.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/dist/css.d.ts +1 -0
- package/dist/index.css +3 -7
- package/dist/index.d.ts +1 -0
- package/dist/index.js +55 -14
- package/dist/styles.css +3 -6
- package/dist/toc.d.ts +9 -0
- package/docs/RELEASING.md +26 -0
- package/package.json +11 -18
package/dist/css.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
declare module '*.css';
|
package/dist/index.css
CHANGED
|
@@ -114,11 +114,8 @@
|
|
|
114
114
|
display: block;
|
|
115
115
|
grid-column: 3;
|
|
116
116
|
grid-row: 2;
|
|
117
|
-
position: sticky;
|
|
118
|
-
top: var(--sd-header-height, 56px);
|
|
119
117
|
align-self: start;
|
|
120
|
-
|
|
121
|
-
overflow-y: auto;
|
|
118
|
+
transform: translateY(var(--sd-rail-follow, 0px));
|
|
122
119
|
padding: 34px 18px 40px 6px;
|
|
123
120
|
font-size: 12.5px;
|
|
124
121
|
}
|
|
@@ -173,13 +170,12 @@
|
|
|
173
170
|
margin: 0;
|
|
174
171
|
padding: 0 20px 18px;
|
|
175
172
|
min-width: 0;
|
|
176
|
-
border: 0;
|
|
177
173
|
background: none;
|
|
178
174
|
color: var(--sd-text-muted);
|
|
179
175
|
font-size: 13px;
|
|
180
176
|
}
|
|
181
|
-
.sd-controls
|
|
182
|
-
|
|
177
|
+
.sd-controls-label {
|
|
178
|
+
margin: 16px 0 10px;
|
|
183
179
|
font-size: 11px;
|
|
184
180
|
font-weight: 600;
|
|
185
181
|
letter-spacing: 0.06em;
|
package/dist/index.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
/// <reference path="./virtual.d.ts" />
|
|
2
|
+
/// <reference path="./css.d.ts" />
|
|
2
3
|
export { start } from './start.js';
|
|
3
4
|
export { ComponentDemo, type ComponentDemoProps } from './component-demo.js';
|
|
4
5
|
export type { StorybookDocsConfig, CatalogEntry, ThemeRole } from './config.js';
|
package/dist/index.js
CHANGED
|
@@ -6,7 +6,7 @@ import { site as site3, themeCss, theme as theme2 } from "virtual:storybook-docs
|
|
|
6
6
|
|
|
7
7
|
// src/app.tsx
|
|
8
8
|
import { useEffect as useEffect7, useRef as useRef5, useState as useState8 } from "react";
|
|
9
|
-
import { catalog as catalog3, groups as groups2
|
|
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
|
|
|
12
12
|
// src/pages/component-page.tsx
|
|
@@ -531,6 +531,39 @@ function storyLink(location, story) {
|
|
|
531
531
|
return `${base}${hashPath(location.hash)}?${new URLSearchParams({ [STORY_PARAM]: story })}`;
|
|
532
532
|
}
|
|
533
533
|
var slugify = (text) => text.normalize("NFKD").replace(/[̀-ͯ]/g, "").toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-|-$/g, "");
|
|
534
|
+
function useRailFollow(ref, ready = true) {
|
|
535
|
+
useEffect3(() => {
|
|
536
|
+
const element = ref.current;
|
|
537
|
+
if (!element) return;
|
|
538
|
+
let frame = 0;
|
|
539
|
+
let applied = 0;
|
|
540
|
+
const limit = () => window.innerHeight - (Number.parseFloat(getComputedStyle(document.documentElement).getPropertyValue("--sd-header-height")) || 56) - 20;
|
|
541
|
+
const apply = () => {
|
|
542
|
+
frame = 0;
|
|
543
|
+
const bottomInDocument = element.getBoundingClientRect().bottom + window.scrollY - applied;
|
|
544
|
+
const crossing = bottomInDocument - limit();
|
|
545
|
+
const next = Math.max(0, window.scrollY - crossing);
|
|
546
|
+
if (next !== applied) {
|
|
547
|
+
applied = next;
|
|
548
|
+
element.style.setProperty("--sd-rail-follow", `${next}px`);
|
|
549
|
+
}
|
|
550
|
+
};
|
|
551
|
+
const schedule = () => {
|
|
552
|
+
if (!frame) frame = requestAnimationFrame(apply);
|
|
553
|
+
};
|
|
554
|
+
apply();
|
|
555
|
+
window.addEventListener("scroll", schedule, { passive: true });
|
|
556
|
+
window.addEventListener("resize", schedule);
|
|
557
|
+
const observer = new ResizeObserver(schedule);
|
|
558
|
+
observer.observe(element);
|
|
559
|
+
return () => {
|
|
560
|
+
window.removeEventListener("scroll", schedule);
|
|
561
|
+
window.removeEventListener("resize", schedule);
|
|
562
|
+
observer.disconnect();
|
|
563
|
+
if (frame) cancelAnimationFrame(frame);
|
|
564
|
+
};
|
|
565
|
+
}, [ready, ref]);
|
|
566
|
+
}
|
|
534
567
|
function scanPage(root, pageKey) {
|
|
535
568
|
const used = /* @__PURE__ */ new Set();
|
|
536
569
|
const unique = (prefix, text) => {
|
|
@@ -542,9 +575,12 @@ function scanPage(root, pageKey) {
|
|
|
542
575
|
};
|
|
543
576
|
const sections = [];
|
|
544
577
|
const frames = [];
|
|
545
|
-
const subHeadings = [...root.querySelectorAll("h3")].filter(
|
|
578
|
+
const subHeadings = [...root.querySelectorAll("h3")].filter(
|
|
579
|
+
(heading) => heading.textContent && !heading.closest(".story-lane") && !heading.closest(".frame")
|
|
580
|
+
);
|
|
546
581
|
root.querySelectorAll("h2").forEach((heading) => {
|
|
547
582
|
if (!heading.textContent) return;
|
|
583
|
+
if (heading.closest(".story-lane") || heading.closest(".frame")) return;
|
|
548
584
|
heading.id ||= unique("section", heading.textContent);
|
|
549
585
|
heading.dataset.toc = "";
|
|
550
586
|
const section = heading.parentElement?.tagName === "SECTION" ? heading.parentElement : null;
|
|
@@ -570,6 +606,13 @@ function scanPage(root, pageKey) {
|
|
|
570
606
|
});
|
|
571
607
|
sections.push({ id: heading.id, title: heading.textContent, element: section ?? heading, heading, stories, subs });
|
|
572
608
|
});
|
|
609
|
+
const counts = /* @__PURE__ */ new Map();
|
|
610
|
+
for (const item of frames) counts.set(item.name, (counts.get(item.name) ?? 0) + 1);
|
|
611
|
+
for (const item of frames) {
|
|
612
|
+
if ((counts.get(item.name) ?? 0) > 1 && item.story && item.story !== item.name) {
|
|
613
|
+
item.name = `${item.name} \xB7 ${item.story}`;
|
|
614
|
+
}
|
|
615
|
+
}
|
|
573
616
|
return { pageKey, sections, frames };
|
|
574
617
|
}
|
|
575
618
|
var signature = (scan) => `${scan.pageKey}|${scan.sections.map((s) => `${s.id}(${s.subs.map((sub) => sub.id).join("+")}):${s.stories.map((st) => `${st.id}:${st.name}`).join(",")}`).join(";")}`;
|
|
@@ -657,10 +700,12 @@ function PageRail({ pageKey }) {
|
|
|
657
700
|
window.setTimeout(() => match.element.classList.remove("toc-flash"), FLASH_MS);
|
|
658
701
|
setTarget(null);
|
|
659
702
|
}, [target, scan, pageKey]);
|
|
703
|
+
const railRef = useRef2(null);
|
|
704
|
+
useRailFollow(railRef, scan !== null);
|
|
660
705
|
const active = useActiveIds(scan);
|
|
661
706
|
const go = useCallback((element) => scrollToElement(element), []);
|
|
662
707
|
if (!scan) return null;
|
|
663
|
-
return /* @__PURE__ */ jsx5(Fragment, { children: scan.sections.length > 0 ? /* @__PURE__ */ jsxs3("aside", { className: "toc", "aria-label": "On this page", children: [
|
|
708
|
+
return /* @__PURE__ */ jsx5(Fragment, { children: scan.sections.length > 0 ? /* @__PURE__ */ jsxs3("aside", { className: "toc", "aria-label": "On this page", ref: railRef, children: [
|
|
664
709
|
/* @__PURE__ */ jsx5("div", { className: "toc-title", children: "On this page" }),
|
|
665
710
|
/* @__PURE__ */ jsx5("ul", { children: scan.sections.map((section) => /* @__PURE__ */ jsxs3("li", { children: [
|
|
666
711
|
/* @__PURE__ */ jsx5(
|
|
@@ -799,6 +844,7 @@ function ComponentDemo({
|
|
|
799
844
|
children
|
|
800
845
|
}) {
|
|
801
846
|
const [codeOpen, setCodeOpen] = useState4(false);
|
|
847
|
+
const controlsLabelId = useId();
|
|
802
848
|
const canvasRef = useRef3(null);
|
|
803
849
|
const [scrollable, setScrollable] = useState4(false);
|
|
804
850
|
useEffect4(() => {
|
|
@@ -844,8 +890,8 @@ function ComponentDemo({
|
|
|
844
890
|
skipped.join(", "),
|
|
845
891
|
". See it in Storybook."
|
|
846
892
|
] }) : null,
|
|
847
|
-
unavailable ? /* @__PURE__ */ jsx6("p", { className: "sd-controls-note", children: unavailable }) : /* @__PURE__ */ jsxs4("
|
|
848
|
-
/* @__PURE__ */ jsxs4("
|
|
893
|
+
unavailable ? /* @__PURE__ */ jsx6("p", { className: "sd-controls-note", children: unavailable }) : /* @__PURE__ */ jsxs4("div", { className: "sd-controls", role: "group", "aria-labelledby": controlsLabelId, children: [
|
|
894
|
+
/* @__PURE__ */ jsxs4("p", { className: "sd-controls-label", id: controlsLabelId, children: [
|
|
849
895
|
"Controls for ",
|
|
850
896
|
storyName
|
|
851
897
|
] }),
|
|
@@ -1756,6 +1802,8 @@ function DocsApp() {
|
|
|
1756
1802
|
const [route, setRoute] = useState8(() => parseRoute(window.location.hash));
|
|
1757
1803
|
const [mode, setMode] = useState8(theme.values?.[0] ?? "dark");
|
|
1758
1804
|
const [navOpen, setNavOpen] = useState8(false);
|
|
1805
|
+
const navRef = useRef5(null);
|
|
1806
|
+
useRailFollow(navRef);
|
|
1759
1807
|
const headerRef = useRef5(null);
|
|
1760
1808
|
const mainRef = useRef5(null);
|
|
1761
1809
|
useEffect7(() => {
|
|
@@ -1845,7 +1893,7 @@ function DocsApp() {
|
|
|
1845
1893
|
/* @__PURE__ */ jsx16("span", { "aria-hidden": "true", children: "\u2197" })
|
|
1846
1894
|
] }, link.href))
|
|
1847
1895
|
] }),
|
|
1848
|
-
/* @__PURE__ */ jsxs13("nav", { id: "docs-nav", className: navOpen ? "nav open" : "nav", "aria-label": "Documentation", children: [
|
|
1896
|
+
/* @__PURE__ */ jsxs13("nav", { id: "docs-nav", className: navOpen ? "nav open" : "nav", "aria-label": "Documentation", ref: navRef, children: [
|
|
1849
1897
|
/* @__PURE__ */ jsx16("a", { href: routeHref("/"), className: route.kind === "overview" ? "on" : void 0, "aria-current": route.kind === "overview" ? "page" : void 0, children: "Overview" }),
|
|
1850
1898
|
releases2.changelog ? /* @__PURE__ */ jsxs13(
|
|
1851
1899
|
"a",
|
|
@@ -1889,14 +1937,7 @@ function DocsApp() {
|
|
|
1889
1937
|
},
|
|
1890
1938
|
entry.slug
|
|
1891
1939
|
))
|
|
1892
|
-
] }, group))
|
|
1893
|
-
/* @__PURE__ */ jsxs13("div", { className: "nav-note", children: [
|
|
1894
|
-
"navigation, examples and API tables generated from ",
|
|
1895
|
-
stats2.components,
|
|
1896
|
-
" story files \xB7 ",
|
|
1897
|
-
stats2.stories,
|
|
1898
|
-
" stories"
|
|
1899
|
-
] })
|
|
1940
|
+
] }, group))
|
|
1900
1941
|
] }),
|
|
1901
1942
|
/* @__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, {}) }),
|
|
1902
1943
|
route.kind !== "overview" ? /* @__PURE__ */ jsx16(PageRail, { pageKey: activeSlug ?? route.kind }) : null
|
package/dist/styles.css
CHANGED
|
@@ -190,6 +190,9 @@ body {
|
|
|
190
190
|
border-right: 0;
|
|
191
191
|
background: var(--sd-surface);
|
|
192
192
|
padding: 14px 12px 80px;
|
|
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));
|
|
193
196
|
}
|
|
194
197
|
.nav a {
|
|
195
198
|
display: block;
|
|
@@ -217,12 +220,6 @@ body {
|
|
|
217
220
|
color: var(--sd-text-muted);
|
|
218
221
|
font-weight: 700;
|
|
219
222
|
}
|
|
220
|
-
.nav-note {
|
|
221
|
-
margin: 22px 10px 0;
|
|
222
|
-
font-size: 11.5px;
|
|
223
|
-
line-height: 1.6;
|
|
224
|
-
color: var(--sd-text-muted);
|
|
225
|
-
}
|
|
226
223
|
|
|
227
224
|
.main {
|
|
228
225
|
padding: 48px clamp(28px, 4vw, 64px) 160px;
|
package/dist/toc.d.ts
CHANGED
|
@@ -1,9 +1,18 @@
|
|
|
1
|
+
/** @jsxImportSource react */
|
|
2
|
+
import { type RefObject } from 'react';
|
|
1
3
|
import './toc.css';
|
|
2
4
|
/** The hash without its query: `#/components/button?story=Variants` → `#/components/button`. */
|
|
3
5
|
export declare function hashPath(hash: string): string;
|
|
4
6
|
/** The `?story=` deep-link target of a hash, if any. */
|
|
5
7
|
export declare function storyFromHash(hash: string): string | null;
|
|
6
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
|
+
export declare function useRailFollow(ref: RefObject<HTMLElement | null>, ready?: boolean): void;
|
|
7
16
|
/** The "On this page" rail and the `?story=` deep-link landing. */
|
|
8
17
|
export declare function PageRail({ pageKey }: {
|
|
9
18
|
pageKey: string;
|
package/docs/RELEASING.md
CHANGED
|
@@ -125,3 +125,29 @@ Official npm references (check them when changing authentication):
|
|
|
125
125
|
[trusted publishers](https://docs.npmjs.com/trusted-publishers/),
|
|
126
126
|
[provenance](https://docs.npmjs.com/generating-provenance-statements/),
|
|
127
127
|
[granular tokens](https://docs.npmjs.com/creating-and-viewing-access-tokens/).
|
|
128
|
+
|
|
129
|
+
## First publish of a new package name
|
|
130
|
+
|
|
131
|
+
Established procedure, after a morning spent rediscovering it:
|
|
132
|
+
|
|
133
|
+
1. **`npm trust` works before the package exists.** `npm trust github <pkg> --repo <owner>/<repo> --file publish.yml --allow-publish`
|
|
134
|
+
returns **201** even for a name that has never been published, as long as you are authenticated. Do this first; it is
|
|
135
|
+
what lets every later `v*` tag publish itself through OIDC with provenance, no tokens.
|
|
136
|
+
2. **Workflows that set `NODE_AUTH_TOKEN` cannot use trusted publishing.** An empty secret sends an
|
|
137
|
+
unauthenticated request and npm answers `404` on the `PUT`, which reads like a missing package. This workflow
|
|
138
|
+
therefore sets no token.
|
|
139
|
+
3. **The first publish has to happen once from a machine** — the registry has no artifact yet:
|
|
140
|
+
|
|
141
|
+
```bash
|
|
142
|
+
cd <the package checkout>
|
|
143
|
+
npm login --registry https://registry.npmjs.org # prints a browser URL; no OTP code needed
|
|
144
|
+
NPM_CONFIG_USERCONFIG=<config> npm publish # browser URL again, then "+ <pkg>@<version>"
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
A `~/.npmrc` that maps the scope to another registry (e.g. `@scope:registry=https://npm.pkg.github.com/`) makes a
|
|
148
|
+
plain `npm publish` target that registry instead and fail with `403`. Point the scope at npmjs in the config used
|
|
149
|
+
for the publish.
|
|
150
|
+
4. **Verify from the registry, not from the local output:** `curl -s https://registry.npmjs.org/<scope>%2f<pkg>`
|
|
151
|
+
must list the version. Until it does, nothing is published.
|
|
152
|
+
5. After that, releases are tags: `git tag -a vX.Y.Z && git push origin vX.Y.Z`, and the publish workflow does the
|
|
153
|
+
rest. Do **not** push a tag for a version you already published by hand — npm rejects the duplicate.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@jfrader/storybook-docs",
|
|
3
|
-
"version": "0.4.
|
|
3
|
+
"version": "0.4.4",
|
|
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": {
|
|
@@ -27,12 +27,6 @@
|
|
|
27
27
|
"react-dom": "^19.3.0",
|
|
28
28
|
"vite": "^8.3.4"
|
|
29
29
|
},
|
|
30
|
-
"packageManager": "pnpm@10.12.1",
|
|
31
|
-
"pnpm": {
|
|
32
|
-
"onlyBuiltDependencies": [
|
|
33
|
-
"esbuild"
|
|
34
|
-
]
|
|
35
|
-
},
|
|
36
30
|
"dependencies": {
|
|
37
31
|
"marked": "^18.1.1",
|
|
38
32
|
"react-docgen-typescript": "^2.4.0",
|
|
@@ -60,15 +54,6 @@
|
|
|
60
54
|
"props",
|
|
61
55
|
"docs"
|
|
62
56
|
],
|
|
63
|
-
"scripts": {
|
|
64
|
-
"test": "node --test test/*.test.ts",
|
|
65
|
-
"typecheck": "tsc --noEmit",
|
|
66
|
-
"build": "pnpm build:package && pnpm --dir examples/jfrader-ui build",
|
|
67
|
-
"build:package": "node scripts/build.mjs",
|
|
68
|
-
"smoke:package": "node scripts/smoke-package.mjs",
|
|
69
|
-
"check:frames": "node scripts/check-example-frames.mjs",
|
|
70
|
-
"prepack": "pnpm build:package"
|
|
71
|
-
},
|
|
72
57
|
"engines": {
|
|
73
58
|
"node": ">=22.12.0"
|
|
74
59
|
},
|
|
@@ -81,5 +66,13 @@
|
|
|
81
66
|
],
|
|
82
67
|
"sideEffects": [
|
|
83
68
|
"**/*.css"
|
|
84
|
-
]
|
|
85
|
-
|
|
69
|
+
],
|
|
70
|
+
"scripts": {
|
|
71
|
+
"test": "node --test test/*.test.ts",
|
|
72
|
+
"typecheck": "tsc --noEmit",
|
|
73
|
+
"build": "pnpm build:package && pnpm --dir examples/jfrader-ui build",
|
|
74
|
+
"build:package": "node scripts/build.mjs",
|
|
75
|
+
"smoke:package": "node scripts/smoke-package.mjs",
|
|
76
|
+
"check:frames": "node scripts/check-example-frames.mjs"
|
|
77
|
+
}
|
|
78
|
+
}
|