@storybook/react-native
Version:
A better way to develop React Native Components for your app
1,259 lines (1,246 loc) • 43.3 kB
JavaScript
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 __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/index.ts
var src_exports = {};
__export(src_exports, {
darkTheme: () => import_react_native_theming3.darkTheme,
getProjectAnnotations: () => getProjectAnnotations,
prepareStories: () => prepareStories,
start: () => start,
theme: () => import_react_native_theming3.theme,
updateView: () => updateView
});
module.exports = __toCommonJS(src_exports);
var import_react_native_theming3 = require("@storybook/react-native-theming");
// src/Start.tsx
var import_react_native4 = require("react-native");
var import_manager_api2 = require("@storybook/core/manager-api");
var import_preview_api2 = require("@storybook/core/preview-api");
var import_csf2 = require("@storybook/csf");
var import_channels2 = require("@storybook/core/channels");
// src/View.tsx
var import_bottom_sheet = require("@gorhom/bottom-sheet");
var import_channels = require("@storybook/core/channels");
var import_core_events = __toESM(require("@storybook/core/core-events"));
var import_csf = require("@storybook/csf");
var import_manager_api = require("@storybook/core/manager-api");
var import_preview_api = require("@storybook/core/preview-api");
var import_react_native_theming2 = require("@storybook/react-native-theming");
var import_react_native_ui = require("@storybook/react-native-ui");
var import_dedent = __toESM(require("dedent"));
var import_deepmerge = __toESM(require("deepmerge"));
var import_react4 = require("react");
var import_react_native3 = require("react-native");
var import_react_native_gesture_handler = require("react-native-gesture-handler");
var import_react_native_safe_area_context = require("react-native-safe-area-context");
// src/components/StoryView/StoryView.tsx
var import_react3 = __toESM(require("react"));
var import_react_native_theming = require("@storybook/react-native-theming");
var import_react_native2 = require("react-native");
// ../../node_modules/jotai/esm/vanilla.mjs
var import_meta = {};
var keyCount = 0;
function atom(read, write) {
const key = `atom${++keyCount}`;
const config = {
toString: () => key
};
if (typeof read === "function") {
config.read = read;
} else {
config.init = read;
config.read = function(get) {
return get(this);
};
config.write = function(get, set, arg) {
return set(
this,
typeof arg === "function" ? arg(get(this)) : arg
);
};
}
if (write) {
config.write = write;
}
return config;
}
var hasInitialValue = (atom2) => "init" in atom2;
var isActuallyWritableAtom = (atom2) => !!atom2.write;
var cancelPromiseMap = /* @__PURE__ */ new WeakMap();
var registerCancelPromise = (promise, cancel) => {
cancelPromiseMap.set(promise, cancel);
promise.catch(() => {
}).finally(() => cancelPromiseMap.delete(promise));
};
var cancelPromise = (promise, next) => {
const cancel = cancelPromiseMap.get(promise);
if (cancel) {
cancelPromiseMap.delete(promise);
cancel(next);
}
};
var resolvePromise = (promise, value) => {
promise.status = "fulfilled";
promise.value = value;
};
var rejectPromise = (promise, e) => {
promise.status = "rejected";
promise.reason = e;
};
var isPromiseLike = (x) => typeof (x == null ? void 0 : x.then) === "function";
var isEqualAtomValue = (a, b) => !!a && "v" in a && "v" in b && Object.is(a.v, b.v);
var isEqualAtomError = (a, b) => !!a && "e" in a && "e" in b && Object.is(a.e, b.e);
var hasPromiseAtomValue = (a) => !!a && "v" in a && a.v instanceof Promise;
var isEqualPromiseAtomValue = (a, b) => "v" in a && "v" in b && a.v.orig && a.v.orig === b.v.orig;
var returnAtomValue = (atomState) => {
if ("e" in atomState) {
throw atomState.e;
}
return atomState.v;
};
var createStore = () => {
const atomStateMap = /* @__PURE__ */ new WeakMap();
const mountedMap = /* @__PURE__ */ new WeakMap();
const pendingMap = /* @__PURE__ */ new Map();
let storeListenersRev2;
let mountedAtoms;
if ((import_meta.env ? import_meta.env.MODE : void 0) !== "production") {
storeListenersRev2 = /* @__PURE__ */ new Set();
mountedAtoms = /* @__PURE__ */ new Set();
}
const getAtomState = (atom2) => atomStateMap.get(atom2);
const setAtomState = (atom2, atomState) => {
if ((import_meta.env ? import_meta.env.MODE : void 0) !== "production") {
Object.freeze(atomState);
}
const prevAtomState = atomStateMap.get(atom2);
atomStateMap.set(atom2, atomState);
if (!pendingMap.has(atom2)) {
pendingMap.set(atom2, prevAtomState);
}
if (hasPromiseAtomValue(prevAtomState)) {
const next = "v" in atomState ? atomState.v instanceof Promise ? atomState.v : Promise.resolve(atomState.v) : Promise.reject(atomState.e);
if (prevAtomState.v !== next) {
cancelPromise(prevAtomState.v, next);
}
}
};
const updateDependencies = (atom2, nextAtomState, nextDependencies) => {
const dependencies = /* @__PURE__ */ new Map();
let changed = false;
nextDependencies.forEach((aState, a) => {
if (!aState && a === atom2) {
aState = nextAtomState;
}
if (aState) {
dependencies.set(a, aState);
if (nextAtomState.d.get(a) !== aState) {
changed = true;
}
} else if ((import_meta.env ? import_meta.env.MODE : void 0) !== "production") {
console.warn("[Bug] atom state not found");
}
});
if (changed || nextAtomState.d.size !== dependencies.size) {
nextAtomState.d = dependencies;
}
};
const setAtomValue = (atom2, value, nextDependencies) => {
const prevAtomState = getAtomState(atom2);
const nextAtomState = {
d: (prevAtomState == null ? void 0 : prevAtomState.d) || /* @__PURE__ */ new Map(),
v: value
};
if (nextDependencies) {
updateDependencies(atom2, nextAtomState, nextDependencies);
}
if (isEqualAtomValue(prevAtomState, nextAtomState) && prevAtomState.d === nextAtomState.d) {
return prevAtomState;
}
if (hasPromiseAtomValue(prevAtomState) && hasPromiseAtomValue(nextAtomState) && isEqualPromiseAtomValue(prevAtomState, nextAtomState)) {
if (prevAtomState.d === nextAtomState.d) {
return prevAtomState;
} else {
nextAtomState.v = prevAtomState.v;
}
}
setAtomState(atom2, nextAtomState);
return nextAtomState;
};
const setAtomValueOrPromise = (atom2, valueOrPromise, nextDependencies, abortPromise) => {
if (isPromiseLike(valueOrPromise)) {
let continuePromise;
const updatePromiseDependencies = () => {
const prevAtomState = getAtomState(atom2);
if (!hasPromiseAtomValue(prevAtomState) || prevAtomState.v !== promise) {
return;
}
const nextAtomState = setAtomValue(
atom2,
promise,
nextDependencies
);
if (mountedMap.has(atom2) && prevAtomState.d !== nextAtomState.d) {
mountDependencies(atom2, nextAtomState, prevAtomState.d);
}
};
const promise = new Promise((resolve, reject) => {
let settled = false;
valueOrPromise.then(
(v) => {
if (!settled) {
settled = true;
resolvePromise(promise, v);
resolve(v);
updatePromiseDependencies();
}
},
(e) => {
if (!settled) {
settled = true;
rejectPromise(promise, e);
reject(e);
updatePromiseDependencies();
}
}
);
continuePromise = (next) => {
if (!settled) {
settled = true;
next.then(
(v) => resolvePromise(promise, v),
(e) => rejectPromise(promise, e)
);
resolve(next);
}
};
});
promise.orig = valueOrPromise;
promise.status = "pending";
registerCancelPromise(promise, (next) => {
if (next) {
continuePromise(next);
}
abortPromise == null ? void 0 : abortPromise();
});
return setAtomValue(atom2, promise, nextDependencies);
}
return setAtomValue(atom2, valueOrPromise, nextDependencies);
};
const setAtomError = (atom2, error, nextDependencies) => {
const prevAtomState = getAtomState(atom2);
const nextAtomState = {
d: (prevAtomState == null ? void 0 : prevAtomState.d) || /* @__PURE__ */ new Map(),
e: error
};
if (nextDependencies) {
updateDependencies(atom2, nextAtomState, nextDependencies);
}
if (isEqualAtomError(prevAtomState, nextAtomState) && prevAtomState.d === nextAtomState.d) {
return prevAtomState;
}
setAtomState(atom2, nextAtomState);
return nextAtomState;
};
const readAtomState = (atom2, force) => {
const atomState = getAtomState(atom2);
if (!force && atomState) {
if (mountedMap.has(atom2)) {
return atomState;
}
if (Array.from(atomState.d).every(([a, s]) => {
if (a === atom2) {
return true;
}
const aState = readAtomState(a);
return aState === s || isEqualAtomValue(aState, s);
})) {
return atomState;
}
}
const nextDependencies = /* @__PURE__ */ new Map();
let isSync = true;
const getter = (a) => {
if (a === atom2) {
const aState2 = getAtomState(a);
if (aState2) {
nextDependencies.set(a, aState2);
return returnAtomValue(aState2);
}
if (hasInitialValue(a)) {
nextDependencies.set(a, void 0);
return a.init;
}
throw new Error("no atom init");
}
const aState = readAtomState(a);
nextDependencies.set(a, aState);
return returnAtomValue(aState);
};
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" && !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) {
return writeAtom(atom2, ...args);
}
};
}
return setSelf;
}
};
try {
const valueOrPromise = atom2.read(getter, options);
return setAtomValueOrPromise(
atom2,
valueOrPromise,
nextDependencies,
() => controller == null ? void 0 : controller.abort()
);
} catch (error) {
return setAtomError(atom2, error, nextDependencies);
} finally {
isSync = false;
}
};
const readAtom = (atom2) => returnAtomValue(readAtomState(atom2));
const addAtom = (atom2) => {
let mounted = mountedMap.get(atom2);
if (!mounted) {
mounted = mountAtom(atom2);
}
return mounted;
};
const canUnmountAtom = (atom2, mounted) => !mounted.l.size && (!mounted.t.size || mounted.t.size === 1 && mounted.t.has(atom2));
const delAtom = (atom2) => {
const mounted = mountedMap.get(atom2);
if (mounted && canUnmountAtom(atom2, mounted)) {
unmountAtom(atom2);
}
};
const recomputeDependents = (atom2) => {
const dependencyMap = /* @__PURE__ */ new Map();
const dirtyMap = /* @__PURE__ */ new WeakMap();
const getDependents = (a) => {
var _a;
const dependents = new Set((_a = mountedMap.get(a)) == null ? void 0 : _a.t);
pendingMap.forEach((_, pendingAtom) => {
var _a2;
if ((_a2 = getAtomState(pendingAtom)) == null ? void 0 : _a2.d.has(a)) {
dependents.add(pendingAtom);
}
});
return dependents;
};
const loop1 = (a) => {
getDependents(a).forEach((dependent) => {
if (dependent !== a) {
dependencyMap.set(
dependent,
(dependencyMap.get(dependent) || /* @__PURE__ */ new Set()).add(a)
);
dirtyMap.set(dependent, (dirtyMap.get(dependent) || 0) + 1);
loop1(dependent);
}
});
};
loop1(atom2);
const loop2 = (a) => {
getDependents(a).forEach((dependent) => {
var _a;
if (dependent !== a) {
let dirtyCount = dirtyMap.get(dependent);
if (dirtyCount) {
dirtyMap.set(dependent, --dirtyCount);
}
if (!dirtyCount) {
let isChanged = !!((_a = dependencyMap.get(dependent)) == null ? void 0 : _a.size);
if (isChanged) {
const prevAtomState = getAtomState(dependent);
const nextAtomState = readAtomState(dependent, true);
isChanged = !isEqualAtomValue(prevAtomState, nextAtomState);
}
if (!isChanged) {
dependencyMap.forEach((s) => s.delete(dependent));
}
}
loop2(dependent);
}
});
};
loop2(atom2);
};
const writeAtomState = (atom2, ...args) => {
let isSync = true;
const getter = (a) => returnAtomValue(readAtomState(a));
const setter = (a, ...args2) => {
let r;
if (a === atom2) {
if (!hasInitialValue(a)) {
throw new Error("atom not writable");
}
const prevAtomState = getAtomState(a);
const nextAtomState = setAtomValueOrPromise(a, args2[0]);
if (!isEqualAtomValue(prevAtomState, nextAtomState)) {
recomputeDependents(a);
}
} else {
r = writeAtomState(a, ...args2);
}
if (!isSync) {
const flushed = flushPending();
if ((import_meta.env ? import_meta.env.MODE : void 0) !== "production") {
storeListenersRev2.forEach(
(l) => l({ type: "async-write", flushed })
);
}
}
return r;
};
const result = atom2.write(getter, setter, ...args);
isSync = false;
return result;
};
const writeAtom = (atom2, ...args) => {
const result = writeAtomState(atom2, ...args);
const flushed = flushPending();
if ((import_meta.env ? import_meta.env.MODE : void 0) !== "production") {
storeListenersRev2.forEach(
(l) => l({ type: "write", flushed })
);
}
return result;
};
const mountAtom = (atom2, initialDependent, onMountQueue) => {
var _a;
const queue = onMountQueue || [];
(_a = getAtomState(atom2)) == null ? void 0 : _a.d.forEach((_, a) => {
const aMounted = mountedMap.get(a);
if (aMounted) {
aMounted.t.add(atom2);
} else {
if (a !== atom2) {
mountAtom(a, atom2, queue);
}
}
});
readAtomState(atom2);
const mounted = {
t: new Set(initialDependent && [initialDependent]),
l: /* @__PURE__ */ new Set()
};
mountedMap.set(atom2, mounted);
if ((import_meta.env ? import_meta.env.MODE : void 0) !== "production") {
mountedAtoms.add(atom2);
}
if (isActuallyWritableAtom(atom2) && atom2.onMount) {
const { onMount } = atom2;
queue.push(() => {
const onUnmount = onMount((...args) => writeAtom(atom2, ...args));
if (onUnmount) {
mounted.u = onUnmount;
}
});
}
if (!onMountQueue) {
queue.forEach((f) => f());
}
return mounted;
};
const unmountAtom = (atom2) => {
var _a;
const onUnmount = (_a = mountedMap.get(atom2)) == null ? void 0 : _a.u;
if (onUnmount) {
onUnmount();
}
mountedMap.delete(atom2);
if ((import_meta.env ? import_meta.env.MODE : void 0) !== "production") {
mountedAtoms.delete(atom2);
}
const atomState = getAtomState(atom2);
if (atomState) {
if (hasPromiseAtomValue(atomState)) {
cancelPromise(atomState.v);
}
atomState.d.forEach((_, a) => {
if (a !== atom2) {
const mounted = mountedMap.get(a);
if (mounted) {
mounted.t.delete(atom2);
if (canUnmountAtom(a, mounted)) {
unmountAtom(a);
}
}
}
});
} else if ((import_meta.env ? import_meta.env.MODE : void 0) !== "production") {
console.warn("[Bug] could not find atom state to unmount", atom2);
}
};
const mountDependencies = (atom2, atomState, prevDependencies) => {
const depSet = new Set(atomState.d.keys());
const maybeUnmountAtomSet = /* @__PURE__ */ new Set();
prevDependencies == null ? void 0 : prevDependencies.forEach((_, a) => {
if (depSet.has(a)) {
depSet.delete(a);
return;
}
maybeUnmountAtomSet.add(a);
const mounted = mountedMap.get(a);
if (mounted) {
mounted.t.delete(atom2);
}
});
depSet.forEach((a) => {
const mounted = mountedMap.get(a);
if (mounted) {
mounted.t.add(atom2);
} else if (mountedMap.has(atom2)) {
mountAtom(a, atom2);
}
});
maybeUnmountAtomSet.forEach((a) => {
const mounted = mountedMap.get(a);
if (mounted && canUnmountAtom(a, mounted)) {
unmountAtom(a);
}
});
};
const flushPending = () => {
let flushed;
if ((import_meta.env ? import_meta.env.MODE : void 0) !== "production") {
flushed = /* @__PURE__ */ new Set();
}
while (pendingMap.size) {
const pending = Array.from(pendingMap);
pendingMap.clear();
pending.forEach(([atom2, prevAtomState]) => {
const atomState = getAtomState(atom2);
if (atomState) {
const mounted = mountedMap.get(atom2);
if (mounted && atomState.d !== (prevAtomState == null ? void 0 : prevAtomState.d)) {
mountDependencies(atom2, atomState, prevAtomState == null ? void 0 : prevAtomState.d);
}
if (mounted && !// TODO This seems pretty hacky. Hope to fix it.
// Maybe we could `mountDependencies` in `setAtomState`?
(!hasPromiseAtomValue(prevAtomState) && (isEqualAtomValue(prevAtomState, atomState) || isEqualAtomError(prevAtomState, atomState)))) {
mounted.l.forEach((listener) => listener());
if ((import_meta.env ? import_meta.env.MODE : void 0) !== "production") {
flushed.add(atom2);
}
}
} else if ((import_meta.env ? import_meta.env.MODE : void 0) !== "production") {
console.warn("[Bug] no atom state to flush");
}
});
}
if ((import_meta.env ? import_meta.env.MODE : void 0) !== "production") {
return flushed;
}
};
const subscribeAtom = (atom2, listener) => {
const mounted = addAtom(atom2);
const flushed = flushPending();
const listeners = mounted.l;
listeners.add(listener);
if ((import_meta.env ? import_meta.env.MODE : void 0) !== "production") {
storeListenersRev2.forEach(
(l) => l({ type: "sub", flushed })
);
}
return () => {
listeners.delete(listener);
delAtom(atom2);
if ((import_meta.env ? import_meta.env.MODE : void 0) !== "production") {
storeListenersRev2.forEach((l) => l({ type: "unsub" }));
}
};
};
if ((import_meta.env ? import_meta.env.MODE : void 0) !== "production") {
return {
get: readAtom,
set: writeAtom,
sub: subscribeAtom,
// store dev methods (these are tentative and subject to change without notice)
dev_subscribe_store: (l, rev) => {
if (rev !== 2) {
throw new Error("The current StoreListener revision is 2.");
}
storeListenersRev2.add(l);
return () => {
storeListenersRev2.delete(l);
};
},
dev_get_mounted_atoms: () => mountedAtoms.values(),
dev_get_atom_state: (a) => atomStateMap.get(a),
dev_get_mounted: (a) => mountedMap.get(a),
dev_restore_atoms: (values) => {
for (const [atom2, valueOrPromise] of values) {
if (hasInitialValue(atom2)) {
setAtomValueOrPromise(atom2, valueOrPromise);
recomputeDependents(atom2);
}
}
const flushed = flushPending();
storeListenersRev2.forEach(
(l) => l({ type: "restore", flushed })
);
}
};
}
return {
get: readAtom,
set: writeAtom,
sub: subscribeAtom
};
};
var defaultStore;
if ((import_meta.env ? import_meta.env.MODE : void 0) !== "production") {
if (typeof globalThis.__NUMBER_OF_JOTAI_INSTANCES__ === "number") {
++globalThis.__NUMBER_OF_JOTAI_INSTANCES__;
} else {
globalThis.__NUMBER_OF_JOTAI_INSTANCES__ = 1;
}
}
var getDefaultStore = () => {
if (!defaultStore) {
defaultStore = createStore();
}
return defaultStore;
};
// ../../node_modules/jotai/esm/react.mjs
var import_react = __toESM(require("react"), 1);
var import_meta2 = {};
var StoreContext = (0, import_react.createContext)(void 0);
var useStore = (options) => {
const store = (0, import_react.useContext)(StoreContext);
return (options == null ? void 0 : options.store) || store || getDefaultStore();
};
var isPromiseLike2 = (x) => typeof (x == null ? void 0 : x.then) === "function";
var use = import_react.default.use || ((promise) => {
if (promise.status === "pending") {
throw promise;
} else if (promise.status === "fulfilled") {
return promise.value;
} else if (promise.status === "rejected") {
throw promise.reason;
} else {
promise.status = "pending";
promise.then(
(v) => {
promise.status = "fulfilled";
promise.value = v;
},
(e) => {
promise.status = "rejected";
promise.reason = e;
}
);
throw promise;
}
});
function useAtomValue(atom2, options) {
const store = useStore(options);
const [[valueFromReducer, storeFromReducer, atomFromReducer], rerender] = (0, import_react.useReducer)(
(prev) => {
const nextValue = store.get(atom2);
if (Object.is(prev[0], nextValue) && prev[1] === store && prev[2] === atom2) {
return prev;
}
return [nextValue, store, atom2];
},
void 0,
() => [store.get(atom2), store, atom2]
);
let value = valueFromReducer;
if (storeFromReducer !== store || atomFromReducer !== atom2) {
rerender();
value = store.get(atom2);
}
const delay = options == null ? void 0 : options.delay;
(0, import_react.useEffect)(() => {
const unsub = store.sub(atom2, () => {
if (typeof delay === "number") {
setTimeout(rerender, delay);
return;
}
rerender();
});
rerender();
return unsub;
}, [store, atom2, delay]);
(0, import_react.useDebugValue)(value);
return isPromiseLike2(value) ? use(value) : value;
}
function useSetAtom(atom2, options) {
const store = useStore(options);
const setAtom = (0, import_react.useCallback)(
(...args) => {
if ((import_meta2.env ? import_meta2.env.MODE : void 0) !== "production" && !("write" in atom2)) {
throw new Error("not writable atom");
}
return store.set(atom2, ...args);
},
[store, atom2]
);
return setAtom;
}
// src/hooks.tsx
var storyContextAtom = atom(null);
function useSetStoryContext() {
return useSetAtom(storyContextAtom);
}
function useStoryContext() {
return useAtomValue(storyContextAtom);
}
// src/components/StoryView/ErrorBoundary.tsx
var import_react2 = __toESM(require("react"));
var import_react_native = 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_native.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_native.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_native2.Keyboard.dismiss();
return false;
}
var Text2 = import_react_native_theming.styled.Text(({ theme: theme3 }) => ({
color: theme3?.color?.defaultText
}));
var StoryView = () => {
const context = useStoryContext();
const id = context?.id;
const theme3 = (0, import_react_native_theming.useTheme)();
if (context && context.unboundStoryFn) {
const { unboundStoryFn: StoryComponent } = context;
return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
import_react_native2.View,
{
style: { flex: 1, backgroundColor: theme3.background?.content },
testID: id,
onStartShouldSetResponder: dismissOnStartResponder,
children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
ErrorBoundary,
{
onError: () => {
console.log(`Error rendering story for ${context.title} ${context.name}`);
},
children: StoryComponent && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(StoryComponent, { ...context })
}
)
},
id
);
}
return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_react_native2.View, { style: { flex: 1, padding: 16, alignItems: "center", justifyContent: "center" }, children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Text2, { children: "Please open the sidebar and select a story to preview." }) });
};
var StoryView_default = import_react3.default.memo(StoryView);
// src/rn-host-detect.js
function getByRemoteConfig(hostname) {
var remoteModuleConfig = window?.__fbBatchedBridgeConfig?.remoteModuleConfig;
if (!Array.isArray(remoteModuleConfig) || hostname !== "localhost" && hostname !== "127.0.0.1") {
return { hostname, passed: false };
}
var constants = (remoteModuleConfig.find(getConstants) || [])[1];
if (constants) {
var serverHost = constants.ServerHost || hostname;
return { hostname: serverHost.split(":")[0], passed: true };
}
return { hostname, passed: false };
}
function getConstants(config) {
return config && (config[0] === "AndroidConstants" || config[0] === "PlatformConstants");
}
function getByRNRequirePolyfill(hostname) {
var NativeModules;
var PlatformConstants;
var AndroidConstants;
if (typeof window === "undefined" || !window.__DEV__ || typeof window.require !== "function" || // RN >= 0.56
// TODO: Get NativeModules for RN >= 0.56
window.require.name === "metroRequire") {
return hostname;
}
NativeModules = window.require("NativeModules");
if (!NativeModules || !NativeModules.PlatformConstants && !NativeModules.AndroidConstants) {
return hostname;
}
PlatformConstants = NativeModules.PlatformConstants;
AndroidConstants = NativeModules.AndroidConstants;
var serverHost = (PlatformConstants ? PlatformConstants.ServerHost : AndroidConstants.ServerHost) || hostname;
return serverHost.split(":")[0];
}
function getHost(hostname) {
if (typeof __fbBatchedBridge !== "object" || hostname !== "localhost" && hostname !== "127.0.0.1") {
return hostname;
}
var result = getByRemoteConfig(hostname);
if (result.passed) {
return result.hostname;
}
return getByRNRequirePolyfill(hostname);
}
// src/View.tsx
var import_jsx_runtime3 = require("react/jsx-runtime");
var STORAGE_KEY = "lastOpenedStory";
var View3 = class {
_storyIndex;
_setStory = () => {
};
_forceRerender = () => {
};
_ready = false;
_preview;
_asyncStorageStoryId;
_webUrl;
_storage;
_channel;
_idToPrepared = {};
constructor(preview, channel) {
this._preview = preview;
this._channel = channel;
}
_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(STORAGE_KEY);
this._asyncStorageStoryId = value;
}
const exists = value && Object.keys(this._storyIndex.entries).includes(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" };
};
_getServerChannel = (params = {}) => {
const host = getHost(params.host || "localhost");
const port = `:${params.port || 7007}`;
const query = params.query || "";
const websocketType = params.secured ? "wss" : "ws";
const url = `${websocketType}://${host}${port}/${query}`;
const channel = new import_channels.Channel({
transport: new import_channels.WebsocketTransport({
url,
onError: (e) => {
console.log(`WebsocketTransport error ${JSON.stringify(e)}`);
}
}),
async: true
});
return channel;
};
createPreparedStoryMapping = async () => {
await this._preview.ready().then(
() => Promise.all(
Object.keys(this._storyIndex.entries).map(async (storyId) => {
this._idToPrepared[storyId] = await this._preview.loadStory({ storyId });
})
)
);
};
getStorybookUI = (params = {}) => {
const {
shouldPersistSelection = true,
onDeviceUI = true,
enableWebsockets = false,
storage
} = params;
this._storage = storage;
const initialStory = this._getInitialStory(params);
if (enableWebsockets) {
const channel = this._getServerChannel(params);
import_manager_api.addons.setChannel(channel);
import_preview_api.addons.setChannel(channel);
this._channel = channel;
this._preview.channel = channel;
this._preview.setupListeners();
channel.emit(import_core_events.default.CHANNEL_CREATED);
this._preview.ready().then(() => this._preview.onStoryIndexChanged());
}
import_manager_api.addons.loadAddons({
store: () => ({
fromId: (id) => {
if (!this._ready) {
throw new Error("Storybook is not ready yet");
}
return this._preview.getStoryContext(this._idToPrepared[id]);
},
getSelection: () => {
return this._preview.currentSelection;
},
_channel: this._channel
})
});
const self = this;
return () => {
const setContext = useSetStoryContext();
const story = useStoryContext();
const colorScheme = (0, import_react_native3.useColorScheme)();
const [update, forceUpdate] = (0, import_react4.useReducer)((x) => x + 1, 0);
const [ready, setReady] = (0, import_react4.useState)(false);
const appliedTheme = (0, import_react4.useMemo)(
() => (0, import_deepmerge.default)(colorScheme === "dark" ? import_react_native_theming2.darkTheme : import_react_native_theming2.theme, params.theme ?? {}),
[colorScheme]
);
(0, import_react4.useEffect)(() => {
this.createPreparedStoryMapping().then(() => {
this._ready = true;
setReady(true);
initialStory.then((st) => {
self._preview.selectionStore.selectionSpecifier = st;
self._preview.selectSpecifiedStory();
});
}).catch((e) => console.error(e));
self._setStory = (newStory) => {
setContext(newStory);
if (shouldPersistSelection && !storage) {
console.warn(import_dedent.default`Please set storage in getStorybookUI like this:
const StorybookUIRoot = view.getStorybookUI({
storage: {
getItem: AsyncStorage.getItem,
setItem: AsyncStorage.setItem,
},
});
`);
}
if (shouldPersistSelection && !!this._storage) {
this._storage.setItem(STORAGE_KEY, newStory.id).catch((e) => {
console.warn("storybook-log: error writing to async storage", e);
});
}
};
self._forceRerender = () => forceUpdate();
}, []);
const storyHash = (0, import_react4.useMemo)(() => {
if (!ready) {
return {};
}
return (0, import_react_native_ui.transformStoryIndexToStoriesHash)(this._storyIndex, {
docsOptions: { docsMode: false, autodocs: false, defaultName: "" },
filters: {},
status: {},
provider: {
handleAPI: () => ({}),
getConfig: () => ({})
}
});
}, [ready, update]);
if (!ready) {
return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
import_react_native3.View,
{
style: {
...import_react_native3.StyleSheet.absoluteFillObject,
alignItems: "center",
justifyContent: "center"
},
children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_react_native3.ActivityIndicator, { animating: true, size: "large" })
}
);
}
if (onDeviceUI) {
return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_react_native_theming2.ThemeProvider, { theme: appliedTheme, children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_react_native_safe_area_context.SafeAreaProvider, { children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_react_native_gesture_handler.GestureHandlerRootView, { style: { flex: 1 }, children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_bottom_sheet.BottomSheetModalProvider, { children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_react_native_ui.LayoutProvider, { children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_react_native_ui.Layout, { storyHash, story, children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(StoryView_default, {}) }) }) }) }) }) });
} else {
return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(StoryView_default, {});
}
};
};
};
// src/Start.tsx
var import_jsx_runtime4 = require("react/jsx-runtime");
if (import_react_native4.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_native4.Platform.OS === "web" && typeof globalThis.setImmediate === "undefined") {
require("setimmediate");
}
function prepareStories({
storyEntries,
options
}) {
let index = {
v: 4,
entries: {}
};
let importMap = {};
const makeTitle = (fileName, specifier, userTitle) => {
const title = (0, import_preview_api2.userOrAutoTitleFromSpecifier)(fileName, specifier, userTitle);
if (title) {
return title.replace("./", "");
} else {
console.log({
fileName,
userTitle,
storyEntries: storyEntries.map((entry) => {
return { ...entry, importPathMatcher: entry.importPathMatcher.source };
}),
title: title ?? ""
});
throw new Error("Could not generate title");
}
};
storyEntries.forEach((specifier) => {
const { req, directory: root } = specifier;
req.keys().forEach((filename) => {
try {
const fileExports = req(filename);
if (!fileExports.default)
return;
const meta = fileExports.default;
Object.keys(fileExports).forEach((key) => {
if (key === "default")
return;
if (!(0, import_csf2.isExportStory)(key, fileExports.default))
return;
const exportValue = fileExports[key];
if (!exportValue)
return;
const name = (0, import_csf2.storyNameFromExport)(key);
const title = makeTitle(filename, specifier, meta.title);
if (title) {
const id = (0, import_csf2.toId)(title, name);
index.entries[id] = {
type: "story",
id,
name,
title,
importPath: `${root}/${filename.substring(2)}`,
// FIXME: use normalize function here
tags: ["story"]
};
const importedStories = req(filename);
const stories = Object.entries(importedStories).reduce(
(carry, [storyKey, story]) => {
if (!(0, import_csf2.isExportStory)(storyKey, fileExports.default))
return carry;
if (story.play && !options?.playFn) {
carry[storyKey] = { ...story, play: void 0 };
} else {
carry[storyKey] = story;
}
return carry;
},
{}
);
importMap[`${root}/${filename.substring(2)}`] = stories;
} else {
console.log(`Unexpected error while loading ${filename}: could not find title`);
}
});
} catch (error) {
const errorString = error.message && error.stack ? `${error.message}
${error.stack}` : error.toString();
console.error(`Unexpected error while loading ${filename}: ${errorString}`);
}
});
});
return { index, importMap };
}
var getProjectAnnotations = (view, annotations) => async () => (0, import_preview_api2.composeConfigs)([
{
renderToCanvas: (context) => {
view._setStory(context.storyContext);
},
render: (args, context) => {
const { id, component: Component } = context;
if (!Component) {
throw new Error(
`Unable to render story ${id} as the component annotation is missing from the default export`
);
}
return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(Component, { ...args });
}
},
...annotations
]);
function start({
annotations,
storyEntries,
options
}) {
const { index, importMap } = prepareStories({ storyEntries, options });
const channel = (0, import_channels2.createBrowserChannel)({ page: "preview" });
import_manager_api2.addons.setChannel(channel);
import_preview_api2.addons.setChannel(channel);
const previewView = {
prepareForStory: () => {
return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_jsx_runtime4.Fragment, {});
},
prepareForDocs: () => {
},
showErrorDisplay: (e) => {
console.log(e);
},
showDocs: () => {
},
showMain: () => {
},
showNoPreview: () => {
},
showPreparingDocs: () => {
},
showPreparingStory: () => {
},
showStory: () => {
},
showStoryDuringRender: () => {
}
// TODO what happened to this type?
};
const selectionStore = {
selection: null,
selectionSpecifier: null,
setQueryParams: () => {
},
setSelection: (selection) => {
preview.selectionStore.selection = selection;
}
};
const getProjectAnnotationsInitial = async () => (0, import_preview_api2.composeConfigs)([
{
renderToCanvas: (context) => {
view._setStory(context.storyContext);
},
render: (args, context) => {
const { id, component: Component } = context;
if (!Component) {
throw new Error(
`Unable to render story ${id} as the component annotation is missing from the default export`
);
}
return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(Component, { ...args });
}
},
...annotations
]);
const preview = new import_preview_api2.PreviewWithSelection(
async (importPath) => importMap[importPath],
getProjectAnnotationsInitial,
selectionStore,
previewView
);
const view = new View3(preview, channel);
if (global) {
global.__STORYBOOK_ADDONS_CHANNEL__ = channel;
global.__STORYBOOK_PREVIEW__ = preview;
}
view._storyIndex = index;
preview.getStoryIndexFromServer = async () => view._storyIndex;
return view;
}
function updateView(viewInstance, annotations, normalizedStories, options) {
const { importMap, index } = prepareStories({ storyEntries: normalizedStories, options });
viewInstance._preview.onStoriesChanged({
importFn: async (importPath) => importMap[importPath]
});
viewInstance._preview.onGetProjectAnnotationsChanged({
getProjectAnnotations: getProjectAnnotations(viewInstance, annotations)
});
viewInstance._storyIndex = index;
viewInstance._preview.onStoryIndexChanged().then(() => {
viewInstance.createPreparedStoryMapping().then(() => viewInstance._forceRerender());
});
}
// Annotate the CommonJS export names for ESM import in node:
0 && (module.exports = {
darkTheme,
getProjectAnnotations,
prepareStories,
start,
theme,
updateView
});