UNPKG

@storybook/react-native

Version:

A better way to develop React Native Components for your app

349 lines (336 loc) 11.2 kB
var __create = Object.create; var __defProp = Object.defineProperty; var __getOwnPropDesc = Object.getOwnPropertyDescriptor; var __getOwnPropNames = Object.getOwnPropertyNames; var __getProtoOf = Object.getPrototypeOf; var __hasOwnProp = Object.prototype.hasOwnProperty; var __commonJS = (cb, mod) => function __require() { return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports; }; var __copyProps = (to, from, except, desc) => { if (from && typeof from === "object" || typeof from === "function") { for (let key of __getOwnPropNames(from)) if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); } return to; }; var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps( // If the importer is in node compatibility mode or this is not an ESM // file that has been converted to a CommonJS file using a Babel- // compatible transform (i.e. "__esModule" has not been set), then set // "default" to the CommonJS "module.exports" for node compatibility. isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target, mod )); // scripts/common.js var require_common = __commonJS({ "scripts/common.js"(exports2, module2) { var { globToRegexp, serverRequire } = require("storybook/internal/common"); var path2 = require("path"); var fs = require("fs"); var cwd = process.cwd(); var toRequireContext = (specifier) => { const { directory, files } = specifier; const match = globToRegexp(`./${files}`); return { path: directory, recursive: files.includes("**") || files.split("/").length > 1, match }; }; function requireUncached(module3) { delete require.cache[require.resolve(module3)]; return serverRequire(module3); } var supportedExtensions = ["js", "jsx", "ts", "tsx", "cjs", "mjs"]; function getFilePathExtension({ configPath }, fileName) { for (const ext of supportedExtensions) { const filePath = path2.resolve(cwd, configPath, `${fileName}.${ext}`); if (fs.existsSync(filePath)) { return ext; } } return null; } function getMain({ configPath }) { const fileExtension = getFilePathExtension({ configPath }, "main"); if (fileExtension === null) { throw new Error("main config file not found"); } const mainPath = path2.resolve(cwd, configPath, `main.${fileExtension}`); return requireUncached(mainPath); } function ensureRelativePathHasDot(relativePath) { return relativePath.startsWith(".") ? relativePath : `./${relativePath}`; } function getPreviewExists({ configPath }) { return !!getFilePathExtension({ configPath }, "preview"); } function resolveAddonFile(addon, file, extensions = ["js", "mjs", "ts"], configPath) { if (!addon || typeof addon !== "string") return null; try { const basePath = `${addon}/${file}`; require.resolve(basePath); return basePath; } catch (_error) { } for (const ext of extensions) { try { const filePath = `${addon}/${file}.${ext}`; require.resolve(filePath); return filePath; } catch (_error) { } } if (addon.startsWith("./") || addon.startsWith("../")) { try { const extension = getFilePathExtension({ configPath }, `${addon}/${file}`); if (extension) { return `${addon}/${file}`; } } catch (_error) { } } return null; } function getAddonName(addon) { if (typeof addon === "string") return addon; if (typeof addon === "object" && addon.name && typeof addon.name === "string") return addon.name; console.error("Invalid addon configuration", addon); return null; } module2.exports = { toRequireContext, requireUncached, getFilePathExtension, getMain, ensureRelativePathHasDot, getPreviewExists, resolveAddonFile, getAddonName }; } }); // scripts/generate.js var require_generate = __commonJS({ "scripts/generate.js"(exports2, module2) { var { toRequireContext, ensureRelativePathHasDot, getMain, getPreviewExists, resolveAddonFile, getAddonName } = require_common(); var { normalizeStories, globToRegexp } = require("storybook/internal/common"); var fs = require("fs"); var path2 = require("path"); var cwd = process.cwd(); function generate2({ configPath, /* absolute = false, */ useJs = false, docTools = true }) { const storybookRequiresLocation = path2.resolve( cwd, configPath, `storybook.requires.${useJs ? "js" : "ts"}` ); const mainImport = getMain({ configPath }); const main = mainImport.default ?? mainImport; const storiesSpecifiers = normalizeStories(main.stories, { configDir: configPath, workingDir: cwd }); const normalizedStories = storiesSpecifiers.map((specifier) => { const reg = globToRegexp(`./${specifier.files}`); const { path: p, recursive: r, match: m } = toRequireContext(specifier); const pathToStory = ensureRelativePathHasDot(path2.posix.relative(configPath, p)); return `{ titlePrefix: "${specifier.titlePrefix}", directory: "${specifier.directory}", files: "${specifier.files}", importPathMatcher: /${reg.source}/, ${useJs ? "" : "// @ts-ignore"} req: require.context( '${pathToStory}', ${r}, ${m} ), }`; }); const registeredAddons = []; for (const addon of main.addons) { const registerPath = resolveAddonFile( getAddonName(addon), "register", ["js", "mjs", "jsx", "ts", "tsx"], configPath ); if (registerPath) { registeredAddons.push(`import "${registerPath}";`); } } const docToolsAnnotation = 'require("@storybook/react-native/preview")'; const enhancers = []; if (docTools) { enhancers.push(docToolsAnnotation); } for (const addon of main.addons) { const previewPath = resolveAddonFile( getAddonName(addon), "preview", ["js", "mjs", "jsx", "ts", "tsx"], configPath ); if (previewPath) { enhancers.push(`require('${previewPath}')`); continue; } } let options = ""; let optionsVar = ""; const reactNativeOptions = main.reactNative; if (reactNativeOptions && typeof reactNativeOptions === "object") { optionsVar = `const options = ${JSON.stringify(reactNativeOptions, null, 4)}`; options = "options"; } const previewExists = getPreviewExists({ configPath }); if (previewExists) { enhancers.unshift("require('./preview')"); } const annotations = `[ ${enhancers.join(",\n ")} ]`; const globalTypes = ` declare global { var view: View; var STORIES: typeof normalizedStories; } `; const fileContent = `/* do not change this file, it is auto generated by storybook. */ import { start, updateView${useJs ? "" : ", View"} } from '@storybook/react-native'; ${registeredAddons.join("\n")} const normalizedStories = [ ${normalizedStories.join(",\n")} ]; ${useJs ? "" : globalTypes} const annotations = ${annotations}; global.STORIES = normalizedStories; ${useJs ? "" : "// @ts-ignore"} module?.hot?.accept?.(); ${optionsVar} if (!global.view) { global.view = start({ annotations, storyEntries: normalizedStories, ${options ? ` ${options},` : ""} }); } else { updateView(global.view, annotations, normalizedStories${options ? `, ${options}` : ""}); } export const view${useJs ? "" : ": View"} = global.view; `; fs.writeFileSync(storybookRequiresLocation, fileContent, { encoding: "utf8", flag: "w" }); } module2.exports = { generate: generate2 }; } }); // src/metro/withStorybook.ts var path = __toESM(require("path")); var import_generate = __toESM(require_generate()); var import_ws = require("ws"); function withStorybook(config, options = { enabled: true, useJs: false, onDisabledRemoveStorybook: false, docTools: true }) { const { configPath, enabled = true, websockets, useJs = false, onDisabledRemoveStorybook = false, docTools = true } = options; if (!enabled) { if (onDisabledRemoveStorybook) { return { ...config, resolver: { ...config.resolver, resolveRequest: (context, moduleName, platform) => { const resolveFunction = config?.resolver?.resolveRequest ? config.resolver.resolveRequest : context.resolveRequest; if (moduleName.startsWith("storybook") || moduleName.startsWith("@storybook")) { return { type: "empty" }; } return resolveFunction(context, moduleName, platform); } } }; } return config; } if (websockets) { const port = websockets.port ?? 7007; const host = websockets.host ?? "localhost"; const wss = new import_ws.WebSocketServer({ port, host }); wss.on("connection", function connection(ws) { console.log("WebSocket connection established"); ws.on("error", console.error); ws.on("message", function message(data) { try { const json = JSON.parse(data.toString()); wss.clients.forEach((wsClient) => wsClient.send(JSON.stringify(json))); } catch (error) { console.error(error); } }); }); } (0, import_generate.generate)({ configPath: configPath ?? path.resolve(process.cwd(), "./.rnstorybook"), useJs, docTools }); return { ...config, transformer: { ...config.transformer, unstable_allowRequireContext: true }, resolver: { ...config.resolver, resolveRequest: (context, moduleName, platform) => { const resolveFunction = config?.resolver?.resolveRequest ? config.resolver.resolveRequest : context.resolveRequest; const shouldUseCustomResolveConfig = moduleName.startsWith("storybook") || moduleName.startsWith("@storybook") || moduleName.startsWith("uuid"); const theContext = shouldUseCustomResolveConfig ? { ...context, unstable_enablePackageExports: true, unstable_conditionNames: ["import"] } : context; const resolveResult = resolveFunction(theContext, moduleName, platform); if (resolveResult?.filePath?.includes?.("@storybook/react/template/cli")) { return { type: "empty" }; } return resolveResult; } } }; } module.exports = withStorybook;