@weasel-js/forge 1.15.2 → 1.16.1

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.
Files changed (35) hide show
  1. package/README.md +14 -0
  2. package/dist/{FrameController-BM6xuEfY.d.ts → FrameController-D9CddmJg.d.ts} +2 -0
  3. package/dist/{chunk-PPB7VP6R.js → chunk-5B4RDEF3.js} +87 -7
  4. package/dist/chunk-5B4RDEF3.js.map +1 -0
  5. package/dist/{chunk-MRYXJTDO.js → chunk-7YVJS4QS.js} +3 -3
  6. package/dist/{chunk-MRYXJTDO.js.map → chunk-7YVJS4QS.js.map} +1 -1
  7. package/dist/{chunk-PGLOYXDP.js → chunk-EVPVBDHM.js} +31 -5
  8. package/dist/chunk-EVPVBDHM.js.map +1 -0
  9. package/dist/{chunk-SZ2SMRE6.js → chunk-KNBEHCFD.js} +3 -29
  10. package/dist/chunk-KNBEHCFD.js.map +1 -0
  11. package/dist/{chunk-5WS67HMU.js → chunk-PN4IFL5E.js} +6 -3
  12. package/dist/chunk-PN4IFL5E.js.map +1 -0
  13. package/dist/{chunk-RVJHUY7W.js → chunk-ZGELUE2H.js} +3 -3
  14. package/dist/{chunk-RVJHUY7W.js.map → chunk-ZGELUE2H.js.map} +1 -1
  15. package/dist/{config-DOjWyIui.d.ts → config-Ey2RPFrg.d.ts} +1 -1
  16. package/dist/frame/index.css +100 -0
  17. package/dist/frame/index.css.map +1 -1
  18. package/dist/frame/index.d.ts +4 -4
  19. package/dist/frame/index.js +4 -4
  20. package/dist/index.d.ts +3 -3
  21. package/dist/{mountFrame-CRPAjg1M.d.ts → mountFrame-AZzyw6bu.d.ts} +1 -1
  22. package/dist/shell/index.css +100 -0
  23. package/dist/shell/index.css.map +1 -1
  24. package/dist/shell/index.d.ts +4 -4
  25. package/dist/shell/index.js +7 -7
  26. package/dist/test/index.d.ts +1 -1
  27. package/dist/test/index.js +3 -3
  28. package/dist/vite/index.d.ts +5 -0
  29. package/dist/vite/index.js +271 -56
  30. package/dist/vite/index.js.map +1 -1
  31. package/package.json +11 -11
  32. package/dist/chunk-5WS67HMU.js.map +0 -1
  33. package/dist/chunk-PGLOYXDP.js.map +0 -1
  34. package/dist/chunk-PPB7VP6R.js.map +0 -1
  35. package/dist/chunk-SZ2SMRE6.js.map +0 -1
@@ -1,7 +1,7 @@
1
- import { CAPTURE_PAGES, DEFAULT_TITLE, ISSUES_PATH, CAPTURE_PATH, issueLabel, parsePayload, messageOf } from '../chunk-MRYXJTDO.js';
2
- import { byComponent } from '../chunk-RVJHUY7W.js';
1
+ import { CAPTURE_PAGES, DEFAULT_TITLE, ISSUES_PATH, CAPTURE_PATH, issueLabel, parsePayload, messageOf } from '../chunk-7YVJS4QS.js';
2
+ import { byComponent } from '../chunk-ZGELUE2H.js';
3
3
  import { isGallery } from '../chunk-VUPN73JP.js';
4
- import { PROP_ARG_TYPES_EXPORT, storyNameFromExport, storyId } from '../chunk-5WS67HMU.js';
4
+ import { PROP_ARG_TYPES_EXPORT, API_EXPORT, storyNameFromExport, storyId } from '../chunk-PN4IFL5E.js';
5
5
  import { readFileSync, mkdtempSync, existsSync, mkdirSync, writeFileSync, globSync, statSync, watch, rmSync } from 'fs';
6
6
  import { resolve, relative, sep, isAbsolute, join, dirname, basename, matchesGlob, posix } from 'path';
7
7
  import { parse } from '@babel/parser';
