UNPKG

@storybook/react-native

Version:

A better way to develop React Native Components for your app

1,465 lines (1,441 loc) 66.4 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 __esm = (fn, res) => function __init() { return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res; }; var __export = (target, all) => { for (var name in all) __defProp(target, name, { get: all[name], enumerable: true }); }; 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 )); var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); // src/backgrounds/Swatch.tsx var import_react_native_theming3, import_jsx_runtime4, PressableSwatch, ColorSwatch, ValueContainer, NameText, ValueText, Swatch, Swatch_default; var init_Swatch = __esm({ "src/backgrounds/Swatch.tsx"() { import_react_native_theming3 = require("@storybook/react-native-theming"); import_jsx_runtime4 = require("react/jsx-runtime"); PressableSwatch = import_react_native_theming3.styled.TouchableOpacity(({ theme: theme3 }) => ({ marginBottom: 10, borderWidth: 1, borderColor: theme3.appBorderColor, borderRadius: 6, backgroundColor: theme3.background.content, paddingVertical: 4, paddingHorizontal: 4 })); ColorSwatch = import_react_native_theming3.styled.View(({ color, theme: theme3 }) => ({ height: 40, width: "100%", borderRadius: 4, backgroundColor: color, borderColor: theme3.appBorderColor, borderWidth: 1 })); ValueContainer = import_react_native_theming3.styled.View(() => ({ flex: 1, flexDirection: "row", justifyContent: "space-between", padding: 4, paddingBottom: 0 })); NameText = import_react_native_theming3.styled.Text(({ theme: theme3 }) => ({ fontSize: theme3.typography.size.s2, color: theme3.color.defaultText, fontWeight: theme3.typography.weight.bold })); ValueText = import_react_native_theming3.styled.Text(({ theme: theme3 }) => ({ fontSize: theme3.typography.size.s2, color: theme3.color.defaultText })); Swatch = ({ name, value, setBackground, disabled }) => /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)( PressableSwatch, { onPress: () => setBackground(value), disabled, style: { opacity: disabled ? 0.5 : 1 }, children: [ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(ColorSwatch, { color: value }), /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(ValueContainer, { children: [ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(NameText, { children: name }), /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(ValueText, { children: value }) ] }) ] } ); Swatch_default = Swatch; } }); // src/backgrounds/constants.ts var PARAM_KEY, ADDON_ID, PANEL_ID; var init_constants = __esm({ "src/backgrounds/constants.ts"() { PARAM_KEY = "backgrounds"; ADDON_ID = "storybook-addon-background"; PANEL_ID = `${ADDON_ID}/background-panel`; } }); // src/backgrounds/BackgroundPanel.tsx var import_react_native5, import_react5, import_core_events2, import_react_native_theming4, import_jsx_runtime5, codeSample, ThemedText, TitleText, ParagraphText, LockedText, Instructions, BackgroundPanel, BackgroundPanel_default; var init_BackgroundPanel = __esm({ "src/backgrounds/BackgroundPanel.tsx"() { import_react_native5 = require("react-native"); import_react5 = require("react"); import_core_events2 = require("storybook/internal/core-events"); import_react_native_theming4 = require("@storybook/react-native-theming"); init_Swatch(); init_constants(); import_jsx_runtime5 = require("react/jsx-runtime"); codeSample = ` // In your preview config (.storybook/preview.tsx): import type { Preview } from '@storybook/react-native'; const preview: Preview = { parameters: { backgrounds: { options: { dark: { name: 'Dark', value: '#333333' }, light: { name: 'Light', value: '#F7F9F2' }, maroon: { name: 'Maroon', value: '#400000' }, }, }, }, initialGlobals: { backgrounds: { value: 'light' }, }, }; export default preview; `.trim(); ThemedText = import_react_native_theming4.styled.Text(({ theme: theme3 }) => ({ color: theme3.color.defaultText })); TitleText = import_react_native_theming4.styled.Text(({ theme: theme3 }) => ({ color: theme3.color.defaultText, fontSize: 16, marginBottom: 8 })); ParagraphText = import_react_native_theming4.styled.Text(({ theme: theme3 }) => ({ color: theme3.color.defaultText, marginBottom: 8 })); LockedText = import_react_native_theming4.styled.Text(({ theme: theme3 }) => ({ color: theme3.color.defaultText, marginBottom: 10, fontStyle: "italic", opacity: 0.7 })); Instructions = () => /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(import_react_native5.View, { children: [ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(TitleText, { children: "Setup Instructions" }), /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(ParagraphText, { children: "Add background options to your preview parameters. Each option should include a name and the corresponding color value." }), /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(ParagraphText, { children: "Below is an example of how to configure backgrounds in your preview config. Long press the example to copy it." }), /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(ThemedText, { selectable: true, children: codeSample }) ] }); BackgroundPanel = ({ active, api, channel }) => { const store2 = api.store(); const storyId = store2.getSelection()?.storyId; const story = storyId ? store2.fromId(storyId) : null; const isLocked = !!story?.storyGlobals?.[PARAM_KEY]; const setBackground = (0, import_react5.useCallback)( (name) => { channel.emit(import_core_events2.UPDATE_GLOBALS, { globals: { [PARAM_KEY]: { value: name } } }); }, [channel] ); const bgParams = story?.parameters?.[PARAM_KEY]; const options = bgParams?.options; if (options && Object.keys(options).length > 0) { return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(import_react_native5.View, { style: { padding: 10 }, children: [ isLocked && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(LockedText, { children: "Background is set at the story level" }), Object.entries(options).map(([key, { name, value }]) => /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_react_native5.View, { children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)( Swatch_default, { value, name: name || key, setBackground: () => setBackground(key), disabled: isLocked } ) }, `${key} ${value}`)) ] }); } return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_react_native5.View, { style: { padding: 10 }, children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(Instructions, {}) }); }; BackgroundPanel_default = BackgroundPanel; } }); // src/backgrounds/register.tsx var register_exports = {}; __export(register_exports, { registerBackgroundsAddon: () => registerBackgroundsAddon }); function registerBackgroundsAddon() { import_manager_api2.addons.register(ADDON_ID, (api) => { const channel = import_manager_api2.addons.getChannel(); import_manager_api2.addons.add(PANEL_ID, { type: import_manager_api2.types.PANEL, title: "Backgrounds", render: ({ active }) => /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(BackgroundPanel_default, { channel, api, active }), paramKey: PARAM_KEY }); }); } var import_manager_api2, import_jsx_runtime6; var init_register = __esm({ "src/backgrounds/register.tsx"() { import_manager_api2 = require("storybook/manager-api"); init_BackgroundPanel(); init_constants(); import_jsx_runtime6 = require("react/jsx-runtime"); } }); // src/index.ts var index_exports = {}; __export(index_exports, { RN_STORYBOOK_EVENTS: () => RN_STORYBOOK_EVENTS, RN_STORYBOOK_STORAGE_KEY: () => RN_STORYBOOK_STORAGE_KEY, STORYBOOK_STORY_ID_PARAM: () => STORYBOOK_STORY_ID_PARAM, darkTheme: () => import_react_native_theming5.darkTheme, getProjectAnnotations: () => getProjectAnnotations, prepareStories: () => prepareStories, start: () => start, theme: () => import_react_native_theming5.theme, updateView: () => updateView }); module.exports = __toCommonJS(index_exports); var import_react_native_theming5 = require("@storybook/react-native-theming"); // src/polyfill.ts var import_react_native = require("react-native"); if (import_react_native.Platform.OS !== "web") { try { let params = new URLSearchParams({ test: "1" }); params.get("test"); } catch { const { setupURLPolyfill } = require("react-native-url-polyfill"); setupURLPolyfill(); } } if (import_react_native.Platform.OS === "web" && typeof globalThis.setImmediate === "undefined") { require("setimmediate"); } // src/Start.tsx var import_react_native6 = require("react-native"); var import_manager_api3 = require("storybook/manager-api"); var import_preview_api3 = require("storybook/internal/preview-api"); var import_channels2 = require("storybook/internal/channels"); // src/View.tsx var import_csf = require("storybook/internal/csf"); var import_react_native_theming2 = require("@storybook/react-native-theming"); var import_react_native_ui_common = require("@storybook/react-native-ui-common"); var import_channels = require("storybook/internal/channels"); var import_core_events = require("storybook/internal/core-events"); var import_manager_api = require("storybook/manager-api"); var import_preview_api = require("storybook/internal/preview-api"); var import_dedent = __toESM(require("dedent")); // src/patchChannelForRN.ts function snapshotValue(value, depth = 0) { if (depth > 3) return "[...]"; if (value === null || value === void 0) return value; if (typeof value === "function") return void 0; if (typeof value !== "object") return value; if (Array.isArray(value)) { return value.map((item) => snapshotValue(item, depth + 1)); } const result = {}; for (const key of Object.keys(value)) { try { result[key] = snapshotValue(value[key], depth + 1); } catch { result[key] = "[Error]"; } } return result; } function isSyntheticEvent(value) { return value !== null && typeof value === "object" && typeof value.persist === "function" && "nativeEvent" in value; } function sanitizeActionArgs(value) { if (isSyntheticEvent(value)) { return snapshotValue(value); } if (Array.isArray(value)) { return value.map(sanitizeActionArgs); } return value; } function patchChannelForRN(channel) { globalThis.CHANNEL_OPTIONS = { maxDepth: 5 }; const originalEmit = channel.emit.bind(channel); channel.emit = (eventName, ...args) => { if (eventName === "storybook/actions/action-event") { const actionDisplay = args[0]; if (actionDisplay?.data?.args != null) { actionDisplay.data.args = sanitizeActionArgs(actionDisplay.data.args); } } return originalEmit(eventName, ...args); }; } // src/View.tsx var import_deepmerge = __toESM(require("deepmerge")); var import_react4 = require("react"); var import_react_native4 = require("react-native"); // src/components/StoryView/StoryView.tsx var import_react_native_theming = require("@storybook/react-native-theming"); var import_react3 = __toESM(require("react")); var import_react_native3 = require("react-native"); // ../../node_modules/jotai/esm/vanilla/internals.mjs var import_meta = {}; function hasInitialValue(atom2) { return "init" in atom2; } function isActuallyWritableAtom(atom2) { return !!atom2.write; } function isAtomStateInitialized(atomState) { return "v" in atomState || "e" in atomState; } function returnAtomValue(atomState) { if ("e" in atomState) { throw atomState.e; } if ((import_meta.env ? import_meta.env.MODE : void 0) !== "production" && !("v" in atomState)) { throw new Error("[Bug] atom state is not initialized"); } return atomState.v; } function isPromiseLike(p) { return typeof (p == null ? void 0 : p.then) === "function"; } function addPendingPromiseToDependency(atom2, promise, dependencyAtomState) { if (!dependencyAtomState.p.has(atom2)) { dependencyAtomState.p.add(atom2); const cleanup = () => dependencyAtomState.p.delete(atom2); promise.then(cleanup, cleanup); } } function getMountedOrPendingDependents(atom2, atomState, mountedMap) { var _a; const dependents = /* @__PURE__ */ new Set(); for (const a of ((_a = mountedMap.get(atom2)) == null ? void 0 : _a.t) || []) { dependents.add(a); } for (const atomWithPendingPromise of atomState.p) { dependents.add(atomWithPendingPromise); } return dependents; } var BUILDING_BLOCK_atomRead = (_store, atom2, ...params) => atom2.read(...params); var BUILDING_BLOCK_atomWrite = (_store, atom2, ...params) => atom2.write(...params); var BUILDING_BLOCK_atomOnInit = (store2, atom2) => { var _a; return (_a = atom2.INTERNAL_onInit) == null ? void 0 : _a.call(atom2, store2); }; var BUILDING_BLOCK_atomOnMount = (_store, atom2, setAtom) => { var _a; return (_a = atom2.onMount) == null ? void 0 : _a.call(atom2, setAtom); }; var BUILDING_BLOCK_ensureAtomState = (store2, atom2) => { var _a; const buildingBlocks = getInternalBuildingBlocks(store2); const atomStateMap = buildingBlocks[0]; const storeHooks = buildingBlocks[6]; const atomOnInit = buildingBlocks[9]; if ((import_meta.env ? import_meta.env.MODE : void 0) !== "production" && !atom2) { throw new Error("Atom is undefined or null"); } let atomState = atomStateMap.get(atom2); if (!atomState) { atomState = { d: /* @__PURE__ */ new Map(), p: /* @__PURE__ */ new Set(), n: 0 }; atomStateMap.set(atom2, atomState); (_a = storeHooks.i) == null ? void 0 : _a.call(storeHooks, atom2); atomOnInit == null ? void 0 : atomOnInit(store2, atom2); } return atomState; }; var BUILDING_BLOCK_flushCallbacks = (store2) => { const buildingBlocks = getInternalBuildingBlocks(store2); const mountedMap = buildingBlocks[1]; const changedAtoms = buildingBlocks[3]; const mountCallbacks = buildingBlocks[4]; const unmountCallbacks = buildingBlocks[5]; const storeHooks = buildingBlocks[6]; const recomputeInvalidatedAtoms = buildingBlocks[13]; const errors = []; const call = (fn) => { try { fn(); } catch (e) { errors.push(e); } }; do { if (storeHooks.f) { call(storeHooks.f); } const callbacks = /* @__PURE__ */ new Set(); const add = callbacks.add.bind(callbacks); changedAtoms.forEach((atom2) => { var _a; return (_a = mountedMap.get(atom2)) == null ? void 0 : _a.l.forEach(add); }); changedAtoms.clear(); unmountCallbacks.forEach(add); unmountCallbacks.clear(); mountCallbacks.forEach(add); mountCallbacks.clear(); callbacks.forEach(call); if (changedAtoms.size) { recomputeInvalidatedAtoms(store2); } } while (changedAtoms.size || unmountCallbacks.size || mountCallbacks.size); if (errors.length) { throw new AggregateError(errors); } }; var BUILDING_BLOCK_recomputeInvalidatedAtoms = (store2) => { const buildingBlocks = getInternalBuildingBlocks(store2); const mountedMap = buildingBlocks[1]; const invalidatedAtoms = buildingBlocks[2]; const changedAtoms = buildingBlocks[3]; const ensureAtomState = buildingBlocks[11]; const readAtomState = buildingBlocks[14]; const mountDependencies = buildingBlocks[17]; const topSortedReversed = []; const visiting = /* @__PURE__ */ new WeakSet(); const visited = /* @__PURE__ */ new WeakSet(); const stack = Array.from(changedAtoms); while (stack.length) { const a = stack[stack.length - 1]; const aState = ensureAtomState(store2, a); if (visited.has(a)) { stack.pop(); continue; } if (visiting.has(a)) { if (invalidatedAtoms.get(a) === aState.n) { topSortedReversed.push([a, aState]); } else if ((import_meta.env ? import_meta.env.MODE : void 0) !== "production" && invalidatedAtoms.has(a)) { throw new Error("[Bug] invalidated atom exists"); } visited.add(a); stack.pop(); continue; } visiting.add(a); for (const d of getMountedOrPendingDependents(a, aState, mountedMap)) { if (!visiting.has(d)) { stack.push(d); } } } for (let i = topSortedReversed.length - 1; i >= 0; --i) { const [a, aState] = topSortedReversed[i]; let hasChangedDeps = false; for (const dep of aState.d.keys()) { if (dep !== a && changedAtoms.has(dep)) { hasChangedDeps = true; break; } } if (hasChangedDeps) { invalidatedAtoms.set(a, aState.n); readAtomState(store2, a); mountDependencies(store2, a); } invalidatedAtoms.delete(a); } }; var storeMutationSet = /* @__PURE__ */ new WeakSet(); var BUILDING_BLOCK_readAtomState = (store2, atom2) => { var _a, _b; const buildingBlocks = getInternalBuildingBlocks(store2); const mountedMap = buildingBlocks[1]; const invalidatedAtoms = buildingBlocks[2]; const changedAtoms = buildingBlocks[3]; const storeHooks = buildingBlocks[6]; const atomRead = buildingBlocks[7]; const ensureAtomState = buildingBlocks[11]; const flushCallbacks = buildingBlocks[12]; const recomputeInvalidatedAtoms = buildingBlocks[13]; const readAtomState = buildingBlocks[14]; const writeAtomState = buildingBlocks[16]; const mountDependencies = buildingBlocks[17]; const setAtomStateValueOrPromise = buildingBlocks[20]; const registerAbortHandler = buildingBlocks[26]; const storeEpochHolder = buildingBlocks[28]; const atomState = ensureAtomState(store2, atom2); const storeEpochNumber = storeEpochHolder[0]; if (isAtomStateInitialized(atomState)) { if ( // If the atom is mounted, we can use cached atom state, // because it should have been updated by dependencies. // We can't use the cache if the atom is invalidated. mountedMap.has(atom2) && invalidatedAtoms.get(atom2) !== atomState.n || // If atom is not mounted, we can use cached atom state, // only if store hasn't been mutated. atomState.m === storeEpochNumber ) { atomState.m = storeEpochNumber; return atomState; } let hasChangedDeps = false; for (const [a, n] of atomState.d) { if (readAtomState(store2, a).n !== n) { hasChangedDeps = true; break; } } if (!hasChangedDeps) { atomState.m = storeEpochNumber; return atomState; } } let isSync = true; const prevDeps = new Set(atomState.d.keys()); const nextDeps = /* @__PURE__ */ new Map(); const pruneDependencies = () => { for (const a of prevDeps) { if (!nextDeps.has(a)) { atomState.d.delete(a); } } }; const mountDependenciesIfAsync = () => { if (mountedMap.has(atom2)) { const shouldRecompute = !changedAtoms.size; mountDependencies(store2, atom2); if (shouldRecompute) { recomputeInvalidatedAtoms(store2); flushCallbacks(store2); } } }; const getter = (a) => { var _a2; if (a === atom2) { const aState2 = ensureAtomState(store2, a); if (!isAtomStateInitialized(aState2)) { if (hasInitialValue(a)) { setAtomStateValueOrPromise(store2, a, a.init); } else { throw new Error("no atom init"); } } return returnAtomValue(aState2); } const aState = readAtomState(store2, a); try { return returnAtomValue(aState); } finally { nextDeps.set(a, aState.n); atomState.d.set(a, aState.n); if (isPromiseLike(atomState.v)) { addPendingPromiseToDependency(atom2, atomState.v, aState); } if (mountedMap.has(atom2)) { (_a2 = mountedMap.get(a)) == null ? void 0 : _a2.t.add(atom2); } if (!isSync) { mountDependenciesIfAsync(); } } }; let controller; let setSelf; const options = { get signal() { if (!controller) { controller = new AbortController(); } return controller.signal; }, get setSelf() { if ((import_meta.env ? import_meta.env.MODE : void 0) !== "production") { console.warn( "[DEPRECATED] setSelf is deprecated and will be removed in v3." ); } if ((import_meta.env ? import_meta.env.MODE : void 0) !== "production" && !isActuallyWritableAtom(atom2)) { console.warn("setSelf function cannot be used with read-only atom"); } if (!setSelf && isActuallyWritableAtom(atom2)) { setSelf = (...args) => { if ((import_meta.env ? import_meta.env.MODE : void 0) !== "production" && isSync) { console.warn("setSelf function cannot be called in sync"); } if (!isSync) { try { return writeAtomState(store2, atom2, ...args); } finally { recomputeInvalidatedAtoms(store2); flushCallbacks(store2); } } }; } return setSelf; } }; const prevEpochNumber = atomState.n; const prevInvalidated = invalidatedAtoms.get(atom2) === prevEpochNumber; try { if ((import_meta.env ? import_meta.env.MODE : void 0) !== "production") { storeMutationSet.delete(store2); } const valueOrPromise = atomRead(store2, atom2, getter, options); if ((import_meta.env ? import_meta.env.MODE : void 0) !== "production" && storeMutationSet.has(store2)) { console.warn( "Detected store mutation during atom read. This is not supported." ); } setAtomStateValueOrPromise(store2, atom2, valueOrPromise); if (isPromiseLike(valueOrPromise)) { registerAbortHandler(store2, valueOrPromise, () => controller == null ? void 0 : controller.abort()); const settle = () => { pruneDependencies(); mountDependenciesIfAsync(); }; valueOrPromise.then(settle, settle); } else { pruneDependencies(); } (_a = storeHooks.r) == null ? void 0 : _a.call(storeHooks, atom2); atomState.m = storeEpochNumber; return atomState; } catch (error) { delete atomState.v; atomState.e = error; ++atomState.n; atomState.m = storeEpochNumber; return atomState; } finally { isSync = false; if (atomState.n !== prevEpochNumber && prevInvalidated) { invalidatedAtoms.set(atom2, atomState.n); changedAtoms.add(atom2); (_b = storeHooks.c) == null ? void 0 : _b.call(storeHooks, atom2); } } }; var BUILDING_BLOCK_invalidateDependents = (store2, atom2) => { const buildingBlocks = getInternalBuildingBlocks(store2); const mountedMap = buildingBlocks[1]; const invalidatedAtoms = buildingBlocks[2]; const ensureAtomState = buildingBlocks[11]; const stack = [atom2]; while (stack.length) { const a = stack.pop(); const aState = ensureAtomState(store2, a); for (const d of getMountedOrPendingDependents(a, aState, mountedMap)) { const dState = ensureAtomState(store2, d); if (invalidatedAtoms.get(d) !== dState.n) { invalidatedAtoms.set(d, dState.n); stack.push(d); } } } }; var BUILDING_BLOCK_writeAtomState = (store2, atom2, ...args) => { const buildingBlocks = getInternalBuildingBlocks(store2); const changedAtoms = buildingBlocks[3]; const storeHooks = buildingBlocks[6]; const atomWrite = buildingBlocks[8]; const ensureAtomState = buildingBlocks[11]; const flushCallbacks = buildingBlocks[12]; const recomputeInvalidatedAtoms = buildingBlocks[13]; const readAtomState = buildingBlocks[14]; const invalidateDependents = buildingBlocks[15]; const writeAtomState = buildingBlocks[16]; const mountDependencies = buildingBlocks[17]; const setAtomStateValueOrPromise = buildingBlocks[20]; const storeEpochHolder = buildingBlocks[28]; let isSync = true; const getter = (a) => returnAtomValue(readAtomState(store2, a)); const setter = (a, ...args2) => { var _a; const aState = ensureAtomState(store2, a); try { if (a === atom2) { if (!hasInitialValue(a)) { throw new Error("atom not writable"); } if ((import_meta.env ? import_meta.env.MODE : void 0) !== "production") { storeMutationSet.add(store2); } const prevEpochNumber = aState.n; const v = args2[0]; setAtomStateValueOrPromise(store2, a, v); mountDependencies(store2, a); if (prevEpochNumber !== aState.n) { ++storeEpochHolder[0]; changedAtoms.add(a); invalidateDependents(store2, a); (_a = storeHooks.c) == null ? void 0 : _a.call(storeHooks, a); } return void 0; } else { return writeAtomState(store2, a, ...args2); } } finally { if (!isSync) { recomputeInvalidatedAtoms(store2); flushCallbacks(store2); } } }; try { return atomWrite(store2, atom2, getter, setter, ...args); } finally { isSync = false; } }; var BUILDING_BLOCK_mountDependencies = (store2, atom2) => { var _a; const buildingBlocks = getInternalBuildingBlocks(store2); const mountedMap = buildingBlocks[1]; const changedAtoms = buildingBlocks[3]; const storeHooks = buildingBlocks[6]; const ensureAtomState = buildingBlocks[11]; const invalidateDependents = buildingBlocks[15]; const mountAtom = buildingBlocks[18]; const unmountAtom = buildingBlocks[19]; const atomState = ensureAtomState(store2, atom2); const mounted = mountedMap.get(atom2); if (mounted) { for (const [a, n] of atomState.d) { if (!mounted.d.has(a)) { const aState = ensureAtomState(store2, a); const aMounted = mountAtom(store2, a); aMounted.t.add(atom2); mounted.d.add(a); if (n !== aState.n) { changedAtoms.add(a); invalidateDependents(store2, a); (_a = storeHooks.c) == null ? void 0 : _a.call(storeHooks, a); } } } for (const a of mounted.d) { if (!atomState.d.has(a)) { mounted.d.delete(a); const aMounted = unmountAtom(store2, a); aMounted == null ? void 0 : aMounted.t.delete(atom2); } } } }; var BUILDING_BLOCK_mountAtom = (store2, atom2) => { var _a; const buildingBlocks = getInternalBuildingBlocks(store2); const mountedMap = buildingBlocks[1]; const mountCallbacks = buildingBlocks[4]; const storeHooks = buildingBlocks[6]; const atomOnMount = buildingBlocks[10]; const ensureAtomState = buildingBlocks[11]; const flushCallbacks = buildingBlocks[12]; const recomputeInvalidatedAtoms = buildingBlocks[13]; const readAtomState = buildingBlocks[14]; const writeAtomState = buildingBlocks[16]; const mountAtom = buildingBlocks[18]; const atomState = ensureAtomState(store2, atom2); let mounted = mountedMap.get(atom2); if (!mounted) { readAtomState(store2, atom2); for (const a of atomState.d.keys()) { const aMounted = mountAtom(store2, a); aMounted.t.add(atom2); } mounted = { l: /* @__PURE__ */ new Set(), d: new Set(atomState.d.keys()), t: /* @__PURE__ */ new Set() }; mountedMap.set(atom2, mounted); if (isActuallyWritableAtom(atom2)) { const processOnMount = () => { let isSync = true; const setAtom = (...args) => { try { return writeAtomState(store2, atom2, ...args); } finally { if (!isSync) { recomputeInvalidatedAtoms(store2); flushCallbacks(store2); } } }; try { const onUnmount = atomOnMount(store2, atom2, setAtom); if (onUnmount) { mounted.u = () => { isSync = true; try { onUnmount(); } finally { isSync = false; } }; } } finally { isSync = false; } }; mountCallbacks.add(processOnMount); } (_a = storeHooks.m) == null ? void 0 : _a.call(storeHooks, atom2); } return mounted; }; var BUILDING_BLOCK_unmountAtom = (store2, atom2) => { var _a, _b; const buildingBlocks = getInternalBuildingBlocks(store2); const mountedMap = buildingBlocks[1]; const unmountCallbacks = buildingBlocks[5]; const storeHooks = buildingBlocks[6]; const ensureAtomState = buildingBlocks[11]; const unmountAtom = buildingBlocks[19]; const atomState = ensureAtomState(store2, atom2); let mounted = mountedMap.get(atom2); if (!mounted || mounted.l.size) { return mounted; } let isDependent = false; for (const a of mounted.t) { if ((_a = mountedMap.get(a)) == null ? void 0 : _a.d.has(atom2)) { isDependent = true; break; } } if (!isDependent) { if (mounted.u) { unmountCallbacks.add(mounted.u); } mounted = void 0; mountedMap.delete(atom2); for (const a of atomState.d.keys()) { const aMounted = unmountAtom(store2, a); aMounted == null ? void 0 : aMounted.t.delete(atom2); } (_b = storeHooks.u) == null ? void 0 : _b.call(storeHooks, atom2); return void 0; } return mounted; }; var BUILDING_BLOCK_setAtomStateValueOrPromise = (store2, atom2, valueOrPromise) => { const buildingBlocks = getInternalBuildingBlocks(store2); const ensureAtomState = buildingBlocks[11]; const abortPromise = buildingBlocks[27]; const atomState = ensureAtomState(store2, atom2); const hasPrevValue = "v" in atomState; const prevValue = atomState.v; if (isPromiseLike(valueOrPromise)) { for (const a of atomState.d.keys()) { addPendingPromiseToDependency( atom2, valueOrPromise, ensureAtomState(store2, a) ); } } atomState.v = valueOrPromise; delete atomState.e; if (!hasPrevValue || !Object.is(prevValue, atomState.v)) { ++atomState.n; if (isPromiseLike(prevValue)) { abortPromise(store2, prevValue); } } }; var BUILDING_BLOCK_storeGet = (store2, atom2) => { const readAtomState = getInternalBuildingBlocks(store2)[14]; return returnAtomValue(readAtomState(store2, atom2)); }; var BUILDING_BLOCK_storeSet = (store2, atom2, ...args) => { const buildingBlocks = getInternalBuildingBlocks(store2); const changedAtoms = buildingBlocks[3]; const flushCallbacks = buildingBlocks[12]; const recomputeInvalidatedAtoms = buildingBlocks[13]; const writeAtomState = buildingBlocks[16]; const prevChangedAtomsSize = changedAtoms.size; try { return writeAtomState(store2, atom2, ...args); } finally { if (changedAtoms.size !== prevChangedAtomsSize) { recomputeInvalidatedAtoms(store2); flushCallbacks(store2); } } }; var BUILDING_BLOCK_storeSub = (store2, atom2, listener) => { const buildingBlocks = getInternalBuildingBlocks(store2); const flushCallbacks = buildingBlocks[12]; const mountAtom = buildingBlocks[18]; const unmountAtom = buildingBlocks[19]; const mounted = mountAtom(store2, atom2); const listeners = mounted.l; listeners.add(listener); flushCallbacks(store2); return () => { listeners.delete(listener); unmountAtom(store2, atom2); flushCallbacks(store2); }; }; var BUILDING_BLOCK_registerAbortHandler = (store2, promise, abortHandler) => { const buildingBlocks = getInternalBuildingBlocks(store2); const abortHandlersMap = buildingBlocks[25]; let abortHandlers = abortHandlersMap.get(promise); if (!abortHandlers) { abortHandlers = /* @__PURE__ */ new Set(); abortHandlersMap.set(promise, abortHandlers); const cleanup = () => abortHandlersMap.delete(promise); promise.then(cleanup, cleanup); } abortHandlers.add(abortHandler); }; var BUILDING_BLOCK_abortPromise = (store2, promise) => { const buildingBlocks = getInternalBuildingBlocks(store2); const abortHandlersMap = buildingBlocks[25]; const abortHandlers = abortHandlersMap.get(promise); abortHandlers == null ? void 0 : abortHandlers.forEach((fn) => fn()); }; var buildingBlockMap = /* @__PURE__ */ new WeakMap(); var getInternalBuildingBlocks = (store2) => { const buildingBlocks = buildingBlockMap.get(store2); if ((import_meta.env ? import_meta.env.MODE : void 0) !== "production" && !buildingBlocks) { throw new Error( "Store must be created by buildStore to read its building blocks" ); } return buildingBlocks; }; function getBuildingBlocks(store2) { const buildingBlocks = getInternalBuildingBlocks(store2); const enhanceBuildingBlocks = buildingBlocks[24]; if (enhanceBuildingBlocks) { return enhanceBuildingBlocks(buildingBlocks); } return buildingBlocks; } function buildStore(...buildArgs) { const store2 = { get(atom2) { const storeGet = getInternalBuildingBlocks(store2)[21]; return storeGet(store2, atom2); }, set(atom2, ...args) { const storeSet = getInternalBuildingBlocks(store2)[22]; return storeSet(store2, atom2, ...args); }, sub(atom2, listener) { const storeSub = getInternalBuildingBlocks(store2)[23]; return storeSub(store2, atom2, listener); } }; const buildingBlocks = [ // store state /* @__PURE__ */ new WeakMap(), // atomStateMap /* @__PURE__ */ new WeakMap(), // mountedMap /* @__PURE__ */ new WeakMap(), // invalidatedAtoms /* @__PURE__ */ new Set(), // changedAtoms /* @__PURE__ */ new Set(), // mountCallbacks /* @__PURE__ */ new Set(), // unmountCallbacks {}, // storeHooks // atom interceptors BUILDING_BLOCK_atomRead, BUILDING_BLOCK_atomWrite, BUILDING_BLOCK_atomOnInit, BUILDING_BLOCK_atomOnMount, // building-block functions BUILDING_BLOCK_ensureAtomState, BUILDING_BLOCK_flushCallbacks, BUILDING_BLOCK_recomputeInvalidatedAtoms, BUILDING_BLOCK_readAtomState, BUILDING_BLOCK_invalidateDependents, BUILDING_BLOCK_writeAtomState, BUILDING_BLOCK_mountDependencies, BUILDING_BLOCK_mountAtom, BUILDING_BLOCK_unmountAtom, BUILDING_BLOCK_setAtomStateValueOrPromise, BUILDING_BLOCK_storeGet, BUILDING_BLOCK_storeSet, BUILDING_BLOCK_storeSub, void 0, // abortable promise support /* @__PURE__ */ new WeakMap(), // abortHandlersMap BUILDING_BLOCK_registerAbortHandler, BUILDING_BLOCK_abortPromise, // store epoch [0] ].map((fn, i) => buildArgs[i] || fn); buildingBlockMap.set(store2, Object.freeze(buildingBlocks)); return store2; } // ../../node_modules/jotai/esm/vanilla.mjs var import_meta2 = {}; var keyCount = 0; function atom(read, write) { const key = `atom${++keyCount}`; const config = { toString() { return (import_meta2.env ? import_meta2.env.MODE : void 0) !== "production" && this.debugLabel ? key + ":" + this.debugLabel : key; } }; if (typeof read === "function") { config.read = read; } else { config.init = read; config.read = defaultRead; config.write = defaultWrite; } if (write) { config.write = write; } return config; } function defaultRead(get) { return get(this); } function defaultWrite(get, set, arg) { return set( this, typeof arg === "function" ? arg(get(this)) : arg ); } var overriddenCreateStore; function createStore() { if (overriddenCreateStore) { return overriddenCreateStore(); } return buildStore(); } var defaultStore; function getDefaultStore() { if (!defaultStore) { defaultStore = createStore(); if ((import_meta2.env ? import_meta2.env.MODE : void 0) !== "production") { globalThis.__JOTAI_DEFAULT_STORE__ || (globalThis.__JOTAI_DEFAULT_STORE__ = defaultStore); if (globalThis.__JOTAI_DEFAULT_STORE__ !== defaultStore) { console.warn( "Detected multiple Jotai instances. It may cause unexpected behavior with the default store. https://github.com/pmndrs/jotai/discussions/2044" ); } } } return defaultStore; } // ../../node_modules/jotai/esm/react.mjs var import_react = __toESM(require("react"), 1); var import_meta3 = {}; var StoreContext = (0, import_react.createContext)( void 0 ); function useStore(options) { const store2 = (0, import_react.useContext)(StoreContext); return (options == null ? void 0 : options.store) || store2 || getDefaultStore(); } var isPromiseLike2 = (x) => typeof (x == null ? void 0 : x.then) === "function"; var attachPromiseStatus = (promise) => { if (!promise.status) { promise.status = "pending"; promise.then( (v) => { promise.status = "fulfilled"; promise.value = v; }, (e) => { promise.status = "rejected"; promise.reason = e; } ); } }; var use = import_react.default.use || // A shim for older React versions ((promise) => { if (promise.status === "pending") { throw promise; } else if (promise.status === "fulfilled") { return promise.value; } else if (promise.status === "rejected") { throw promise.reason; } else { attachPromiseStatus(promise); throw promise; } }); var continuablePromiseMap = /* @__PURE__ */ new WeakMap(); var createContinuablePromise = (store2, promise, getValue) => { const buildingBlocks = getBuildingBlocks(store2); const registerAbortHandler = buildingBlocks[26]; let continuablePromise = continuablePromiseMap.get(promise); if (!continuablePromise) { continuablePromise = new Promise((resolve, reject) => { let curr = promise; const onFulfilled = (me) => (v) => { if (curr === me) { resolve(v); } }; const onRejected = (me) => (e) => { if (curr === me) { reject(e); } }; const onAbort = () => { try { const nextValue = getValue(); if (isPromiseLike2(nextValue)) { continuablePromiseMap.set(nextValue, continuablePromise); curr = nextValue; nextValue.then(onFulfilled(nextValue), onRejected(nextValue)); registerAbortHandler(store2, nextValue, onAbort); } else { resolve(nextValue); } } catch (e) { reject(e); } }; promise.then(onFulfilled(promise), onRejected(promise)); registerAbortHandler(store2, promise, onAbort); }); continuablePromiseMap.set(promise, continuablePromise); } return continuablePromise; }; function useAtomValue(atom2, options) { const { delay, unstable_promiseStatus: promiseStatus = !import_react.default.use } = options || {}; const store2 = useStore(options); const [[valueFromReducer, storeFromReducer, atomFromReducer], rerender] = (0, import_react.useReducer)( (prev) => { const nextValue = store2.get(atom2); if (Object.is(prev[0], nextValue) && prev[1] === store2 && prev[2] === atom2) { return prev; } return [nextValue, store2, atom2]; }, void 0, () => [store2.get(atom2), store2, atom2] ); let value = valueFromReducer; if (storeFromReducer !== store2 || atomFromReducer !== atom2) { rerender(); value = store2.get(atom2); } (0, import_react.useEffect)(() => { const unsub = store2.sub(atom2, () => { if (promiseStatus) { try { const value2 = store2.get(atom2); if (isPromiseLike2(value2)) { attachPromiseStatus( createContinuablePromise(store2, value2, () => store2.get(atom2)) ); } } catch (e) { } } if (typeof delay === "number") { console.warn(`[DEPRECATED] delay option is deprecated and will be removed in v3. Migration guide: Create a custom hook like the following. function useAtomValueWithDelay<Value>( atom: Atom<Value>, options: { delay: number }, ): Value { const { delay } = options const store = useStore(options) const [value, setValue] = useState(() => store.get(atom)) useEffect(() => { const unsub = store.sub(atom, () => { setTimeout(() => setValue(store.get(atom)), delay) }) return unsub }, [store, atom, delay]) return value } `); setTimeout(rerender, delay); return; } rerender(); }); rerender(); return unsub; }, [store2, atom2, delay, promiseStatus]); (0, import_react.useDebugValue)(value); if (isPromiseLike2(value)) { const promise = createContinuablePromise( store2, value, () => store2.get(atom2) ); if (promiseStatus) { attachPromiseStatus(promise); } return use(promise); } return value; } function useSetAtom(atom2, options) { const store2 = useStore(options); const setAtom = (0, import_react.useCallback)( (...args) => { if ((import_meta3.env ? import_meta3.env.MODE : void 0) !== "production" && !("write" in atom2)) { throw new Error("not writable atom"); } return store2.set(atom2, ...args); }, [store2, atom2] ); return setAtom; } // src/hooks.tsx var store = createStore(); var storyContextAtom = atom(null); function useSetStoryContext() { return useSetAtom(storyContextAtom, { store }); } function useStoryContext() { return useAtomValue(storyContextAtom, { store }); } // src/components/StoryView/ErrorBoundary.tsx var import_react2 = __toESM(require("react")); var import_react_native2 = require("react-native"); var import_jsx_runtime = require("react/jsx-runtime"); var ErrorBoundary = class extends import_react2.default.Component { constructor(props) { super(props); this.state = { hasError: false }; } static getDerivedStateFromError(_error) { return { hasError: true }; } componentDidCatch(error, info) { this.props.onError(error, info.componentStack); } render() { if (this.state.hasError) { return /* @__PURE__ */ (0, import_jsx_runtime.jsx)( import_react_native2.View, { style: { margin: 16, padding: 16, borderColor: "red", borderWidth: 2, alignItems: "center", justifyContent: "center", borderRadius: 4 }, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react_native2.Text, { style: { fontWeight: "bold" }, children: "Something went wrong rendering your story" }) } ); } return this.props.children; } }; // src/components/StoryView/StoryView.tsx var import_jsx_runtime2 = require("react/jsx-runtime"); function dismissOnStartResponder() { import_react_native3.Keyboard.dismiss(); return false; } var Text2 = import_react_native_theming.styled.Text(({ theme: theme3 }) => ({ color: theme3?.color?.defaultText })); var errorContainerStyle = { flex: 1, padding: 16, alignItems: "center", justifyContent: "center" }; var layoutStyles = { padded: { padding: 8 }, centered: { alignItems: "center", justifyContent: "center" }, fullscreen: {} }; var StoryView = ({ useWrapper = true, storyBackgroundColor }) => { const context = useStoryContext(); const id = context?.id; const theme3 = (0, import_react_native_theming.useTheme)(); const containerStyle = (0, import_react3.useMemo)(() => { const layout = context?.parameters?.layout; const layoutStyle = layout ? layoutStyles[layout] : {}; return { flex: 1, backgroundColor: storyBackgroundColor || theme3.background?.content, overflow: "hidden", ...layoutStyle }; }, [theme3.background?.content, context?.parameters?.layout, storyBackgroundColor]); const onError = (0, import_react3.useCallback)(() => { console.log(`Error rendering story for ${context?.title} ${context?.name}`); }, [context?.title, context?.name]); if (context && context.unboundStoryFn) { const { unboundStoryFn: StoryComponent } = context; if (useWrapper) { return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)( import_react_native3.View, { style: containerStyle, testID: id, accessibilityLabel: id, importantForAccessibility: "no", onStartShouldSetResponder: dismissOnStartResponder, children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(ErrorBoundary, { onError, children: StoryComponent && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(StoryComponent, { ...context }) }) }, id ); } return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(ErrorBoundary, { onError, children: StoryComponent && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(StoryComponent, { ...context }) }); } return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_react_native3.View, { style: errorContainerStyle, children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Text2, { children: "Please select a story to preview." }) }); }; var StoryView_default = import_react3.default.memo(StoryView); // src/constants.ts var RN_STORYBOOK_STORAGE_KEY = "lastOpenedStory"; var RN_STORYBOOK_EVENTS = { RN_GET_INDEX: "RN_GET_INDEX", RN_GET_INDEX_RESPONSE: "RN_GET_INDEX_RESPONSE" }; var STORYBOOK_STORY_ID_PARAM = "STORYBOOK_STORY_ID"; // src/View.tsx var import_jsx_runtime3 = require("react/jsx-runtime"); function resolveStoryBackgroundColor(story) { const backgroundGlobal = story?.globals?.backgrounds?.value; const bgParams = story?.parameters?.backgrounds; const backgroundName = backgroundGlobal; if (!backgroundName) return void 0; if (bgParams?.options?.[backgroundName]?.value) { return bgParams.options[backgroundName].value; } if (backgroundName.startsWith("#")) return backgroundName; return void 0; } var View3 = class { _storyIndex; _setStory = () => { }; _forceRerender = () => { }; _ready = false; _preview; _asyncStorageStoryId; _webUrl; _storage; _channel; _idToPrepared = {}; constructor(preview, channel) { this._preview = preview; this._channel = channel; } _storyIdExists = (storyId) => { return Object.keys(this._storyIndex.entries).includes(storyId); }; _getInitialStory = async ({ initialSelection, shouldPersistSelection = true } = {}) => { if (initialSelection) { if (typeof initialSelection === "string") { return { storySpecifier: initialSelection, viewMode: "story" }; } else { return { storySpecifier: (0, import_csf.toId)(initialSelection.kind, initialSelection.name), viewMode: "story" }; } } if (shouldPersistSelection) { try { let value = this._asyncStorageStoryId; if (!value && this._storage != null) { value = await this._storage.getItem(RN_STORYBOOK_STORAGE_KEY); this._asyncStorageStoryId = value; } const exists = value && this._storyIdExists(value); if (!exists) console.log("Storybook: could not find persisted story"); return { storySpecifier: exists ? value : "*", viewMode: "story" }; } catch (e) { console.warn("storybook-log: error reading from async storage", e); } } return { storySpecifier: "*", viewMode: "story" }; }; _getHost = (params = {}) => { if (params.host) { return params.host; } if (globalThis.STORYBOOK_WEBSOCKET?.host) { return globalThis.STORYBOOK_WEBSOCKET.host; } return import_react_native4.Platform.OS === "android" ? "10.0.2.2" : "localhost"; }; __getPort = (params = {}) => { if (params.port) { return params.port; } if (globalThis.STORYBOOK_WEBSOCKET?.port) { return globalThis.STORYBOOK_WEBSOCKET.port; } return 7007; }; _isSecureConnection = (params = {}) => { if (typeof params.secured === "boolean") { return params.secured; } return globalThis.STORYBOOK_WEBSOCKET?.secured ?? false; }; _getServerChannel = (params = {}) => { const host = this._getHost(params); const port = `:${this.__getPort(params)}`; const query = params.query || ""; const websocketType = this._isSecureConnection(params) ? "wss" : "ws"; const url = `${websocketType}://${host}${port}/${query}`; const channel = new import_channels.Channel({ async: true, transport: new import_channels.WebsocketTransport({ url, onError: (e) => { console.log(`WebsocketTransport error ${JSON.stringify(e)}`); } }) }); patchChannelForRN(channel); return channel; }; createPreparedStoryMapping = async () => { await this._preview.ready().then( () => Promise.all( Object.keys(this._storyIndex.entries).map(async (storyId) => { this._idToPrepared[storyI