UNPKG

storybook-addon-performance

Version:

A storybook addon to help better understand and debug performance for React components

240 lines (229 loc) 9.83 kB
"use strict"; var __defProp = Object.defineProperty; var __getOwnPropDesc = Object.getOwnPropertyDescriptor; var __getOwnPropNames = Object.getOwnPropertyNames; 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 __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); // src/panel/use-panel-machine.tsx var use_panel_machine_exports = {}; __export(use_panel_machine_exports, { default: () => usePanelMachine }); module.exports = __toCommonJS(use_panel_machine_exports); // ../../node_modules/.pnpm/@storybook+core-events@7.6.10/node_modules/@storybook/core-events/dist/index.mjs var events = ((events2) => (events2.CHANNEL_CREATED = "channelCreated", events2.CONFIG_ERROR = "configError", events2.STORY_INDEX_INVALIDATED = "storyIndexInvalidated", events2.STORY_SPECIFIED = "storySpecified", events2.SET_CONFIG = "setConfig", events2.SET_STORIES = "setStories", events2.SET_INDEX = "setIndex", events2.SET_CURRENT_STORY = "setCurrentStory", events2.CURRENT_STORY_WAS_SET = "currentStoryWasSet", events2.FORCE_RE_RENDER = "forceReRender", events2.FORCE_REMOUNT = "forceRemount", events2.PRELOAD_ENTRIES = "preloadStories", events2.STORY_PREPARED = "storyPrepared", events2.DOCS_PREPARED = "docsPrepared", events2.STORY_CHANGED = "storyChanged", events2.STORY_UNCHANGED = "storyUnchanged", events2.STORY_RENDERED = "storyRendered", events2.STORY_MISSING = "storyMissing", events2.STORY_ERRORED = "storyErrored", events2.STORY_THREW_EXCEPTION = "storyThrewException", events2.STORY_RENDER_PHASE_CHANGED = "storyRenderPhaseChanged", events2.PLAY_FUNCTION_THREW_EXCEPTION = "playFunctionThrewException", events2.UPDATE_STORY_ARGS = "updateStoryArgs", events2.STORY_ARGS_UPDATED = "storyArgsUpdated", events2.RESET_STORY_ARGS = "resetStoryArgs", events2.SET_GLOBALS = "setGlobals", events2.UPDATE_GLOBALS = "updateGlobals", events2.GLOBALS_UPDATED = "globalsUpdated", events2.REGISTER_SUBSCRIPTION = "registerSubscription", events2.PREVIEW_KEYDOWN = "previewKeydown", events2.PREVIEW_BUILDER_PROGRESS = "preview_builder_progress", events2.SELECT_STORY = "selectStory", events2.STORIES_COLLAPSE_ALL = "storiesCollapseAll", events2.STORIES_EXPAND_ALL = "storiesExpandAll", events2.DOCS_RENDERED = "docsRendered", events2.SHARED_STATE_CHANGED = "sharedStateChanged", events2.SHARED_STATE_SET = "sharedStateSet", events2.NAVIGATE_URL = "navigateUrl", events2.UPDATE_QUERY_PARAMS = "updateQueryParams", events2.REQUEST_WHATS_NEW_DATA = "requestWhatsNewData", events2.RESULT_WHATS_NEW_DATA = "resultWhatsNewData", events2.SET_WHATS_NEW_CACHE = "setWhatsNewCache", events2.TOGGLE_WHATS_NEW_NOTIFICATIONS = "toggleWhatsNewNotifications", events2.TELEMETRY_ERROR = "telemetryError", events2))(events || {}); var { CHANNEL_CREATED, CONFIG_ERROR, CURRENT_STORY_WAS_SET, DOCS_PREPARED, DOCS_RENDERED, FORCE_RE_RENDER, FORCE_REMOUNT, GLOBALS_UPDATED, NAVIGATE_URL, PLAY_FUNCTION_THREW_EXCEPTION, PRELOAD_ENTRIES, PREVIEW_BUILDER_PROGRESS, PREVIEW_KEYDOWN, REGISTER_SUBSCRIPTION, RESET_STORY_ARGS, SELECT_STORY, SET_CONFIG, SET_CURRENT_STORY, SET_GLOBALS, SET_INDEX, SET_STORIES, SHARED_STATE_CHANGED, SHARED_STATE_SET, STORIES_COLLAPSE_ALL, STORIES_EXPAND_ALL, STORY_ARGS_UPDATED, STORY_CHANGED, STORY_ERRORED, STORY_INDEX_INVALIDATED, STORY_MISSING, STORY_PREPARED, STORY_RENDER_PHASE_CHANGED, STORY_RENDERED, STORY_SPECIFIED, STORY_THREW_EXCEPTION, STORY_UNCHANGED, UPDATE_GLOBALS, UPDATE_QUERY_PARAMS, UPDATE_STORY_ARGS, REQUEST_WHATS_NEW_DATA, RESULT_WHATS_NEW_DATA, SET_WHATS_NEW_CACHE, TOGGLE_WHATS_NEW_NOTIFICATIONS, TELEMETRY_ERROR } = events; var IGNORED_EXCEPTION = new Error("ignoredException"); // src/panel/use-panel-machine.tsx var import_react = require("@xstate/react"); var import_react2 = require("react"); // src/events.ts var events_default = { START_ALL: "start all", START_ONE: "start one", FINISH_ALL: "finish all", FINISH_ONE: "finish one", PUBLISH_INTERACTIONS: "publish interactions" }; // src/util/bind-channel-events.ts function bind(channel, binding) { channel.on(binding.eventName, binding.fn); return function unbind() { channel.off(binding.eventName, binding.fn); }; } function bindAll(channel, bindings) { const unbinds = bindings.map((binding) => bind(channel, binding)); return function unbindAll() { unbinds.forEach((unbind) => unbind()); }; } // src/addon-constants.ts var packageName = "storybook-addon-performance"; // src/selectors.ts function prefix(selector) { return `${packageName}-${selector}`; } var startAllButtonId = prefix("start-all-button"); var panelId = prefix("panel"); var sampleSelectId = prefix("sample-select"); var copySelectId = prefix("copy-select"); var pinButtonId = prefix("pin-button"); var hiddenFileAnchorId = prefix("hidden-anchor"); var loadButtonId = prefix("load-button"); var saveButtonId = prefix("save-button"); // src/panel/file-system.ts function saveFile(storyName, current) { const anchor = document.getElementById(hiddenFileAnchorId); if (anchor) { anchor.setAttribute( "href", "data:text/json," + encodeURIComponent(JSON.stringify(current, null, 2)) ); anchor.setAttribute("download", `${storyName}.json`); anchor.click(); } } // src/panel/pinned-storage.ts function hasProperty(value, key) { return Object.prototype.hasOwnProperty.call(value, key); } function isValidContext(value) { if (typeof value !== "object") { return false; } if (value == null) { return false; } if (Array.isArray(value)) { return false; } const hasAllProperties = ["results", "samples", "copies"].every( (key) => hasProperty(value, key) ); if (!hasAllProperties) { return false; } const map = ( // @ts-ignore value && value.results && value.results[0] ? value.results[0].map : void 0 ); if (map == null) { return false; } const hasTaskId = Object.keys(map).some((key) => { const entry = map[key]; return hasProperty(entry, "taskId"); }); return hasTaskId ? false : true; } function getKey(storyName) { return `${packageName}-${storyName}`; } function savePinned(storyName, results) { localStorage.setItem(getKey(storyName), JSON.stringify(results)); } function clearPinned(storyName) { localStorage.removeItem(getKey(storyName)); } function getPinned(storyName) { const raw = localStorage.getItem(getKey(storyName)); if (!raw) { return null; } const value = JSON.parse(raw); if (!isValidContext(value)) { console.warn("Unsupported value found in localStorage. Value cleared"); clearPinned(storyName); return null; } return value; } // src/panel/use-panel-machine.tsx function mergeWithResults({ existing, result }) { return existing.map((groupResult) => { return { ...groupResult, map: { ...groupResult.map, [result.taskName]: result } }; }); } function usePanelMachine(machine, channel) { const [state, send, service] = (0, import_react.useMachine)(machine); (0, import_react2.useEffect)( function bindChannelEvents() { const unsubscribe = bindAll(channel, [ { eventName: STORY_RENDERED, fn: (storyName) => { service.send("LOADED", { storyName, pinned: getPinned(storyName) }); } }, { eventName: STORY_CHANGED, fn: () => service.send("WAIT") } ]); return unsubscribe; }, [service, channel] ); (0, import_react2.useEffect)(() => { function finishAll({ results }) { service.send("FINISH", { results }); } function finishOne({ result }) { const results = mergeWithResults({ // we are using a state machine guard to prevent this existing: service.state.context.current.results, result }); service.send("FINISH", { results }); } const unbindChannel = bindAll(channel, [ { eventName: events_default.FINISH_ALL, fn: finishAll }, { eventName: events_default.FINISH_ONE, fn: finishOne } ]); const unsubscribable = service.subscribe( // @ts-ignore: unknown second event argument in type. This is fixed in master function next(state2, event) { if (!state2.changed) { return; } if (!event) { return; } const { current, storyName } = state2.context; if (event.type === "SAVE") { saveFile(storyName, current); return; } if (event.type === "PIN") { savePinned(storyName, current); return; } if (event.type === "UNPIN") { clearPinned(storyName); return; } const { samples, copies } = current; if (state2.matches("active.running")) { if (event.type === "START_ALL") { channel.emit(events_default.START_ALL, { samples, copies }); return; } if (event.type === "START_ONE") { channel.emit(events_default.START_ONE, { taskName: event.taskName, samples, copies }); } } } ); return function unsubscribe() { unbindChannel(); unsubscribable.unsubscribe(); }; }, [service, channel]); return { state, send, service }; }