@@ -55,6 +55,68 @@ function hoistPages(bundle, emit) {
55
55
  emit({ type: "asset", fileName: `${name}.html`, source: up(asset.source) });
56
56
  }
57
57
  }
58
+
59
+ // src/vite/componentOf.ts
60
+ var titleStandIn = (title) => title.split("/").pop()?.replace(/\s+/g, "");
61
+ function componentOf(tsm, checker, source, fallback) {
62
+ const module = checker.getSymbolAtLocation(source);
63
+ const exported = module && checker.tryGetMemberInModuleExports("default", module);
64
+ if (!exported) return null;
65
+ const meta = checker.getTypeOfSymbolAtLocation(resolved(tsm, checker, exported), source);
66
+ let named = meta.getProperty("component");
67
+ let symbol = named && assigned(tsm, checker, resolved(tsm, checker, exported));
68
+ const local = !symbol || symbol.getDeclarations()?.some((declaration2) => declaration2.getSourceFile() === source);
69
+ const imported = local && fallback ? importNamed(tsm, checker, source, fallback) : void 0;
70
+ if (imported) {
71
+ named = void 0;
72
+ symbol = imported;
73
+ }
74
+ if (!named && !symbol) return null;
75
+ const type = checker.getNonNullableType(checker.getTypeOfSymbolAtLocation(symbol ?? named, source));
76
+ const declaration = symbol?.getDeclarations()?.[0];
77
+ for (const part of type.isUnion() ? type.types : [type]) {
78
+ const [call] = part.getCallSignatures();
79
+ const [param] = call?.getParameters() ?? [];
80
+ if (call) return { props: param ? checker.getTypeOfSymbolAtLocation(param, source) : null, declaration };
81
+ const instance = part.getConstructSignatures()[0]?.getReturnType();
82
+ const held = instance?.getProperty("props");
83
+ if (held) return { props: checker.getTypeOfSymbolAtLocation(held, source), declaration };
84
+ }
85
+ return null;
86
+ }
87
+ var resolved = (tsm, checker, symbol) => symbol.flags & tsm.SymbolFlags.Alias ? checker.getAliasedSymbol(symbol) : symbol;
88
+ function assigned(tsm, checker, meta) {
89
+ const declaration = meta.getDeclarations()?.[0];
90
+ let node = declaration && tsm.isVariableDeclaration(declaration) ? declaration.initializer : declaration && tsm.isExportAssignment(declaration) ? declaration.expression : void 0;
91
+ while (node && !tsm.isObjectLiteralExpression(node)) {
92
+ if (tsm.isCallExpression(node)) node = node.arguments[0];
93
+ else if (tsm.isParenthesizedExpression(node) || tsm.isAsExpression(node) || tsm.isSatisfiesExpression(node)) {
94
+ node = node.expression;
95
+ } else node = void 0;
96
+ }
97
+ const property = node?.properties.find((p) => p.name && tsm.isIdentifier(p.name) && p.name.text === "component");
98
+ let value;
99
+ if (property && tsm.isShorthandPropertyAssignment(property)) value = checker.getShorthandAssignmentValueSymbol(property);
100
+ else if (property && tsm.isPropertyAssignment(property)) value = checker.getSymbolAtLocation(property.initializer);
101
+ return value && resolved(tsm, checker, value);
102
+ }
103
+ function importNamed(tsm, checker, source, name) {
104
+ for (const statement of source.statements) {
105
+ if (!tsm.isImportDeclaration(statement)) continue;
106
+ const clause = statement.importClause;
107
+ const bindings = clause?.namedBindings;
108
+ const names = [
109
+ ...clause?.name ? [clause.name] : [],
110
+ ...bindings && tsm.isNamedImports(bindings) ? bindings.elements.map((element) => element.name) : []
111
+ ];
112
+ const found = names.find((id) => id.text === name);
113
+ const symbol = found && checker.getSymbolAtLocation(found);
114
+ if (symbol) return resolved(tsm, checker, symbol);
115
+ }
116
+ return void 0;
117
+ }
118
+
119
+ // src/vite/depGraph.ts
58
120
  var keyOf = (file, local) => `${file}#${local}`;
