@jfrader/storybook-docs 0.9.2 → 0.11.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/build/props.d.ts +5 -1
- package/dist/component-demo.d.ts +2 -3
- package/dist/controls.d.ts +1 -1
- package/dist/index.js +88 -44
- package/dist/prop-docs.d.ts +12 -0
- package/dist/styles.css +22 -0
- package/dist/vite-plugin.js +67 -10
- package/package.json +1 -1
package/dist/build/props.d.ts
CHANGED
|
@@ -1,7 +1,11 @@
|
|
|
1
1
|
import type { ComponentPropsDoc, PropDoc } from '../prop-docs.js';
|
|
2
2
|
export declare function toPropDoc(prop: unknown): PropDoc;
|
|
3
3
|
export declare function createPropsCollector(): {
|
|
4
|
-
collect: (storyFile: string | undefined, entryName: string, slug: string
|
|
4
|
+
collect: (storyFile: string | undefined, entryName: string, slug: string, bases?: {
|
|
5
|
+
name: string;
|
|
6
|
+
slug: string;
|
|
7
|
+
storyFile: string;
|
|
8
|
+
}[]) => ComponentPropsDoc[];
|
|
5
9
|
setBuildMode(value: boolean): void;
|
|
6
10
|
clearPrograms(): void;
|
|
7
11
|
};
|
package/dist/component-demo.d.ts
CHANGED
|
@@ -7,10 +7,9 @@ export interface ComponentDemoProps {
|
|
|
7
7
|
story: string;
|
|
8
8
|
storyName: string;
|
|
9
9
|
authoredStory?: string;
|
|
10
|
-
|
|
10
|
+
notice?: string | null;
|
|
11
11
|
controls: StoryControl[];
|
|
12
12
|
args: Record<string, unknown>;
|
|
13
|
-
unavailable: string | null;
|
|
14
13
|
changed: boolean;
|
|
15
14
|
onControlChange: (name: string, value: unknown) => void;
|
|
16
15
|
onReset: () => void;
|
|
@@ -20,4 +19,4 @@ export interface ComponentDemoProps {
|
|
|
20
19
|
children: ReactNode;
|
|
21
20
|
}
|
|
22
21
|
export declare function hasHorizontalOverflow({ scrollWidth, clientWidth }: Pick<HTMLElement, 'scrollWidth' | 'clientWidth'>): boolean;
|
|
23
|
-
export declare function ComponentDemo({ story, storyName, authoredStory,
|
|
22
|
+
export declare function ComponentDemo({ story, storyName, authoredStory, notice, controls, args, changed, onControlChange, onReset, storyLayout, snippet, codeLanguage, children, }: ComponentDemoProps): import("react").JSX.Element;
|
package/dist/controls.d.ts
CHANGED
|
@@ -38,8 +38,8 @@ export declare function getStoryControls(meta: StoryShape, story: StoryShape, co
|
|
|
38
38
|
[x: string]: unknown;
|
|
39
39
|
};
|
|
40
40
|
controls: StoryControl[];
|
|
41
|
-
unavailable: string | null;
|
|
42
41
|
};
|
|
42
|
+
export declare function skippedNotice(meta: StoryShape, definition: StoryShape): string | null;
|
|
43
43
|
export declare function ControlledStoryFrame({ module, story, componentName, componentDefaults, renderSource }: {
|
|
44
44
|
module: Record<string, unknown>;
|
|
45
45
|
story: string;
|
package/dist/index.js
CHANGED
|
@@ -13,6 +13,15 @@ import { pages, site as site2, theme } from "virtual:storybook-docs/site";
|
|
|
13
13
|
import { useEffect as useEffect6, useMemo as useMemo3, useState as useState7 } from "react";
|
|
14
14
|
import { storySource as storySource2 } from "virtual:storybook-docs/catalog";
|
|
15
15
|
|
|
16
|
+
// src/base.ts
|
|
17
|
+
var STORYBOOK_DOCS_BASE = (() => {
|
|
18
|
+
const globalBase = globalThis.__STORYBOOK_DOCS_BASE__;
|
|
19
|
+
if (globalBase) return globalBase.replace(/\/$/, "");
|
|
20
|
+
const { pathname } = window.location;
|
|
21
|
+
return pathname === "/" || pathname.endsWith(".html") ? "" : pathname.replace(/\/$/, "");
|
|
22
|
+
})();
|
|
23
|
+
var hrefFor = (path) => `${STORYBOOK_DOCS_BASE}${path}`;
|
|
24
|
+
|
|
16
25
|
// src/guidance.tsx
|
|
17
26
|
import { createElement, useEffect, useMemo as useMemo2, useState } from "react";
|
|
18
27
|
import { loadGuidance } from "virtual:storybook-docs/guidance";
|
|
@@ -923,10 +932,9 @@ function ComponentDemo({
|
|
|
923
932
|
story,
|
|
924
933
|
storyName,
|
|
925
934
|
authoredStory,
|
|
926
|
-
|
|
935
|
+
notice,
|
|
927
936
|
controls,
|
|
928
937
|
args,
|
|
929
|
-
unavailable,
|
|
930
938
|
changed,
|
|
931
939
|
onControlChange,
|
|
932
940
|
onReset,
|
|
@@ -977,12 +985,8 @@ function ComponentDemo({
|
|
|
977
985
|
/* @__PURE__ */ jsx6("span", { "data-toc-slot": "", children: /* @__PURE__ */ jsx6(CopyLink, { name: storyName, story }) })
|
|
978
986
|
] }),
|
|
979
987
|
authoredStory ? /* @__PURE__ */ jsx6("p", { className: "story-blurb", children: authoredStory }) : null,
|
|
980
|
-
|
|
981
|
-
|
|
982
|
-
skipped.join(", "),
|
|
983
|
-
". See it in Storybook."
|
|
984
|
-
] }) : null,
|
|
985
|
-
unavailable ? /* @__PURE__ */ jsx6("p", { className: "sd-controls-note", children: unavailable }) : /* @__PURE__ */ jsxs4("div", { className: "sd-controls", role: "group", "aria-labelledby": controlsLabelId, children: [
|
|
988
|
+
notice ? /* @__PURE__ */ jsx6("p", { className: "sd-controls-note", children: notice }) : null,
|
|
989
|
+
controls.length ? /* @__PURE__ */ jsxs4("div", { className: "sd-controls", role: "group", "aria-labelledby": controlsLabelId, children: [
|
|
986
990
|
/* @__PURE__ */ jsxs4("p", { className: "sd-controls-label", id: controlsLabelId, children: [
|
|
987
991
|
"Controls for ",
|
|
988
992
|
storyName
|
|
@@ -999,7 +1003,7 @@ function ComponentDemo({
|
|
|
999
1003
|
)),
|
|
1000
1004
|
/* @__PURE__ */ jsx6("button", { className: "sd-controls-reset", type: "button", disabled: !changed, onClick: onReset, children: "Reset" })
|
|
1001
1005
|
] })
|
|
1002
|
-
] }),
|
|
1006
|
+
] }) : null,
|
|
1003
1007
|
/* @__PURE__ */ jsx6(
|
|
1004
1008
|
"div",
|
|
1005
1009
|
{
|
|
@@ -1068,14 +1072,27 @@ function getStoryControls(meta, story, componentDefaults = {}) {
|
|
|
1068
1072
|
}
|
|
1069
1073
|
return {
|
|
1070
1074
|
args,
|
|
1071
|
-
controls
|
|
1072
|
-
unavailable: controls.length === 0 ? "No controls." : null
|
|
1075
|
+
controls
|
|
1073
1076
|
};
|
|
1074
1077
|
}
|
|
1078
|
+
function skippedNotice(meta, definition) {
|
|
1079
|
+
const hasSetup = Boolean(meta.loaders || definition.loaders || meta.beforeEach || definition.beforeEach);
|
|
1080
|
+
const hasViewport = Boolean(definition.parameters?.viewport ?? meta.parameters?.viewport);
|
|
1081
|
+
if (hasSetup && hasViewport) {
|
|
1082
|
+
return "Setup not run here and shown at this page\u2019s width. Open it in Storybook.";
|
|
1083
|
+
}
|
|
1084
|
+
if (hasSetup) {
|
|
1085
|
+
return "Setup not run here. Open it in Storybook.";
|
|
1086
|
+
}
|
|
1087
|
+
if (hasViewport) {
|
|
1088
|
+
return "Shown at this page\u2019s width. Open it in Storybook.";
|
|
1089
|
+
}
|
|
1090
|
+
return null;
|
|
1091
|
+
}
|
|
1075
1092
|
function ControlledStoryFrame({ module, story, componentName, componentDefaults, renderSource }) {
|
|
1076
1093
|
const meta = module.default ?? {};
|
|
1077
1094
|
const definition = module[story] ?? {};
|
|
1078
|
-
const { args: defaults, controls
|
|
1095
|
+
const { args: defaults, controls } = getStoryControls(meta, definition, componentDefaults);
|
|
1079
1096
|
const [edits, setEdits] = useState5({});
|
|
1080
1097
|
const args = { ...defaults, ...edits };
|
|
1081
1098
|
const changed = Object.entries(edits).some(([name, value]) => !Object.is(value, defaults[name]));
|
|
@@ -1086,8 +1103,7 @@ function ControlledStoryFrame({ module, story, componentName, componentDefaults,
|
|
|
1086
1103
|
const authoredCode = frameSource(meta, definition);
|
|
1087
1104
|
const authoredStory = docsOverride?.description?.story ?? docsMeta?.description?.story;
|
|
1088
1105
|
const storyName = definition.name ?? story;
|
|
1089
|
-
const
|
|
1090
|
-
if (definition.parameters?.viewport ?? meta.parameters?.viewport) skipped.push("viewport");
|
|
1106
|
+
const notice = skippedNotice(meta, definition);
|
|
1091
1107
|
const codeLanguage = authoredCode?.trim() ? docsOverride?.source?.language ?? docsMeta?.source?.language ?? "tsx" : "tsx";
|
|
1092
1108
|
const snippet = buildUsageSnippet({
|
|
1093
1109
|
componentName,
|
|
@@ -1106,10 +1122,9 @@ function ControlledStoryFrame({ module, story, componentName, componentDefaults,
|
|
|
1106
1122
|
story,
|
|
1107
1123
|
storyName,
|
|
1108
1124
|
authoredStory,
|
|
1109
|
-
|
|
1125
|
+
notice,
|
|
1110
1126
|
controls,
|
|
1111
1127
|
args,
|
|
1112
|
-
unavailable,
|
|
1113
1128
|
changed,
|
|
1114
1129
|
storyLayout,
|
|
1115
1130
|
snippet,
|
|
@@ -1156,7 +1171,7 @@ function formatValue(value) {
|
|
|
1156
1171
|
return String(value);
|
|
1157
1172
|
}
|
|
1158
1173
|
function TableFrame({ label, children }) {
|
|
1159
|
-
return /* @__PURE__ */ jsx8("div", { className: "table-scroll", role: "region", "aria-label": label, tabIndex: 0, children: /* @__PURE__ */ jsxs5("table", { children: [
|
|
1174
|
+
return /* @__PURE__ */ jsx8("div", { className: "table-scroll", role: "region", "aria-label": label, tabIndex: 0, children: /* @__PURE__ */ jsxs5("table", { className: "props-table", children: [
|
|
1160
1175
|
/* @__PURE__ */ jsx8("caption", { className: "sr-only", children: label }),
|
|
1161
1176
|
children
|
|
1162
1177
|
] }) });
|
|
@@ -1175,28 +1190,67 @@ function PropNotes({ prop }) {
|
|
|
1175
1190
|
!prop.description && !prop.tags?.length && !prop.inheritedFrom ? "\u2014" : null
|
|
1176
1191
|
] });
|
|
1177
1192
|
}
|
|
1193
|
+
var SHAPE_PREVIEW_FIELDS = 3;
|
|
1194
|
+
function PropType({ prop }) {
|
|
1195
|
+
const signature2 = prop.signatures?.[0];
|
|
1196
|
+
const fields = prop.members?.slice(0, SHAPE_PREVIEW_FIELDS).map((member) => `${member.name}${member.required ? "" : "?"}: \u2026`).join("; ");
|
|
1197
|
+
return /* @__PURE__ */ jsxs5(Fragment3, { children: [
|
|
1198
|
+
/* @__PURE__ */ jsx8("code", { className: signature2 ? "type signature" : "type", tabIndex: signature2 ? 0 : void 0, children: prop.typeUnavailable ? "Not resolved" : signature2?.type ?? prop.type }),
|
|
1199
|
+
signature2 ? /* @__PURE__ */ jsxs5("details", { children: [
|
|
1200
|
+
/* @__PURE__ */ jsx8("summary", { children: "Signature details" }),
|
|
1201
|
+
prop.type !== signature2.type ? /* @__PURE__ */ jsx8("code", { className: "type", children: prop.type }) : null,
|
|
1202
|
+
prop.signatures?.map((item, index) => /* @__PURE__ */ jsxs5("div", { children: [
|
|
1203
|
+
/* @__PURE__ */ jsx8("code", { className: "type", children: item.type }),
|
|
1204
|
+
/* @__PURE__ */ jsx8("dl", { children: item.parameters.filter((parameter) => parameter.description).map((parameter) => /* @__PURE__ */ jsxs5("div", { children: [
|
|
1205
|
+
/* @__PURE__ */ jsx8("dt", { children: /* @__PURE__ */ jsxs5("code", { children: [
|
|
1206
|
+
parameter.name,
|
|
1207
|
+
": ",
|
|
1208
|
+
parameter.type
|
|
1209
|
+
] }) }),
|
|
1210
|
+
/* @__PURE__ */ jsx8("dd", { children: /* @__PURE__ */ jsx8(MarkdownView, { markdown: parameter.description }) })
|
|
1211
|
+
] }, parameter.name)) })
|
|
1212
|
+
] }, index))
|
|
1213
|
+
] }) : null,
|
|
1214
|
+
prop.members?.length ? /* @__PURE__ */ jsxs5("details", { children: [
|
|
1215
|
+
/* @__PURE__ */ jsxs5("summary", { children: [
|
|
1216
|
+
prop.name === "slotProps" ? "Slots" : "Fields",
|
|
1217
|
+
" ",
|
|
1218
|
+
/* @__PURE__ */ jsx8("code", { children: `{ ${fields}${prop.members.length > SHAPE_PREVIEW_FIELDS ? "; \u2026" : ""} }` })
|
|
1219
|
+
] }),
|
|
1220
|
+
/* @__PURE__ */ jsx8("dl", { children: prop.members.map((member) => /* @__PURE__ */ jsxs5("div", { children: [
|
|
1221
|
+
/* @__PURE__ */ jsxs5("dt", { children: [
|
|
1222
|
+
/* @__PURE__ */ jsxs5("code", { children: [
|
|
1223
|
+
member.name,
|
|
1224
|
+
member.required ? "" : "?"
|
|
1225
|
+
] }),
|
|
1226
|
+
member.required ? " (required)" : ""
|
|
1227
|
+
] }),
|
|
1228
|
+
/* @__PURE__ */ jsxs5("dd", { children: [
|
|
1229
|
+
/* @__PURE__ */ jsx8(PropType, { prop: member }),
|
|
1230
|
+
/* @__PURE__ */ jsx8(PropNotes, { prop: member })
|
|
1231
|
+
] })
|
|
1232
|
+
] }, member.name)) })
|
|
1233
|
+
] }) : null
|
|
1234
|
+
] });
|
|
1235
|
+
}
|
|
1236
|
+
function InheritedLinks({ component }) {
|
|
1237
|
+
const bases = Array.from(new Map(component.props.flatMap((prop) => prop.inheritedComponent ? [[prop.inheritedComponent.slug, prop.inheritedComponent]] : [])).values());
|
|
1238
|
+
return bases.length ? /* @__PURE__ */ jsxs5("p", { children: [
|
|
1239
|
+
"Also available from ",
|
|
1240
|
+
bases.map((entry, index) => /* @__PURE__ */ jsxs5("span", { children: [
|
|
1241
|
+
index ? ", " : "",
|
|
1242
|
+
/* @__PURE__ */ jsx8("a", { href: `#${hrefFor(`/components/${entry.slug}`)}`, children: entry.name })
|
|
1243
|
+
] }, entry.slug)),
|
|
1244
|
+
"."
|
|
1245
|
+
] }) : null;
|
|
1246
|
+
}
|
|
1178
1247
|
function PropRows({ props }) {
|
|
1179
1248
|
return props.map((prop) => /* @__PURE__ */ jsxs5("tr", { children: [
|
|
1180
1249
|
/* @__PURE__ */ jsxs5("th", { scope: "row", children: [
|
|
1181
1250
|
/* @__PURE__ */ jsx8("code", { children: prop.name }),
|
|
1182
1251
|
prop.required ? /* @__PURE__ */ jsx8("span", { className: "req", children: "required" }) : null
|
|
1183
1252
|
] }),
|
|
1184
|
-
/* @__PURE__ */
|
|
1185
|
-
/* @__PURE__ */ jsx8("code", { className: "type", children: prop.typeUnavailable ? "Not resolved" : prop.type }),
|
|
1186
|
-
prop.members?.length ? /* @__PURE__ */ jsxs5("details", { children: [
|
|
1187
|
-
/* @__PURE__ */ jsx8("summary", { children: prop.name === "slotProps" ? "Slots" : "Fields" }),
|
|
1188
|
-
/* @__PURE__ */ jsx8("dl", { children: prop.members.map((member) => /* @__PURE__ */ jsxs5("div", { children: [
|
|
1189
|
-
/* @__PURE__ */ jsxs5("dt", { children: [
|
|
1190
|
-
/* @__PURE__ */ jsx8("code", { children: member.name }),
|
|
1191
|
-
member.required ? " (required)" : ""
|
|
1192
|
-
] }),
|
|
1193
|
-
/* @__PURE__ */ jsxs5("dd", { children: [
|
|
1194
|
-
/* @__PURE__ */ jsx8("code", { children: member.type }),
|
|
1195
|
-
/* @__PURE__ */ jsx8(PropNotes, { prop: member })
|
|
1196
|
-
] })
|
|
1197
|
-
] }, member.name)) })
|
|
1198
|
-
] }) : null
|
|
1199
|
-
] }),
|
|
1253
|
+
/* @__PURE__ */ jsx8("td", { children: /* @__PURE__ */ jsx8(PropType, { prop }) }),
|
|
1200
1254
|
/* @__PURE__ */ jsx8("td", { children: /* @__PURE__ */ jsx8("code", { children: prop.defaultValue === "undefined" ? "\u2014" : prop.defaultValue ?? "\u2014" }) }),
|
|
1201
1255
|
/* @__PURE__ */ jsx8("td", { children: /* @__PURE__ */ jsx8(PropNotes, { prop }) })
|
|
1202
1256
|
] }, prop.name));
|
|
@@ -1231,6 +1285,7 @@ function PropsTable({
|
|
|
1231
1285
|
] }) }),
|
|
1232
1286
|
/* @__PURE__ */ jsx8("tbody", { children: /* @__PURE__ */ jsx8(PropRows, { props: component.props.filter((prop) => !prop.inheritedFrom) }) })
|
|
1233
1287
|
] }) : /* @__PURE__ */ jsx8("p", { children: "No component-specific props." }),
|
|
1288
|
+
/* @__PURE__ */ jsx8(InheritedLinks, { component }),
|
|
1234
1289
|
component.props.some((prop) => prop.inheritedFrom) ? /* @__PURE__ */ jsxs5("details", { children: [
|
|
1235
1290
|
/* @__PURE__ */ jsxs5("summary", { children: [
|
|
1236
1291
|
"Inherited props (",
|
|
@@ -1567,17 +1622,6 @@ function TypePage() {
|
|
|
1567
1622
|
// src/pages/overview.tsx
|
|
1568
1623
|
import { catalog, groups, stats } from "virtual:storybook-docs/catalog";
|
|
1569
1624
|
import { site } from "virtual:storybook-docs/site";
|
|
1570
|
-
|
|
1571
|
-
// src/base.ts
|
|
1572
|
-
var STORYBOOK_DOCS_BASE = (() => {
|
|
1573
|
-
const globalBase = globalThis.__STORYBOOK_DOCS_BASE__;
|
|
1574
|
-
if (globalBase) return globalBase.replace(/\/$/, "");
|
|
1575
|
-
const { pathname } = window.location;
|
|
1576
|
-
return pathname === "/" || pathname.endsWith(".html") ? "" : pathname.replace(/\/$/, "");
|
|
1577
|
-
})();
|
|
1578
|
-
var hrefFor = (path) => `${STORYBOOK_DOCS_BASE}${path}`;
|
|
1579
|
-
|
|
1580
|
-
// src/pages/overview.tsx
|
|
1581
1625
|
import { Fragment as Fragment8, jsx as jsx13, jsxs as jsxs10 } from "react/jsx-runtime";
|
|
1582
1626
|
function OverviewPage() {
|
|
1583
1627
|
const startHere = catalog.slice(0, 6);
|
package/dist/prop-docs.d.ts
CHANGED
|
@@ -6,11 +6,23 @@ export interface PropDoc {
|
|
|
6
6
|
defaultValue: string | null;
|
|
7
7
|
description: string;
|
|
8
8
|
inheritedFrom?: string;
|
|
9
|
+
inheritedComponent?: {
|
|
10
|
+
name: string;
|
|
11
|
+
slug: string;
|
|
12
|
+
};
|
|
9
13
|
tags?: {
|
|
10
14
|
name: string;
|
|
11
15
|
text: string;
|
|
12
16
|
}[];
|
|
13
17
|
members?: PropDoc[];
|
|
18
|
+
signatures?: {
|
|
19
|
+
type: string;
|
|
20
|
+
parameters: {
|
|
21
|
+
name: string;
|
|
22
|
+
type: string;
|
|
23
|
+
description: string;
|
|
24
|
+
}[];
|
|
25
|
+
}[];
|
|
14
26
|
}
|
|
15
27
|
export interface ComponentPropsDoc {
|
|
16
28
|
name: string;
|
package/dist/styles.css
CHANGED
|
@@ -426,8 +426,30 @@ pre.code {
|
|
|
426
426
|
}
|
|
427
427
|
code.type {
|
|
428
428
|
white-space: pre-wrap;
|
|
429
|
+
overflow-wrap: anywhere;
|
|
430
|
+
display: inline-block;
|
|
431
|
+
max-inline-size: 100%;
|
|
432
|
+
}
|
|
433
|
+
code.signature {
|
|
434
|
+
display: block;
|
|
435
|
+
white-space: pre;
|
|
436
|
+
overflow-x: auto;
|
|
437
|
+
padding-bottom: 4px;
|
|
438
|
+
}
|
|
439
|
+
.table-scroll > .props-table {
|
|
440
|
+
table-layout: fixed;
|
|
441
|
+
min-inline-size: 640px;
|
|
442
|
+
}
|
|
443
|
+
.props-table thead th:nth-child(1) { width: 18%; }
|
|
444
|
+
.props-table thead th:nth-child(2) { width: 34%; }
|
|
445
|
+
.props-table thead th:nth-child(3) { width: 12%; }
|
|
446
|
+
.props-table thead th:nth-child(4) { width: 36%; }
|
|
447
|
+
.props-table :is(th, td) {
|
|
448
|
+
overflow-wrap: anywhere;
|
|
429
449
|
}
|
|
430
450
|
.req {
|
|
451
|
+
display: inline-block;
|
|
452
|
+
white-space: nowrap;
|
|
431
453
|
margin-left: 6px;
|
|
432
454
|
font-size: 10.5px;
|
|
433
455
|
letter-spacing: 0.05em;
|
package/dist/vite-plugin.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
// src/vite-plugin.ts
|
|
2
|
-
import { readFileSync as readFileSync3, realpathSync } from "node:fs";
|
|
2
|
+
import { readFileSync as readFileSync3, realpathSync as realpathSync2 } from "node:fs";
|
|
3
3
|
import path7 from "node:path";
|
|
4
4
|
|
|
5
5
|
// src/build/catalog.ts
|
|
@@ -248,7 +248,7 @@ function globalStylesCode(engineStyles, css = []) {
|
|
|
248
248
|
}
|
|
249
249
|
|
|
250
250
|
// src/build/props.ts
|
|
251
|
-
import { readdirSync as readdirSync2 } from "node:fs";
|
|
251
|
+
import { readdirSync as readdirSync2, realpathSync } from "node:fs";
|
|
252
252
|
import path3 from "node:path";
|
|
253
253
|
import { withCompilerOptions } from "react-docgen-typescript";
|
|
254
254
|
import ts from "typescript";
|
|
@@ -319,7 +319,7 @@ function createPropsCollector() {
|
|
|
319
319
|
cache.program = ts.createProgram(sources, compilerOptions, cache.host, cache.program);
|
|
320
320
|
return cache.program;
|
|
321
321
|
};
|
|
322
|
-
const collect = (storyFile, entryName, slug) => {
|
|
322
|
+
const collect = (storyFile, entryName, slug, bases = []) => {
|
|
323
323
|
if (storyFile) {
|
|
324
324
|
const directory = path3.dirname(storyFile);
|
|
325
325
|
const sources = readdirSync2(directory).filter((file) => /\.tsx?$/.test(file) && !file.endsWith(".stories.tsx")).map((file) => path3.join(directory, file));
|
|
@@ -331,7 +331,7 @@ function createPropsCollector() {
|
|
|
331
331
|
})).filter((component) => component.props.length > 0);
|
|
332
332
|
const matchesOwnName = (name) => entryName.length > 0 && name.toLowerCase().startsWith(entryName.toLowerCase());
|
|
333
333
|
const relevant = parsed.some((component) => matchesOwnName(component.name)) ? parsed.filter((component) => matchesOwnName(component.name)) : parsed;
|
|
334
|
-
const typed = collectTypeProps(sources, entryName);
|
|
334
|
+
const typed = collectTypeProps(sources, entryName, bases);
|
|
335
335
|
return mergePropsTables(typed.length > 0 ? [...relevant.filter((table) => typed.some((item) => item.name === table.name)), ...typed] : relevant);
|
|
336
336
|
} catch (cause) {
|
|
337
337
|
console.warn(`storybook-docs: could not read props for "${slug}" (${String(cause)})`);
|
|
@@ -340,10 +340,45 @@ function createPropsCollector() {
|
|
|
340
340
|
}
|
|
341
341
|
return [];
|
|
342
342
|
};
|
|
343
|
-
const collectTypeProps = (sources, entryName) => {
|
|
343
|
+
const collectTypeProps = (sources, entryName, bases) => {
|
|
344
344
|
const program = createPropsProgram(sources, TYPE_PROPS_COMPILER_OPTIONS);
|
|
345
345
|
const checker = program.getTypeChecker();
|
|
346
346
|
const tables = [];
|
|
347
|
+
const baseContracts = bases.filter((base) => base.name !== entryName).map((base) => ({
|
|
348
|
+
...base,
|
|
349
|
+
directory: path3.dirname(realpathSync(base.storyFile)),
|
|
350
|
+
declarations: /* @__PURE__ */ new Set()
|
|
351
|
+
}));
|
|
352
|
+
const readContract = (type, location, declarations, depth = 0) => {
|
|
353
|
+
for (const signature of type.getCallSignatures()) {
|
|
354
|
+
const parameter = signature.getParameters()[0];
|
|
355
|
+
if (!parameter) continue;
|
|
356
|
+
const propsType = checker.getTypeOfSymbolAtLocation(parameter, signature.getDeclaration() ?? location);
|
|
357
|
+
for (const prop of checker.getPropertiesOfType(propsType)) {
|
|
358
|
+
prop.declarations?.forEach((declaration) => declarations.add(declaration));
|
|
359
|
+
}
|
|
360
|
+
}
|
|
361
|
+
if (depth >= 2) return;
|
|
362
|
+
for (const member of checker.getPropertiesOfType(type)) {
|
|
363
|
+
if (["bind", "call", "apply"].includes(member.getName())) continue;
|
|
364
|
+
const memberType = checker.getTypeOfSymbolAtLocation(member, member.valueDeclaration ?? location);
|
|
365
|
+
if (memberType.getCallSignatures().length) readContract(memberType, location, declarations, depth + 1);
|
|
366
|
+
}
|
|
367
|
+
};
|
|
368
|
+
for (const source of program.getSourceFiles()) {
|
|
369
|
+
if (isExternal(source.fileName)) continue;
|
|
370
|
+
const directory = path3.dirname(realpathSync(source.fileName));
|
|
371
|
+
const candidates = baseContracts.filter((base) => base.directory === directory);
|
|
372
|
+
if (!candidates.length) continue;
|
|
373
|
+
const module = checker.getSymbolAtLocation(source);
|
|
374
|
+
if (!module) continue;
|
|
375
|
+
for (const symbol of checker.getExportsOfModule(module)) {
|
|
376
|
+
for (const base of candidates.filter((candidate) => candidate.name === symbol.getName())) {
|
|
377
|
+
const target = symbol.flags & ts.SymbolFlags.Alias ? checker.getAliasedSymbol(symbol) : symbol;
|
|
378
|
+
readContract(checker.getTypeOfSymbolAtLocation(target, target.valueDeclaration ?? source), source, base.declarations);
|
|
379
|
+
}
|
|
380
|
+
}
|
|
381
|
+
}
|
|
347
382
|
const unresolved = /* @__PURE__ */ Symbol("unresolved");
|
|
348
383
|
const literalValue = (node, seen = /* @__PURE__ */ new Set()) => {
|
|
349
384
|
if (seen.has(node)) return unresolved;
|
|
@@ -391,9 +426,26 @@ function createPropsCollector() {
|
|
|
391
426
|
const printedType = checker.typeToString(propType, void 0, typeFlags);
|
|
392
427
|
const displayType = literalUnion && propType.isUnion() ? propType.types.filter((part) => !optional || !(part.flags & ts.TypeFlags.Undefined)).map((part) => checker.typeToString(part, void 0, typeFlags)).join(" | ").replace(/false \| true/g, "boolean") : optional ? printedType.replace(/ \| undefined$/, "") : printedType;
|
|
393
428
|
const parent = declaration?.parent;
|
|
394
|
-
const
|
|
429
|
+
const declarationName = declaration ? parent && (ts.isInterfaceDeclaration(parent) || ts.isTypeAliasDeclaration(parent)) ? parent.name.text : path3.basename(declaration.getSourceFile().fileName) : void 0;
|
|
430
|
+
const inheritedComponent = declaration ? baseContracts.find(
|
|
431
|
+
(base) => base.declarations.has(declaration) && base.directory === path3.dirname(realpathSync(declaration.getSourceFile().fileName))
|
|
432
|
+
) : void 0;
|
|
433
|
+
const inheritedFrom = declaration && (inheritedComponent || isExternal(declaration.getSourceFile().fileName) || !sources.includes(declaration.getSourceFile().fileName)) ? declarationName : void 0;
|
|
395
434
|
const memberType = checker.getNonNullableType(propType);
|
|
396
|
-
const
|
|
435
|
+
const nonCallableAlternatives = propType.isUnion() ? propType.types.filter((part) => Boolean(part.flags & (ts.TypeFlags.Null | ts.TypeFlags.Undefined)) && (!optional || !(part.flags & ts.TypeFlags.Undefined))).map((part) => checker.typeToString(part, void 0, typeFlags)) : [];
|
|
436
|
+
const signatures = memberType.getCallSignatures().map((signature) => {
|
|
437
|
+
const signatureType = checker.signatureToString(signature, location, typeFlags | ts.TypeFormatFlags.WriteArrowStyleSignature);
|
|
438
|
+
return {
|
|
439
|
+
type: nonCallableAlternatives.length ? `(${signatureType}) | ${nonCallableAlternatives.join(" | ")}` : signatureType,
|
|
440
|
+
parameters: signature.getParameters().map((parameter) => ({
|
|
441
|
+
name: parameter.getName(),
|
|
442
|
+
type: checker.typeToString(checker.getTypeOfSymbolAtLocation(parameter, parameter.valueDeclaration ?? location), location, typeFlags),
|
|
443
|
+
description: ts.displayPartsToString(parameter.getDocumentationComment(checker)).trim()
|
|
444
|
+
}))
|
|
445
|
+
};
|
|
446
|
+
});
|
|
447
|
+
const objectTypes = memberType.isUnion() ? memberType.types : [memberType];
|
|
448
|
+
const hasLocalMembers = objectTypes.every((part) => Boolean(part.flags & (ts.TypeFlags.Object | ts.TypeFlags.Intersection))) && !checker.isArrayType(memberType) && !checker.isTupleType(memberType) && !signatures.length && checker.getPropertiesOfType(memberType).some((member) => member.declarations?.some((node) => !isExternal(node.getSourceFile().fileName)));
|
|
397
449
|
return {
|
|
398
450
|
name: symbol.getName(),
|
|
399
451
|
type: displayType || "unknown",
|
|
@@ -402,6 +454,8 @@ function createPropsCollector() {
|
|
|
402
454
|
defaultValue: null,
|
|
403
455
|
description: ts.displayPartsToString(symbol.getDocumentationComment(checker)).trim(),
|
|
404
456
|
inheritedFrom,
|
|
457
|
+
inheritedComponent: inheritedComponent ? { name: inheritedComponent.name, slug: inheritedComponent.slug } : void 0,
|
|
458
|
+
signatures: signatures.length ? signatures : void 0,
|
|
405
459
|
tags: symbol.getJsDocTags(checker).filter((tag) => ["deprecated", "since", "example"].includes(tag.name)).map((tag) => ({ name: tag.name, text: ts.displayPartsToString(tag.text) })),
|
|
406
460
|
members: depth === 0 && (symbol.getName() === "slotProps" || !inheritedFrom && hasLocalMembers) ? describeProps(memberType, location, depth + 1) : void 0
|
|
407
461
|
};
|
|
@@ -928,7 +982,10 @@ function storybookDocs(options2) {
|
|
|
928
982
|
let components = propsCache.get(slug);
|
|
929
983
|
if (!components) {
|
|
930
984
|
const name = catalog.entries.find((entry) => entry.slug === slug)?.name ?? "";
|
|
931
|
-
components = propsCollector.collect(catalog.files.get(slug), name, slug)
|
|
985
|
+
components = propsCollector.collect(catalog.files.get(slug), name, slug, catalog.entries.flatMap((entry) => {
|
|
986
|
+
const storyFile = catalog.files.get(entry.slug);
|
|
987
|
+
return storyFile ? [{ name: entry.name, slug: entry.slug, storyFile }] : [];
|
|
988
|
+
}));
|
|
932
989
|
propsCache.set(slug, components);
|
|
933
990
|
}
|
|
934
991
|
return propsCode(components);
|
|
@@ -980,7 +1037,7 @@ export const storySource = ${JSON.stringify(config.stories.from)};`,
|
|
|
980
1037
|
},
|
|
981
1038
|
resolveId(id) {
|
|
982
1039
|
if (id.startsWith(VIRTUAL_PREFIX)) return `\0${id}`;
|
|
983
|
-
if (id.startsWith(FILE_PREFIX)) return
|
|
1040
|
+
if (id.startsWith(FILE_PREFIX)) return realpathSync2(id.slice(FILE_PREFIX.length));
|
|
984
1041
|
if (id === "storybook/test") return `\0${VIRTUAL_PREFIX}stub-storybook-test`;
|
|
985
1042
|
return null;
|
|
986
1043
|
},
|
|
@@ -993,7 +1050,7 @@ export const storySource = ${JSON.stringify(config.stories.from)};`,
|
|
|
993
1050
|
if (name.startsWith("story-sources/")) {
|
|
994
1051
|
const storyFile = catalog.files.get(name.slice("story-sources/".length));
|
|
995
1052
|
if (!storyFile) return storySourcesCode({});
|
|
996
|
-
const file =
|
|
1053
|
+
const file = realpathSync2(storyFile);
|
|
997
1054
|
let sources = storySourcesCache.get(file);
|
|
998
1055
|
if (!sources) {
|
|
999
1056
|
sources = extractStorySources(readFileSync3(file, "utf8"));
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@jfrader/storybook-docs",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.11.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": {
|