59
121
  var fileOfKey = (key) => key.slice(0, key.lastIndexOf("#"));
60
122
  var SCRIPT = /\.[cm]?[jt]sx?$/;
@@ -130,10 +192,10 @@ function createDepGraph({ root, read }) {
130
192
  const target = await resolveFrom(imp.spec, importer);
131
193
  return target ? declaring(target, imp.imported, depth) : null;
132
194
  };
133
- const componentOf = async (entry) => {
195
+ const componentOf2 = async (entry) => {
134
196
  const mod = info(entry.file);
135
197
  if (!mod) return null;
136
- const byTitle = entry.title.split("/").pop()?.replace(/\s+/g, "");
198
+ const byTitle = titleStandIn(entry.title);
137
199
  for (const local of [entry.componentName, byTitle]) {
138
200
  const imp = local ? mod.imports.get(local) : void 0;
139
201
  const key = imp ? await importKey(entry.file, imp) : null;
@@ -153,7 +215,7 @@ function createDepGraph({ root, read }) {
153
215
  for (const [title, list] of titles) {
154
216
  let key = null;
155
217
  for (const file of new Set(list.map((e) => e.file))) {
156
- key = await componentOf(list.find((e) => e.file === file));
218
+ key = await componentOf2(list.find((e) => e.file === file));
157
219
  if (key) break;
158
220
  }
159
221
  components.set(title, key);
@@ -929,9 +991,9 @@ function createWrapperResolver(read) {
929
991
  }
930
992
 
931
993
  // src/vite/indexStory.ts
932
- function indexStory(code, file, source, resolved) {
933
- const foreign = resolved ? foreignFrom(resolved.foreign) : void 0;
934
- return indexFile(code, file, autoTitle(file, source.root, source.stories), resolved?.wrappers, foreign);
994
+ function indexStory(code, file, source, resolved2) {
995
+ const foreign = resolved2 ? foreignFrom(resolved2.foreign) : void 0;
996
+ return indexFile(code, file, autoTitle(file, source.root, source.stories), resolved2?.wrappers, foreign);
935
997
  }
936
998
  async function indexStoryResolved(code, file, source, resolve6, decide = createWrapperResolver((path) => readFileSync(path, "utf8"))) {
937
999
  const resolution = await decide(file, foreignCallees(code, file), resolve6);
@@ -949,9 +1011,139 @@ function ownEntries(realms) {
949
1011
  }
950
1012
  return [];
951
1013
  }
1014
+
1015
+ // src/vite/apiTable.ts
1016
+ var RESERVED = /* @__PURE__ */ new Set(["ref", "key"]);
1017
+ var IN_PACKAGES = /[\\/]node_modules[\\/]/;
1018
+ function apiTable(reading, declaration, props) {
1019
+ const { checker } = reading;
1020
+ const sources = /* @__PURE__ */ new Set();
1021
+ const record2 = (symbol) => {
1022
+ for (const file of filesOf(symbol)) if (!IN_PACKAGES.test(file)) sources.add(file);
1023
+ };
1024
+ const defaults = declaration ? destructuredDefaults(reading.tsm, declaration) : /* @__PURE__ */ new Map();
1025
+ const listed = [];
1026
+ const inherited = /* @__PURE__ */ new Map();
1027
+ let ref = null;
1028
+ for (const prop2 of props ? checker.getPropertiesOfType(checker.getApparentType(props)) : []) {
1029
+ const name = prop2.getName();
1030
+ if (name === "ref") ref = refOf(reading, prop2, record2);
1031
+ if (RESERVED.has(name)) continue;
1032
+ const files = filesOf(prop2);
1033
+ if (files.length > 0 && files.every(reading.skipped)) {
1034
+ const from = containerName(reading.tsm, prop2) ?? packageOf2(files[0]);
1035
+ inherited.set(from, (inherited.get(from) ?? 0) + 1);
1036
+ continue;
1037
+ }
1038
+ listed.push(propEntry(reading, prop2, defaults.get(name)));
1039
+ record2(prop2);
1040
+ }
1041
+ return {
1042
+ props: listed,
1043
+ inherited: [...inherited].map(([from, count]) => ({ from, count })),
1044
+ ref,
1045
+ sources: [...sources]
1046
+ };
1047
+ }
1048
+ var filesOf = (symbol) => (symbol.getDeclarations() ?? []).map((declaration) => declaration.getSourceFile().fileName);
1049
+ var docOf2 = ({ tsm, checker }, symbol) => tsm.displayPartsToString(symbol.getDocumentationComment(checker)).replace(/\s+/g, " ").trim();
1050
+ function tagText({ tsm, checker }, symbol, names) {
1051
+ const tag = symbol.getJsDocTags(checker).find((t) => names.includes(t.name));
1052
+ return tag ? tsm.displayPartsToString(tag.text).trim() : void 0;
1053
+ }
1054
+ function propEntry(reading, prop2, destructured) {
1055
+ const entry = {
1056
+ name: prop2.getName(),
1057
+ type: writtenType(reading, prop2),
1058
+ required: !(prop2.flags & reading.tsm.SymbolFlags.Optional)
1059
+ };
1060
+ const fallback = destructured ?? tagText(reading, prop2, ["default", "defaultValue"]);
1061
+ if (fallback) entry.default = fallback;
1062
+ const description = docOf2(reading, prop2);
1063
+ if (description) entry.description = description;
1064
+ const deprecated = tagText(reading, prop2, ["deprecated"]);
1065
+ if (deprecated !== void 0) entry.deprecated = deprecated;
1066
+ return entry;
1067
+ }
1068
+ function writtenType({ tsm, checker, at }, symbol) {
1069
+ const type = checker.getNonNullableType(checker.getTypeOfSymbolAtLocation(symbol, at));
1070
+ const [declaration, ...others] = symbol.getDeclarations() ?? [];
1071
+ const node = declaration && others.length === 0 && tsm.isPropertySignature(declaration) ? declaration.type : void 0;
1072
+ if (node && checker.getNonNullableType(checker.getTypeFromTypeNode(node)) === type) return node.getText().replace(/\s+/g, " ");
1073
+ return checker.typeToString(type, void 0, tsm.TypeFormatFlags.NoTruncation);
1074
+ }
1075
+ function packageOf2(file) {
1076
+ const parts = file.split(/[\\/]/);
1077
+ const at = parts.lastIndexOf("node_modules");
1078
+ if (at < 0 || at + 1 >= parts.length) return parts.at(-1) ?? file;
1079
+ const name = parts[at + 1];
1080
+ return name.startsWith("@") && parts[at + 2] ? `${name}/${parts[at + 2]}` : name;
1081
+ }
1082
+ function containerName(tsm, prop2) {
1083
+ const parent = prop2.getDeclarations()?.[0]?.parent;
1084
+ if (!parent) return void 0;
1085
+ if (tsm.isInterfaceDeclaration(parent) || tsm.isClassDeclaration(parent)) return parent.name?.text;
1086
+ if (tsm.isTypeLiteralNode(parent) && tsm.isTypeAliasDeclaration(parent.parent)) return parent.parent.name.text;
1087
+ return void 0;
1088
+ }
1089
+ function refOf(reading, prop2, record2) {
1090
+ const { tsm, checker, at } = reading;
1091
+ const type = checker.getNonNullableType(checker.getTypeOfSymbolAtLocation(prop2, at));
1092
+ for (const part of type.isUnion() ? type.types : [type]) {
1093
+ const current = part.getProperty("current");
1094
+ if (!current) continue;
1095
+ const held = checker.getNonNullableType(checker.getTypeOfSymbolAtLocation(current, at));
1096
+ const name = checker.typeToString(held, void 0, tsm.TypeFormatFlags.NoTruncation);
1097
+ const declared = (held.getSymbol() ?? held.aliasSymbol)?.getDeclarations() ?? [];
1098
+ if (declared.length > 0 && declared.every((d) => reading.platform(d.getSourceFile().fileName))) {
1099
+ return { type: name, members: [] };
1100
+ }
1101
+ const members = checker.getPropertiesOfType(held).map((member) => {
1102
+ record2(member);
1103
+ return memberEntry(reading, member);
1104
+ });
1105
+ return { type: name, members };
1106
+ }
1107
+ return null;
1108
+ }
1109
+ function memberEntry(reading, member) {
1110
+ const { tsm, checker, at } = reading;
1111
+ const type = checker.getTypeOfSymbolAtLocation(member, at);
1112
+ const [call] = type.getCallSignatures();
1113
+ const declarations = member.getDeclarations() ?? [];
1114
+ const entry = {
1115
+ name: member.getName(),
1116
+ kind: call ? "method" : "property",
1117
+ signature: call ? checker.signatureToString(call, void 0, tsm.TypeFormatFlags.WriteArrowStyleSignature | tsm.TypeFormatFlags.NoTruncation) : checker.typeToString(type, void 0, tsm.TypeFormatFlags.NoTruncation),
1118
+ readonly: declarations.some((d) => (tsm.getCombinedModifierFlags(d) & tsm.ModifierFlags.Readonly) !== 0)
1119
+ };
1120
+ const description = docOf2(reading, member);
1121
+ if (description) entry.description = description;
1122
+ return entry;
1123
+ }
1124
+ function destructuredDefaults(tsm, declaration) {
1125
+ const defaults = /* @__PURE__ */ new Map();
1126
+ let node = tsm.isVariableDeclaration(declaration) ? declaration.initializer : declaration;
1127
+ while (node && (tsm.isCallExpression(node) || tsm.isParenthesizedExpression(node) || tsm.isAsExpression(node))) {
1128
+ node = tsm.isCallExpression(node) ? node.arguments[0] : node.expression;
1129
+ }
1130
+ if (!node || !(tsm.isArrowFunction(node) || tsm.isFunctionExpression(node) || tsm.isFunctionDeclaration(node))) {
1131
+ return defaults;
1132
+ }
1133
+ const pattern = node.parameters[0]?.name;
1134
+ if (!pattern || !tsm.isObjectBindingPattern(pattern)) return defaults;
1135
+ for (const element of pattern.elements) {
1136
+ const key = element.propertyName ?? element.name;
1137
+ if (element.initializer && tsm.isIdentifier(key)) defaults.set(key.text, element.initializer.getText());
1138
+ }
1139
+ return defaults;
1140
+ }
1141
+
1142
+ // src/vite/propTypes.ts
952
1143
  var PLATFORM = /[\\/]node_modules[\\/](@types[\\/]react(-dom)?|typescript)[\\/]/;
953
1144
  async function createPropReader(root, stories, { skip } = {}) {
954
- const skipped = (file) => PLATFORM.test(file) || skip?.(file) === true;
1145
+ const platform = (file) => PLATFORM.test(file);
1146
+ const skipped = (file) => platform(file) || skip?.(file) === true;
955
1147
  let tsm;
956
1148
  try {
957
1149
  tsm = (await import('typescript')).default;
@@ -990,38 +1182,29 @@ async function createPropReader(root, stories, { skip } = {}) {
990
1182
  getDirectories: sys.getDirectories
991
1183
  };
992
1184
  const service = tsm.createLanguageService(host, tsm.createDocumentRegistry());
1185
+ const sourceOf = (file) => {
1186
+ const program = service.getProgram();
1187
+ const source = program?.getSourceFile(file);
1188
+ return program && source ? { checker: program.getTypeChecker(), source } : null;
1189
+ };
993
1190
  return {
994
1191
  read(file) {
995
- const program = service.getProgram();
996
- const source = program?.getSourceFile(file);
997
- if (!program || !source) return null;
998
- const checker = program.getTypeChecker();
999
- const props = componentProps(tsm, checker, source);
1192
+ const found = sourceOf(file);
1193
+ if (!found) return null;
1194
+ const { checker, source } = found;
1195
+ const props = componentOf(tsm, checker, source)?.props;
1000
1196
  return props ? propTable(tsm, checker, props, source, skipped) : null;
1197
+ },
1198
+ api(file, fallback) {
1199
+ const found = sourceOf(file);
1200
+ if (!found) return null;
1201
+ const { checker, source } = found;
1202
+ const component = componentOf(tsm, checker, source, fallback);
1203
+ if (!component) return null;
1204
+ return apiTable({ tsm, checker, at: source, skipped, platform }, component.declaration, component.props);
1001
1205
  }
1002
1206
  };
1003
1207
  }
1004
- function componentProps(tsm, checker, source) {
1005
- const module = checker.getSymbolAtLocation(source);
1006
- const exported = module && checker.tryGetMemberInModuleExports("default", module);
1007
- if (!exported) return null;
1008
- const meta = checker.getTypeOfSymbolAtLocation(
1009
- exported.flags & tsm.SymbolFlags.Alias ? checker.getAliasedSymbol(exported) : exported,
1010
- source
1011
- );
1012
- const named = meta.getProperty("component");
1013
- if (!named) return null;
1014
- const component = checker.getNonNullableType(checker.getTypeOfSymbolAtLocation(named, source));
1015
- for (const part of component.isUnion() ? component.types : [component]) {
1016
- const [call] = part.getCallSignatures();
1017
- const [param] = call?.getParameters() ?? [];
1018
- if (call) return param ? checker.getTypeOfSymbolAtLocation(param, source) : null;
1019
- const instance = part.getConstructSignatures()[0]?.getReturnType();
1020
- const held = instance?.getProperty("props");
1021
- if (held) return checker.getTypeOfSymbolAtLocation(held, source);
1022
- }
1023
- return null;
1024
- }
1025
1208
  function propTable(tsm, checker, props, at, skipped) {
1026
1209
  const argTypes = {};
1027
1210
  const reading = { tsm, checker, at, skipped, sources: /* @__PURE__ */ new Set() };
@@ -1041,9 +1224,9 @@ function propTable(tsm, checker, props, at, skipped) {
1041
1224
  return { argTypes, sources: [...reading.sources] };
1042
1225
  }
1043
1226
  var declaredIn = (symbol) => (symbol.getDeclarations() ?? []).map((declaration) => declaration.getSourceFile().fileName);
1044
- var IN_PACKAGES = /[\\/]node_modules[\\/]/;
1227
+ var IN_PACKAGES2 = /[\\/]node_modules[\\/]/;
1045
1228
  function record({ sources }, files) {
1046
- for (const file of files) if (!IN_PACKAGES.test(file)) sources.add(file);
1229
+ for (const file of files) if (!IN_PACKAGES2.test(file)) sources.add(file);
1047
1230
  }
1048
1231
  function controlFor(reading, type, written) {
1049
1232
  const { TypeFlags } = reading.tsm;
@@ -1099,11 +1282,11 @@ function shapeOf(reading, type, depth) {
1099
1282
  if (whole.getCallSignatures().length > 0 || whole.getConstructSignatures().length > 0) return null;
1100
1283
  if (checker.getIndexInfosOfType(whole).length > 0) return null;
1101
1284
  const declared = (whole.getSymbol() ?? whole.aliasSymbol)?.getDeclarations() ?? [];
1102
- if (declared.some((declaration) => IN_PACKAGES.test(declaration.getSourceFile().fileName))) return null;
1285
+ if (declared.some((declaration) => IN_PACKAGES2.test(declaration.getSourceFile().fileName))) return null;
1103
1286
  const fields = {};
1104
1287
  for (const prop2 of checker.getPropertiesOfType(whole)) {
1105
1288
  const files = declaredIn(prop2);
1106
- if (files.some((file) => IN_PACKAGES.test(file) || reading.skipped(file))) return null;
1289
+ if (files.some((file) => IN_PACKAGES2.test(file) || reading.skipped(file))) return null;
1107
1290
  const field = shapeOf(reading, checker.getTypeOfSymbolAtLocation(prop2, reading.at), depth + 1);
1108
1291
  if (field) fields[prop2.getName()] = field;
1109
1292
  else if (!(prop2.flags & tsm.SymbolFlags.Optional)) return null;
@@ -1144,7 +1327,38 @@ function writtenOrder(tsm, checker, prop2) {
1144
1327
  }
1145
1328
 
1146
1329
  // src/vite/propControls.ts
1147
- function propControls(stories, options = {}) {
1330
+ var errorText = (err) => err instanceof Error ? err.message : String(err);
1331
+ function storyExports(reader, file, fallback, { controls, api }, warn) {
1332
+ let code = "";
1333
+ const sources = [];
1334
+ if (controls) {
1335
+ try {
1336
+ const table = reader.read(file);
1337
+ if (table && Object.keys(table.argTypes).length > 0) {
1338
+ code += `
1339
+ export const ${PROP_ARG_TYPES_EXPORT} = ${JSON.stringify(table.argTypes)};
1340
+ `;
1341
+ sources.push(...table.sources);
1342
+ }
1343
+ } catch (err) {
1344
+ warn(`could not read the props for ${file}: ${errorText(err)}`);
1345
+ }
1346
+ }
1347
+ if (api) {
1348
+ try {
1349
+ const read = reader.api(file, fallback);
1350
+ const table = read && { props: read.props, inherited: read.inherited, ref: read.ref };
1351
+ code += `
1352
+ export const ${API_EXPORT} = ${JSON.stringify(table)};
1353
+ `;
1354
+ if (read) sources.push(...read.sources);
1355
+ } catch (err) {
1356
+ warn(`could not read the API for ${file}: ${errorText(err)}`);
1357
+ }
1358
+ }
1359
+ return { code, sources };
1360
+ }
1361
+ function propControls(stories, fallbackOf, readings, options = {}) {
1148
1362
  let root = process.cwd();
1149
1363
  let reader = null;
1150
1364
  return {
@@ -1156,17 +1370,11 @@ function propControls(stories, options = {}) {
1156
1370
  async transform(code, id) {
1157
1371
  if (!stories().includes(id)) return void 0;
1158
1372
  const props = await (reader ??= createPropReader(root, stories, options));
1159
- let table = null;
1160
- try {
1161
- table = props?.read(id) ?? null;
1162
- } catch (err) {
1163
- this.warn(`could not read the props for ${id}: ${err instanceof Error ? err.message : String(err)}`);
1164
- }
1165
- if (!table || Object.keys(table.argTypes).length === 0) return void 0;
1166
- for (const source of table.sources) this.addWatchFile(source);
1167
- return { code: `${code}
1168
- export const ${PROP_ARG_TYPES_EXPORT} = ${JSON.stringify(table.argTypes)};
1169
- `, map: null };
1373
+ if (!props) return void 0;
1374
+ const added = storyExports(props, id, fallbackOf(id), readings, (message) => this.warn(message));
1375
+ if (!added.code) return void 0;
1376
+ for (const source of new Set(added.sources)) this.addWatchFile(source);
1377
+ return { code: code + added.code, map: null };
1170
1378
  }
1171
1379
  };
1172
1380
  }
@@ -1981,12 +2189,19 @@ function watchSources(server, { files, depGraph, reindex, redeps, logError }) {
1981
2189
  });
1982
2190
  }
1983
2191
  }
1984
- function companions(options, storyFiles) {
1985
- const { storybookShims: shims, propControls: controls } = options;
2192
+ function companions(options, files) {
2193
+ const { storybookShims: shims, propControls: controls, api } = options;
2194
+ const storyFiles = () => [...files().keys()];
2195
+ const fallbackOf = (file) => {
2196
+ const title = files().get(file)?.[0]?.title;
2197
+ return title === void 0 ? void 0 : titleStandIn(title);
2198
+ };
2199
+ const readings = { controls: controls !== false, api: api !== false };
2200
+ const narrowed = typeof controls === "object" ? controls : void 0;
1986
2201
  return [
1987
2202
  watchRecovery(),
1988
2203
  ...shims === false ? [] : [storybookShims()],
1989
- ...controls === false ? [] : [propControls(storyFiles, controls === true ? void 0 : controls)]
2204
+ ...readings.controls || readings.api ? [propControls(storyFiles, fallbackOf, readings, narrowed)] : []
1990
2205
  ];
1991
2206
  }
1992
2207
  function forge(options) {
@@ -2127,7 +2342,7 @@ function forge(options) {
2127
2342
  return true;
2128
2343
  }
2129
2344
  return [
2130
- ...companions(options, () => [...files().keys()]),
2345
+ ...companions(options, files),
2131
2346
  {
2132
2347
  name: "weaselforge",
2133
2348
  config(config, { command }) {