UNPKG

storybook

Version:

Storybook: Develop, document, and test UI components in isolation

1,359 lines (1,331 loc) • 85.2 kB
import { DEFAULT_BACKGROUNDS, PARAM_KEY as PARAM_KEY2, PARAM_KEY2 as PARAM_KEY3, PARAM_KEY3 as PARAM_KEY4 } from "../_browser-chunks/chunk-CADGRH3P.js"; import { composeConfigs, composeStory, mountDestructured, normalizeArrays, normalizeProjectAnnotations } from "../_browser-chunks/chunk-RW5PKMWM.js"; import "../_browser-chunks/chunk-LYCSRYYR.js"; import "../_browser-chunks/chunk-Y3M7TW6K.js"; import { combineParameters } from "../_browser-chunks/chunk-B4A3ADP3.js"; import "../_browser-chunks/chunk-ZNRFDIVA.js"; import { invariant } from "../_browser-chunks/chunk-FUOHXXZT.js"; import "../_browser-chunks/chunk-AB7OOPUX.js"; import "../_browser-chunks/chunk-F4Q6SGTB.js"; import "../_browser-chunks/chunk-UTNZYD2N.js"; import "../_browser-chunks/chunk-FSBVR7H5.js"; import "../_browser-chunks/chunk-NVV6MIOE.js"; import { dedent } from "../_browser-chunks/chunk-OPCDBBL3.js"; import { HIGHLIGHT, MAX_Z_INDEX, MIN_TOUCH_AREA_SIZE, REMOVE_HIGHLIGHT, RESET_HIGHLIGHT, SCROLL_INTO_VIEW } from "../_browser-chunks/chunk-GTKOCWCT.js"; import "../_browser-chunks/chunk-ECQ75MKQ.js"; import { action } from "../_browser-chunks/chunk-PB6FZ3WE.js"; import "../_browser-chunks/chunk-XW6KSYKF.js"; import { PARAM_KEY } from "../_browser-chunks/chunk-HHW4FUMO.js"; import { __commonJS, __export, __name, __toESM } from "../_browser-chunks/chunk-MM7DTO55.js"; // ../node_modules/@ngard/tiny-isequal/index.js var require_tiny_isequal = __commonJS({ "../node_modules/@ngard/tiny-isequal/index.js"(exports) { Object.defineProperty(exports, "__esModule", { value: true }), exports.isEqual = /* @__PURE__ */ function() { var e = Object.prototype.toString, r = Object.getPrototypeOf, t = Object.getOwnPropertySymbols ? function(e2) { return Object.keys(e2).concat(Object.getOwnPropertySymbols(e2)); } : Object.keys; return function(n, a) { return (/* @__PURE__ */ __name(function n2(a2, c, u) { var i, s, l, o = e.call(a2), f = e.call(c); if (a2 === c) return true; if (null == a2 || null == c) return false; if (u.indexOf(a2) > -1 && u.indexOf(c) > -1) return true; if (u.push(a2, c), o != f) return false; if (i = t(a2), s = t(c), i.length != s.length || i.some(function(e2) { return !n2(a2[e2], c[e2], u); })) return false; switch (o.slice(8, -1)) { case "Symbol": return a2.valueOf() == c.valueOf(); case "Date": case "Number": return +a2 == +c || +a2 != +a2 && +c != +c; case "RegExp": case "Function": case "String": case "Boolean": return "" + a2 == "" + c; case "Set": case "Map": i = a2.entries(), s = c.entries(); do { if (!n2((l = i.next()).value, s.next().value, u)) return false; } while (!l.done); return true; case "ArrayBuffer": a2 = new Uint8Array(a2), c = new Uint8Array(c); case "DataView": a2 = new Uint8Array(a2.buffer), c = new Uint8Array(c.buffer); case "Float32Array": case "Float64Array": case "Int8Array": case "Int16Array": case "Int32Array": case "Uint8Array": case "Uint16Array": case "Uint32Array": case "Uint8ClampedArray": case "Arguments": case "Array": if (a2.length != c.length) return false; for (l = 0; l < a2.length; l++) if ((l in a2 || l in c) && (l in a2 != l in c || !n2(a2[l], c[l], u))) return false; return true; case "Object": return n2(r(a2), r(c), u); default: return false; } }, "n"))(n, a, []); }; }(); } }); // src/csf/toStartCaseStr.ts function toStartCaseStr(str) { return str.replace(/_/g, " ").replace(/-/g, " ").replace(/\./g, " ").replace(/([^\n])([A-Z])([a-z])/g, (str2, $1, $2, $3) => `${$1} ${$2}${$3}`).replace(/([a-z])([A-Z])/g, (str2, $1, $2) => `${$1} ${$2}`).replace(/([a-z])([0-9])/gi, (str2, $1, $2) => `${$1} ${$2}`).replace(/([0-9])([a-z])/gi, (str2, $1, $2) => `${$1} ${$2}`).replace(/(\s|^)(\w)/g, (str2, $1, $2) => `${$1}${$2.toUpperCase()}`).replace(/ +/g, " ").trim(); } __name(toStartCaseStr, "toStartCaseStr"); // src/csf/includeConditionalArg.ts var import_tiny_isequal = __toESM(require_tiny_isequal(), 1); var count = /* @__PURE__ */ __name((vals) => vals.map((v) => typeof v !== "undefined").filter(Boolean).length, "count"); var testValue = /* @__PURE__ */ __name((cond, value) => { const { exists, eq, neq, truthy } = cond; if (count([exists, eq, neq, truthy]) > 1) { throw new Error(`Invalid conditional test ${JSON.stringify({ exists, eq, neq })}`); } if (typeof eq !== "undefined") { return (0, import_tiny_isequal.isEqual)(value, eq); } if (typeof neq !== "undefined") { return !(0, import_tiny_isequal.isEqual)(value, neq); } if (typeof exists !== "undefined") { const valueExists = typeof value !== "undefined"; return exists ? valueExists : !valueExists; } const shouldBeTruthy = typeof truthy === "undefined" ? true : truthy; return shouldBeTruthy ? !!value : !value; }, "testValue"); var includeConditionalArg = /* @__PURE__ */ __name((argType, args, globals) => { if (!argType.if) { return true; } const { arg, global: global5 } = argType.if; if (count([arg, global5]) !== 1) { throw new Error(`Invalid conditional value ${JSON.stringify({ arg, global: global5 })}`); } const value = arg ? args[arg] : globals[global5]; return testValue(argType.if, value); }, "includeConditionalArg"); // src/csf/csf-factories.ts import { combineTags } from "storybook/internal/csf"; // src/actions/preview.ts import { definePreviewAddon } from "storybook/internal/csf"; // src/actions/addArgs.ts var addArgs_exports = {}; __export(addArgs_exports, { argsEnhancers: () => argsEnhancers }); // src/actions/addArgsHelpers.ts var isInInitialArgs = /* @__PURE__ */ __name((name, initialArgs) => typeof initialArgs[name] === "undefined" && !(name in initialArgs), "isInInitialArgs"); var inferActionsFromArgTypesRegex = /* @__PURE__ */ __name((context) => { const { initialArgs, argTypes, id, parameters: { actions } } = context; if (!actions || actions.disable || !actions.argTypesRegex || !argTypes) { return {}; } const argTypesRegex = new RegExp(actions.argTypesRegex); const argTypesMatchingRegex = Object.entries(argTypes).filter( ([name]) => !!argTypesRegex.test(name) ); return argTypesMatchingRegex.reduce((acc, [name, argType]) => { if (isInInitialArgs(name, initialArgs)) { acc[name] = action(name, { implicit: true, id }); } return acc; }, {}); }, "inferActionsFromArgTypesRegex"); var addActionsFromArgTypes = /* @__PURE__ */ __name((context) => { const { initialArgs, argTypes, parameters: { actions } } = context; if (actions?.disable || !argTypes) { return {}; } const argTypesWithAction = Object.entries(argTypes).filter(([name, argType]) => !!argType.action); return argTypesWithAction.reduce((acc, [name, argType]) => { if (isInInitialArgs(name, initialArgs)) { acc[name] = action(typeof argType.action === "string" ? argType.action : name); } return acc; }, {}); }, "addActionsFromArgTypes"); // src/actions/addArgs.ts var argsEnhancers = [ addActionsFromArgTypes, inferActionsFromArgTypesRegex ]; // src/actions/loaders.ts var loaders_exports = {}; __export(loaders_exports, { loaders: () => loaders }); import { onMockCall } from "storybook/test"; var subscribed = false; var logActionsWhenMockCalled = /* @__PURE__ */ __name((context) => { const { parameters: parameters2 } = context; if (parameters2?.actions?.disable) { return; } if (!subscribed) { onMockCall((mock, args) => { const name = mock.getMockName(); if (name === "spy") { return; } if (name === "vi.fn()") { return; } if (!/^next\/.*::/.test(name) || [ "next/router::useRouter()", "next/navigation::useRouter()", "next/navigation::redirect", "next/cache::", "next/headers::cookies().set", "next/headers::cookies().delete", "next/headers::headers().set", "next/headers::headers().delete" ].some((prefix) => name.startsWith(prefix))) { action(name)(args); } }); subscribed = true; } }, "logActionsWhenMockCalled"); var loaders = [logActionsWhenMockCalled]; // src/actions/preview.ts var preview_default = /* @__PURE__ */ __name(() => definePreviewAddon({ ...addArgs_exports, ...loaders_exports }), "default"); // src/backgrounds/preview.ts import { definePreviewAddon as definePreviewAddon2 } from "storybook/internal/csf"; // src/backgrounds/decorator.ts import { useEffect } from "storybook/preview-api"; // src/backgrounds/utils.ts var { document: document2 } = globalThis; var isReduceMotionEnabled = /* @__PURE__ */ __name(() => { if (!globalThis?.matchMedia) { return false; } const prefersReduceMotion = globalThis.matchMedia("(prefers-reduced-motion: reduce)"); return !!prefersReduceMotion?.matches; }, "isReduceMotionEnabled"); var clearStyles = /* @__PURE__ */ __name((selector) => { const selectors = Array.isArray(selector) ? selector : [selector]; selectors.forEach(clearStyle); }, "clearStyles"); var clearStyle = /* @__PURE__ */ __name((selector) => { if (!document2) { return; } const element = document2.getElementById(selector); if (element && element.parentElement) { element.parentElement.removeChild(element); } }, "clearStyle"); var addGridStyle = /* @__PURE__ */ __name((selector, css) => { if (!document2) { return; } const existingStyle = document2.getElementById(selector); if (existingStyle) { if (existingStyle.innerHTML !== css) { existingStyle.innerHTML = css; } } else { const style = document2.createElement("style"); style.setAttribute("id", selector); style.innerHTML = css; document2.head.appendChild(style); } }, "addGridStyle"); var addBackgroundStyle = /* @__PURE__ */ __name((selector, css, storyId) => { if (!document2) { return; } const existingStyle = document2.getElementById(selector); if (existingStyle) { if (existingStyle.innerHTML !== css) { existingStyle.innerHTML = css; } } else { const style = document2.createElement("style"); style.setAttribute("id", selector); style.innerHTML = css; const gridStyleSelector = `addon-backgrounds-grid${storyId ? `-docs-${storyId}` : ""}`; const existingGridStyle = document2.getElementById(gridStyleSelector); if (existingGridStyle) { existingGridStyle.parentElement?.insertBefore(style, existingGridStyle); } else { document2.head.appendChild(style); } } }, "addBackgroundStyle"); // src/backgrounds/decorator.ts var defaultGrid = { cellSize: 100, cellAmount: 10, opacity: 0.8 }; var BG_SELECTOR_BASE = `addon-backgrounds`; var GRID_SELECTOR_BASE = "addon-backgrounds-grid"; var transitionStyle = isReduceMotionEnabled() ? "" : "transition: background-color 0.3s;"; var withBackgroundAndGrid = /* @__PURE__ */ __name((StoryFn, context) => { const { globals = {}, parameters: parameters2 = {}, viewMode, id } = context; const { options = DEFAULT_BACKGROUNDS, disable, grid = defaultGrid } = parameters2[PARAM_KEY2] || {}; const data = globals[PARAM_KEY2] || {}; const backgroundName = typeof data === "string" ? data : data?.value; const item = backgroundName ? options[backgroundName] : void 0; const value = typeof item === "string" ? item : item?.value || "transparent"; const showGrid = typeof data === "string" ? false : data.grid || false; const shownBackground = !!item && !disable; const backgroundSelector = viewMode === "docs" ? `#anchor--${id} .docs-story` : ".sb-show-main"; const gridSelector = viewMode === "docs" ? `#anchor--${id} .docs-story` : ".sb-show-main"; const isLayoutPadded = parameters2.layout === void 0 || parameters2.layout === "padded"; const defaultOffset = viewMode === "docs" ? 20 : isLayoutPadded ? 16 : 0; const { cellAmount, cellSize, opacity, offsetX = defaultOffset, offsetY = defaultOffset } = grid; const backgroundSelectorId = viewMode === "docs" ? `${BG_SELECTOR_BASE}-docs-${id}` : `${BG_SELECTOR_BASE}-color`; const backgroundTarget = viewMode === "docs" ? id : null; useEffect(() => { const backgroundStyles = ` ${backgroundSelector} { background: ${value} !important; ${transitionStyle} }`; if (!shownBackground) { clearStyles(backgroundSelectorId); return; } addBackgroundStyle(backgroundSelectorId, backgroundStyles, backgroundTarget); }, [backgroundSelector, backgroundSelectorId, backgroundTarget, shownBackground, value]); const gridSelectorId = viewMode === "docs" ? `${GRID_SELECTOR_BASE}-docs-${id}` : `${GRID_SELECTOR_BASE}`; useEffect(() => { if (!showGrid) { clearStyles(gridSelectorId); return; } const gridSize = [ `${cellSize * cellAmount}px ${cellSize * cellAmount}px`, `${cellSize * cellAmount}px ${cellSize * cellAmount}px`, `${cellSize}px ${cellSize}px`, `${cellSize}px ${cellSize}px` ].join(", "); const gridStyles = ` ${gridSelector} { background-size: ${gridSize} !important; background-position: ${offsetX}px ${offsetY}px, ${offsetX}px ${offsetY}px, ${offsetX}px ${offsetY}px, ${offsetX}px ${offsetY}px !important; background-blend-mode: difference !important; background-image: linear-gradient(rgba(130, 130, 130, ${opacity}) 1px, transparent 1px), linear-gradient(90deg, rgba(130, 130, 130, ${opacity}) 1px, transparent 1px), linear-gradient(rgba(130, 130, 130, ${opacity / 2}) 1px, transparent 1px), linear-gradient(90deg, rgba(130, 130, 130, ${opacity / 2}) 1px, transparent 1px) !important; } `; addGridStyle(gridSelectorId, gridStyles); }, [cellAmount, cellSize, gridSelector, gridSelectorId, showGrid, offsetX, offsetY, opacity]); return StoryFn(); }, "withBackgroundAndGrid"); // src/backgrounds/preview.ts var decorators = globalThis.FEATURES?.backgrounds ? [withBackgroundAndGrid] : []; var parameters = { [PARAM_KEY2]: { grid: { cellSize: 20, opacity: 0.5, cellAmount: 5 }, disable: false } }; var initialGlobals = { [PARAM_KEY2]: { value: void 0, grid: false } }; var preview_default2 = /* @__PURE__ */ __name(() => definePreviewAddon2({ decorators, parameters, initialGlobals }), "default"); // src/component-testing/preview.ts import { definePreviewAddon as definePreviewAddon3 } from "storybook/internal/csf"; import { instrument } from "storybook/internal/instrumenter"; var { step } = instrument( { // It seems like the label is unused, but the instrumenter has access to it // The context will be bounded later in StoryRender, so that the user can write just: // await step("label", (context) => { // // labeled step // }); step: /* @__PURE__ */ __name(async (label, play, context) => play(context), "step") }, { intercept: true } ); var preview_default3 = /* @__PURE__ */ __name(() => definePreviewAddon3({ parameters: { throwPlayFunctionExceptions: false }, runStep: step }), "default"); // src/highlight/preview.ts import { definePreviewAddon as definePreviewAddon4 } from "storybook/internal/csf"; import { addons } from "storybook/preview-api"; // src/highlight/useHighlights.ts import { STORY_RENDER_PHASE_CHANGED } from "storybook/internal/core-events"; // src/highlight/icons.ts var iconPaths = { chevronLeft: [ "M9.10355 10.1464C9.29882 10.3417 9.29882 10.6583 9.10355 10.8536C8.90829 11.0488 8.59171 11.0488 8.39645 10.8536L4.89645 7.35355C4.70118 7.15829 4.70118 6.84171 4.89645 6.64645L8.39645 3.14645C8.59171 2.95118 8.90829 2.95118 9.10355 3.14645C9.29882 3.34171 9.29882 3.65829 9.10355 3.85355L5.95711 7L9.10355 10.1464Z" ], chevronRight: [ "M4.89645 10.1464C4.70118 10.3417 4.70118 10.6583 4.89645 10.8536C5.09171 11.0488 5.40829 11.0488 5.60355 10.8536L9.10355 7.35355C9.29882 7.15829 9.29882 6.84171 9.10355 6.64645L5.60355 3.14645C5.40829 2.95118 5.09171 2.95118 4.89645 3.14645C4.70118 3.34171 4.70118 3.65829 4.89645 3.85355L8.04289 7L4.89645 10.1464Z" ], info: [ "M7 5.5a.5.5 0 01.5.5v4a.5.5 0 01-1 0V6a.5.5 0 01.5-.5zM7 4.5A.75.75 0 107 3a.75.75 0 000 1.5z", "M7 14A7 7 0 107 0a7 7 0 000 14zm0-1A6 6 0 107 1a6 6 0 000 12z" ], shareAlt: [ "M2 1.004a1 1 0 00-1 1v10a1 1 0 001 1h10a1 1 0 001-1v-4.5a.5.5 0 00-1 0v4.5H2v-10h4.5a.5.5 0 000-1H2z", "M7.354 7.357L12 2.711v1.793a.5.5 0 001 0v-3a.5.5 0 00-.5-.5h-3a.5.5 0 100 1h1.793L6.646 6.65a.5.5 0 10.708.707z" ] }; // src/highlight/utils.ts var svgElements = "svg,path,rect,circle,line,polyline,polygon,ellipse,text".split(","); var createElement = /* @__PURE__ */ __name((type, props = {}, children) => { const element = svgElements.includes(type) ? document.createElementNS("http://www.w3.org/2000/svg", type) : document.createElement(type); Object.entries(props).forEach(([key, val]) => { if (/[A-Z]/.test(key)) { if (key === "onClick") { element.addEventListener("click", val); element.addEventListener("keydown", (e) => { if (e.key === "Enter" || e.key === " ") { e.preventDefault(); val(); } }); } if (key === "onMouseEnter") { element.addEventListener("mouseenter", val); } if (key === "onMouseLeave") { element.addEventListener("mouseleave", val); } } else { element.setAttribute(key, val); } }); children?.forEach((child) => { if (child === null || child === void 0 || child === false) { return; } try { element.appendChild(child); } catch (e) { element.appendChild(document.createTextNode(String(child))); } }); return element; }, "createElement"); var createIcon = /* @__PURE__ */ __name((name) => iconPaths[name] && createElement( "svg", { width: "14", height: "14", viewBox: "0 0 14 14", xmlns: "http://www.w3.org/2000/svg" }, iconPaths[name].map( (d) => createElement("path", { fill: "currentColor", "fill-rule": "evenodd", "clip-rule": "evenodd", d }) ) ), "createIcon"); var normalizeOptions = /* @__PURE__ */ __name((options) => { if ("elements" in options) { const { elements, color, style } = options; return { id: void 0, priority: 0, selectors: elements, styles: { outline: `2px ${style} ${color}`, outlineOffset: "2px", boxShadow: "0 0 0 6px rgba(255,255,255,0.6)" }, menu: void 0 }; } const { menu, ...rest } = options; return { id: void 0, priority: 0, styles: { outline: "2px dashed #029cfd" }, ...rest, menu: Array.isArray(menu) ? menu.every(Array.isArray) ? menu : [menu] : void 0 }; }, "normalizeOptions"); var isFunction = /* @__PURE__ */ __name((obj) => obj instanceof Function, "isFunction"); var state = /* @__PURE__ */ new Map(); var listeners = /* @__PURE__ */ new Map(); var teardowns = /* @__PURE__ */ new Map(); var useStore = /* @__PURE__ */ __name((initialValue) => { const key = Symbol(); listeners.set(key, []); state.set(key, initialValue); const get = /* @__PURE__ */ __name(() => state.get(key), "get"); const set = /* @__PURE__ */ __name((update) => { const current = state.get(key); const next = isFunction(update) ? update(current) : update; if (next !== current) { state.set(key, next); listeners.get(key)?.forEach((listener) => { teardowns.get(listener)?.(); teardowns.set(listener, listener(next)); }); } }, "set"); const subscribe = /* @__PURE__ */ __name((listener) => { listeners.get(key)?.push(listener); return () => { const list = listeners.get(key); if (list) { listeners.set( key, list.filter((l) => l !== listener) ); } }; }, "subscribe"); const teardown = /* @__PURE__ */ __name(() => { listeners.get(key)?.forEach((listener) => { teardowns.get(listener)?.(); teardowns.delete(listener); }); listeners.delete(key); state.delete(key); }, "teardown"); return { get, set, subscribe, teardown }; }, "useStore"); var mapElements = /* @__PURE__ */ __name((highlights) => { const root = document.getElementById("storybook-root"); const map = /* @__PURE__ */ new Map(); for (const highlight of highlights) { const { priority = 0 } = highlight; for (const selector of highlight.selectors) { const elements = [ ...document.querySelectorAll( // Elements matching the selector, excluding storybook elements and their descendants. // Necessary to find portaled elements (e.g. children of `body`). `:is(${selector}):not([id^="storybook-"], [id^="storybook-"] *, [class^="sb-"], [class^="sb-"] *)` ), // Elements matching the selector inside the storybook root, as these were excluded above. ...root?.querySelectorAll(selector) || [] ]; for (const element of elements) { const existing = map.get(element); if (!existing || existing.priority <= priority) { map.set(element, { ...highlight, priority, selectors: Array.from(new Set((existing?.selectors || []).concat(selector))) }); } } } } return map; }, "mapElements"); var mapBoxes = /* @__PURE__ */ __name((elements) => Array.from(elements.entries()).map(([element, { selectors, styles, hoverStyles, focusStyles, menu }]) => { const { top, left, width, height } = element.getBoundingClientRect(); const { position } = getComputedStyle(element); return { element, selectors, styles, hoverStyles, focusStyles, menu, top: position === "fixed" ? top : top + window.scrollY, left: position === "fixed" ? left : left + window.scrollX, width, height }; }).sort((a, b) => b.width * b.height - a.width * a.height), "mapBoxes"); var isOverMenu = /* @__PURE__ */ __name((menuElement, coordinates) => { const menu = menuElement.getBoundingClientRect(); const { x, y } = coordinates; return menu?.top && menu?.left && x >= menu.left && x <= menu.left + menu.width && y >= menu.top && y <= menu.top + menu.height; }, "isOverMenu"); var isTargeted = /* @__PURE__ */ __name((box, boxElement, coordinates) => { if (!boxElement || !coordinates) { return false; } let { left, top, width, height } = box; if (height < MIN_TOUCH_AREA_SIZE) { top = top - Math.round((MIN_TOUCH_AREA_SIZE - height) / 2); height = MIN_TOUCH_AREA_SIZE; } if (width < MIN_TOUCH_AREA_SIZE) { left = left - Math.round((MIN_TOUCH_AREA_SIZE - width) / 2); width = MIN_TOUCH_AREA_SIZE; } if (boxElement.style.position === "fixed") { left += window.scrollX; top += window.scrollY; } const { x, y } = coordinates; return x >= left && x <= left + width && y >= top && y <= top + height; }, "isTargeted"); var keepInViewport = /* @__PURE__ */ __name((element, targetCoordinates, options = {}) => { const { x, y } = targetCoordinates; const { margin = 5, topOffset = 0, centered = false } = options; const { scrollX, scrollY, innerHeight: windowHeight, innerWidth: windowWidth } = window; const top = Math.min( element.style.position === "fixed" ? y - scrollY : y, windowHeight - element.clientHeight - margin - topOffset + scrollY ); const leftOffset = centered ? element.clientWidth / 2 : 0; const left = element.style.position === "fixed" ? Math.max(Math.min(x - scrollX, windowWidth - leftOffset - margin), leftOffset + margin) : Math.max( Math.min(x, windowWidth - leftOffset - margin + scrollX), leftOffset + margin + scrollX ); Object.assign(element.style, { ...left !== x && { left: `${left}px` }, ...top !== y && { top: `${top}px` } }); }, "keepInViewport"); var showPopover = /* @__PURE__ */ __name((element) => { if (window.HTMLElement.prototype.hasOwnProperty("showPopover")) { element.showPopover(); } }, "showPopover"); var hidePopover = /* @__PURE__ */ __name((element) => { if (window.HTMLElement.prototype.hasOwnProperty("showPopover")) { element.hidePopover(); } }, "hidePopover"); var getEventDetails = /* @__PURE__ */ __name((target) => ({ top: target.top, left: target.left, width: target.width, height: target.height, selectors: target.selectors, element: { attributes: Object.fromEntries( Array.from(target.element.attributes).map((attr) => [attr.name, attr.value]) ), localName: target.element.localName, tagName: target.element.tagName, outerHTML: target.element.outerHTML } }), "getEventDetails"); // src/highlight/useHighlights.ts var menuId = "storybook-highlights-menu"; var rootId = "storybook-highlights-root"; var storybookRootId = "storybook-root"; var useHighlights = /* @__PURE__ */ __name((channel) => { if (globalThis.__STORYBOOK_HIGHLIGHT_INITIALIZED) { return; } globalThis.__STORYBOOK_HIGHLIGHT_INITIALIZED = true; const { document: document3 } = globalThis; const highlights = useStore([]); const elements = useStore(/* @__PURE__ */ new Map()); const boxes = useStore([]); const clickCoords = useStore(); const hoverCoords = useStore(); const targets = useStore([]); const hovered = useStore([]); const focused = useStore(); const selected = useStore(); let root = document3.getElementById(rootId); highlights.subscribe(() => { if (!root) { root = createElement("div", { id: rootId }); document3.body.appendChild(root); } }); highlights.subscribe((value) => { const storybookRoot = document3.getElementById(storybookRootId); if (!storybookRoot) { return; } elements.set(mapElements(value)); const observer = new MutationObserver(() => elements.set(mapElements(value))); observer.observe(storybookRoot, { subtree: true, childList: true }); return () => { observer.disconnect(); }; }); elements.subscribe((value) => { const updateBoxes = /* @__PURE__ */ __name(() => requestAnimationFrame(() => boxes.set(mapBoxes(value))), "updateBoxes"); const observer = new ResizeObserver(updateBoxes); observer.observe(document3.body); Array.from(value.keys()).forEach((element) => observer.observe(element)); const scrollers = Array.from(document3.body.querySelectorAll("*")).filter((el) => { const { overflow, overflowX, overflowY } = window.getComputedStyle(el); return ["auto", "scroll"].some((o) => [overflow, overflowX, overflowY].includes(o)); }); scrollers.forEach((element) => element.addEventListener("scroll", updateBoxes)); return () => { observer.disconnect(); scrollers.forEach((element) => element.removeEventListener("scroll", updateBoxes)); }; }); elements.subscribe((value) => { const sticky = Array.from(value.keys()).filter(({ style }) => style.position === "sticky"); const updateBoxes = /* @__PURE__ */ __name(() => requestAnimationFrame(() => { boxes.set( (current) => current.map((box) => { if (sticky.includes(box.element)) { const { top, left } = box.element.getBoundingClientRect(); return { ...box, top: top + window.scrollY, left: left + window.scrollX }; } return box; }) ); }), "updateBoxes"); document3.addEventListener("scroll", updateBoxes); return () => document3.removeEventListener("scroll", updateBoxes); }); elements.subscribe((value) => { targets.set((t) => t.filter(({ element }) => value.has(element))); }); targets.subscribe((value) => { if (value.length) { selected.set((s) => value.some((t) => t.element === s?.element) ? s : void 0); focused.set((s) => value.some((t) => t.element === s?.element) ? s : void 0); } else { selected.set(void 0); focused.set(void 0); clickCoords.set(void 0); } }); const styleElementByHighlight = new Map(/* @__PURE__ */ new Map()); highlights.subscribe((value) => { value.forEach(({ keyframes }) => { if (keyframes) { let style = styleElementByHighlight.get(keyframes); if (!style) { style = document3.createElement("style"); style.setAttribute("data-highlight", "keyframes"); styleElementByHighlight.set(keyframes, style); document3.head.appendChild(style); } style.innerHTML = keyframes; } }); styleElementByHighlight.forEach((style, keyframes) => { if (!value.some((v) => v.keyframes === keyframes)) { style.remove(); styleElementByHighlight.delete(keyframes); } }); }); const boxElementByTargetElement = new Map(/* @__PURE__ */ new Map()); boxes.subscribe((value) => { value.forEach((box) => { let boxElement = boxElementByTargetElement.get(box.element); if (root && !boxElement) { const props = { popover: "manual", "data-highlight-dimensions": `w${box.width.toFixed(0)}h${box.height.toFixed(0)}`, "data-highlight-coordinates": `x${box.left.toFixed(0)}y${box.top.toFixed(0)}` }; boxElement = root.appendChild( createElement("div", props, [createElement("div")]) ); boxElementByTargetElement.set(box.element, boxElement); } }); boxElementByTargetElement.forEach((box, element) => { if (!value.some(({ element: e }) => e === element)) { box.remove(); boxElementByTargetElement.delete(element); } }); }); boxes.subscribe((value) => { const targetable = value.filter((box) => box.menu); if (!targetable.length) { return; } const onClick = /* @__PURE__ */ __name((event) => { requestAnimationFrame(() => { const menu = document3.getElementById(menuId); const coords = { x: event.pageX, y: event.pageY }; if (menu && !isOverMenu(menu, coords)) { const results = targetable.filter((box) => { const boxElement = boxElementByTargetElement.get(box.element); return isTargeted(box, boxElement, coords); }); clickCoords.set(results.length ? coords : void 0); targets.set(results); } }); }, "onClick"); document3.addEventListener("click", onClick); return () => document3.removeEventListener("click", onClick); }); const updateHovered = /* @__PURE__ */ __name(() => { const menu = document3.getElementById(menuId); const coords = hoverCoords.get(); if (!coords || menu && isOverMenu(menu, coords)) { return; } hovered.set((current) => { const update = boxes.get().filter((box) => { const boxElement = boxElementByTargetElement.get(box.element); return isTargeted(box, boxElement, coords); }); const existing = current.filter((box) => update.includes(box)); const additions = update.filter((box) => !current.includes(box)); const hasRemovals = current.length - existing.length; return additions.length || hasRemovals ? [...existing, ...additions] : current; }); }, "updateHovered"); hoverCoords.subscribe(updateHovered); boxes.subscribe(updateHovered); const updateBoxStyles = /* @__PURE__ */ __name(() => { const selectedElement = selected.get(); const targetElements = selectedElement ? [selectedElement] : targets.get(); const focusedElement = targetElements.length === 1 ? targetElements[0] : focused.get(); const isMenuOpen = clickCoords.get() !== void 0; boxes.get().forEach((box) => { const boxElement = boxElementByTargetElement.get(box.element); if (boxElement) { const isFocused = focusedElement === box; const isHovered = isMenuOpen ? focusedElement ? isFocused : targetElements.includes(box) : hovered.get()?.includes(box); Object.assign(boxElement.style, { animation: "none", background: "transparent", border: "none", boxSizing: "border-box", outline: "none", outlineOffset: "0px", ...box.styles, ...isHovered ? box.hoverStyles : {}, ...isFocused ? box.focusStyles : {}, position: getComputedStyle(box.element).position === "fixed" ? "fixed" : "absolute", zIndex: MAX_Z_INDEX - 10, top: `${box.top}px`, left: `${box.left}px`, width: `${box.width}px`, height: `${box.height}px`, margin: 0, padding: 0, cursor: box.menu && isHovered ? "pointer" : "default", pointerEvents: box.menu ? "auto" : "none", display: "flex", alignItems: "center", justifyContent: "center", overflow: "visible" }); Object.assign(boxElement.children[0].style, { width: "100%", height: "100%", minHeight: `${MIN_TOUCH_AREA_SIZE}px`, minWidth: `${MIN_TOUCH_AREA_SIZE}px`, boxSizing: "content-box", padding: boxElement.style.outlineWidth || "0px" }); showPopover(boxElement); } }); }, "updateBoxStyles"); boxes.subscribe(updateBoxStyles); targets.subscribe(updateBoxStyles); hovered.subscribe(updateBoxStyles); focused.subscribe(updateBoxStyles); selected.subscribe(updateBoxStyles); const renderMenu = /* @__PURE__ */ __name(() => { if (!root) { return; } let menu = document3.getElementById(menuId); if (menu) { menu.innerHTML = ""; } else { const props = { id: menuId, popover: "manual" }; menu = root.appendChild(createElement("div", props)); root.appendChild( createElement("style", {}, [ ` #${menuId} { position: absolute; z-index: ${MAX_Z_INDEX}; width: 300px; padding: 0px; margin: 15px 0 0 0; transform: translateX(-50%); font-family: "Nunito Sans", -apple-system, ".SFNSText-Regular", "San Francisco", BlinkMacSystemFont, "Segoe UI", "Helvetica Neue", Helvetica, Arial, sans-serif; font-size: 12px; background: white; border: none; border-radius: 6px; box-shadow: 0 2px 5px 0 rgba(0, 0, 0, 0.05), 0 5px 15px 0 rgba(0, 0, 0, 0.1); color: #2E3438; } #${menuId} ul { list-style: none; margin: 0; padding: 0; } #${menuId} > ul { max-height: 300px; overflow-y: auto; padding: 4px 0; } #${menuId} li { padding: 0 4px; margin: 0; } #${menuId} li > :not(ul) { display: flex; padding: 8px; margin: 0; align-items: center; gap: 8px; border-radius: 4px; } #${menuId} button { width: 100%; border: 0; background: transparent; color: inherit; text-align: left; font-family: inherit; font-size: inherit; } #${menuId} button:focus-visible { outline-color: #029CFD; } #${menuId} button:hover { background: rgba(2, 156, 253, 0.07); color: #029CFD; cursor: pointer; } #${menuId} li code { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; line-height: 16px; font-size: 11px; } #${menuId} li svg { flex-shrink: 0; margin: 1px; color: #73828C; } #${menuId} li > button:hover svg, #${menuId} li > button:focus-visible svg { color: #029CFD; } #${menuId} .element-list li svg { display: none; } #${menuId} li.selectable svg, #${menuId} li.selected svg { display: block; } #${menuId} .menu-list { border-top: 1px solid rgba(38, 85, 115, 0.15); } #${menuId} .menu-list > li:not(:last-child) { padding-bottom: 4px; margin-bottom: 4px; border-bottom: 1px solid rgba(38, 85, 115, 0.15); } #${menuId} .menu-items, #${menuId} .menu-items li { padding: 0; } #${menuId} .menu-item { display: flex; } #${menuId} .menu-item-content { display: flex; flex-direction: column; flex-grow: 1; } ` ]) ); } const selectedElement = selected.get(); const elementList = selectedElement ? [selectedElement] : targets.get(); if (elementList.length) { menu.style.position = getComputedStyle(elementList[0].element).position === "fixed" ? "fixed" : "absolute"; menu.appendChild( createElement( "ul", { class: "element-list" }, elementList.map((target) => { const selectable = elementList.length > 1 && !!target.menu?.some( (group) => group.some( (item) => !item.selectors || item.selectors.some((s) => target.selectors.includes(s)) ) ); const props = selectable ? { class: "selectable", onClick: /* @__PURE__ */ __name(() => selected.set(target), "onClick"), onMouseEnter: /* @__PURE__ */ __name(() => focused.set(target), "onMouseEnter"), onMouseLeave: /* @__PURE__ */ __name(() => focused.set(void 0), "onMouseLeave") } : selectedElement ? { class: "selected", onClick: /* @__PURE__ */ __name(() => selected.set(void 0), "onClick") } : {}; const asButton = selectable || selectedElement; return createElement("li", props, [ createElement(asButton ? "button" : "div", asButton ? { type: "button" } : {}, [ selectedElement ? createIcon("chevronLeft") : null, createElement("code", {}, [target.element.outerHTML]), selectable ? createIcon("chevronRight") : null ]) ]); }) ) ); } if (selected.get() || targets.get().length === 1) { const target = selected.get() || targets.get()[0]; const menuGroups = target.menu?.filter( (group) => group.some( (item) => !item.selectors || item.selectors.some((s) => target.selectors.includes(s)) ) ); if (menuGroups?.length) { menu.appendChild( createElement( "ul", { class: "menu-list" }, menuGroups.map( (menuItems) => createElement("li", {}, [ createElement( "ul", { class: "menu-items" }, menuItems.map( ({ id, title, description, iconLeft, iconRight, clickEvent: event }) => { const onClick = event && (() => channel.emit(event, id, getEventDetails(target))); return createElement("li", {}, [ createElement( onClick ? "button" : "div", onClick ? { class: "menu-item", type: "button", onClick } : { class: "menu-item" }, [ iconLeft ? createIcon(iconLeft) : null, createElement("div", { class: "menu-item-content" }, [ createElement(description ? "strong" : "span", {}, [title]), description && createElement("span", {}, [description]) ]), iconRight ? createIcon(iconRight) : null ] ) ]); } ) ) ]) ) ) ); } } const coords = clickCoords.get(); if (coords) { Object.assign(menu.style, { display: "block", left: `${menu.style.position === "fixed" ? coords.x - window.scrollX : coords.x}px`, top: `${menu.style.position === "fixed" ? coords.y - window.scrollY : coords.y}px` }); showPopover(menu); requestAnimationFrame(() => keepInViewport(menu, coords, { topOffset: 15, centered: true })); } else { hidePopover(menu); Object.assign(menu.style, { display: "none" }); } }, "renderMenu"); targets.subscribe(renderMenu); selected.subscribe(renderMenu); const addHighlight = /* @__PURE__ */ __name((highlight) => { const info = normalizeOptions(highlight); highlights.set((value) => { const others = info.id ? value.filter((h) => h.id !== info.id) : value; return info.selectors?.length ? [...others, info] : others; }); }, "addHighlight"); const removeHighlight = /* @__PURE__ */ __name((id) => { if (id) { highlights.set((value) => value.filter((h) => h.id !== id)); } }, "removeHighlight"); const resetState = /* @__PURE__ */ __name(() => { highlights.set([]); elements.set(/* @__PURE__ */ new Map()); boxes.set([]); clickCoords.set(void 0); hoverCoords.set(void 0); targets.set([]); hovered.set([]); focused.set(void 0); selected.set(void 0); }, "resetState"); let removeTimeout; const scrollIntoView = /* @__PURE__ */ __name((target, options) => { const id = "scrollIntoView-highlight"; clearTimeout(removeTimeout); removeHighlight(id); const element = document3.querySelector(target); if (!element) { console.warn(`Cannot scroll into view: ${target} not found`); return; } element.scrollIntoView({ behavior: "smooth", block: "center", ...options }); const keyframeName = `kf-${Math.random().toString(36).substring(2, 15)}`; highlights.set((value) => [ ...value, { id, priority: 1e3, selectors: [target], styles: { outline: "2px solid #1EA7FD", outlineOffset: "-1px", animation: `${keyframeName} 3s linear forwards` }, keyframes: `@keyframes ${keyframeName} { 0% { outline: 2px solid #1EA7FD; } 20% { outline: 2px solid #1EA7FD00; } 40% { outline: 2px solid #1EA7FD; } 60% { outline: 2px solid #1EA7FD00; } 80% { outline: 2px solid #1EA7FD; } 100% { outline: 2px solid #1EA7FD00; } }` } ]); removeTimeout = setTimeout(() => removeHighlight(id), 3500); }, "scrollIntoView"); const onMouseMove = /* @__PURE__ */ __name((event) => { requestAnimationFrame(() => hoverCoords.set({ x: event.pageX, y: event.pageY })); }, "onMouseMove"); document3.body.addEventListener("mousemove", onMouseMove); channel.on(HIGHLIGHT, addHighlight); channel.on(REMOVE_HIGHLIGHT, removeHighlight); channel.on(RESET_HIGHLIGHT, resetState); channel.on(SCROLL_INTO_VIEW, scrollIntoView); channel.on(STORY_RENDER_PHASE_CHANGED, ({ newPhase }) => { if (newPhase === "loading") { resetState(); } }); }, "useHighlights"); // src/highlight/preview.ts if (globalThis?.FEATURES?.highlight && addons?.ready) { addons.ready().then(useHighlights); } var preview_default4 = /* @__PURE__ */ __name(() => definePreviewAddon4({}), "default"); // src/measure/preview.ts import { definePreviewAddon as definePreviewAddon5 } from "storybook/internal/csf"; // src/measure/withMeasure.ts import { useEffect as useEffect2 } from "storybook/preview-api"; // src/measure/box-model/canvas.ts import { global } from "@storybook/global"; function getDocumentWidthAndHeight() { const container = global.document.documentElement; const height = Math.max(container.scrollHeight, container.offsetHeight); const width = Math.max(container.scrollWidth, container.offsetWidth); return { width, height }; } __name(getDocumentWidthAndHeight, "getDocumentWidthAndHeight"); function createCanvas() { const canvas = global.document.createElement("canvas"); canvas.id = "storybook-addon-measure"; const context = canvas.getContext("2d"); invariant(context != null); const { width, height } = getDocumentWidthAndHeight(); setCanvasWidthAndHeight(canvas, context, { width, height }); canvas.style.position = "absolute"; canvas.style.left = "0"; canvas.style.top = "0"; canvas.style.zIndex = "2147483647"; canvas.style.pointerEvents = "none"; global.document.body.appendChild(canvas); return { canvas, context, width, height }; } __name(createCanvas, "createCanvas"); function setCanvasWidthAndHeight(canvas, context, { width, height }) { canvas.style.width = `${width}px`; canvas.style.height = `${height}px`; const scale = global.window.devicePixelRatio; canvas.width = Math.floor(width * scale); canvas.height = Math.floor(height * scale); context.scale(scale, scale); } __name(setCanvasWidthAndHeight, "setCanvasWidthAndHeight"); var state2 = {}; function init() { if (!state2.canvas) { state2 = createCanvas(); } } __name(init, "init"); function clear() { if (state2.context) { state2.context.clearRect(0, 0, state2.width ?? 0, state2.height ?? 0); } } __name(clear, "clear"); function draw(callback) { clear(); callback(state2.context); } __name(draw, "draw"); function rescale() { invariant(state2.canvas, "Canvas should exist in the state."); invariant(state2.context, "Context should exist in the state."); setCanvasWidthAndHeight(state2.canvas, state2.context, { width: 0, height: 0 }); const { width, height } = getDocumentWidthAndHeight(); setCanvasWidthAndHeight(state2.canvas, state2.context, { width, height }); state2.width = width; state2.height = height; } __name(rescale, "rescale"); function destroy() { if (state2.canvas) { clear(); state2.canvas.parentNode?.removeChild(state2.canvas); state2 = {}; } } __name(destroy, "destroy"); // src/measure/box-model/visualizer.ts import { global as global2 } from "@storybook/global"; // src/measure/box-model/labels.ts var colors = { margin: "#f6b26b", border: "#ffe599", padding: "#93c47d", content: "#6fa8dc", text: "#232020" }; var labelPadding = 6; function roundedRect(context, { x, y, w, h, r }) { x = x - w / 2; y = y - h / 2; if (w < 2 * r) { r = w / 2; } if (h < 2 * r) { r = h / 2; } context.beginPath(); context.moveTo(x + r, y); context.arcTo(x + w, y, x + w, y + h, r); context.arcTo(x + w, y + h, x, y + h, r); context.arcTo(x, y + h, x, y, r); context.arcTo(x, y, x + w, y, r); context.closePath(); } __name(roundedRect, "roundedRect"); function positionCoordinate(position, { padding, border, width, height, top, left }) { const contentWidth = width - border.left - border.right - padding.left - padding.right; const contentHeight = height - padding.top - padding.bottom - border.top - border.bottom; let x = left + border.left + padding.left; let y = top + border.top + padding.top; if (position === "top") { x += contentWidth / 2; } else if (position === "right") { x += contentWidth; y += contentHeight / 2; } else if (position === "bottom") { x += contentWidth / 2; y += contentHeight; } else if (position === "left") { y += contentHeight / 2; } else if (position === "center") { x += contentWidth / 2; y += contentHeight / 2; } return { x, y }; } __name(positionCoordinate, "positionCoordinate"); function offset(type, position, { margin, border, padding }, labelPaddingSize, external) { let shift = /* @__PURE__ */ __name((dir) => 0, "shift"); let offsetX = 0; let offsetY = 0; const locationMultiplier = external ? 1 : 0.5; const labelPaddingShift = external ? labelPaddingSize * 2 : 0; if (type === "padding") { shift = /* @__PURE__ */ __name((dir) => padding[dir] * locationMultiplier + labelPaddingShift, "shift"); } else if (type === "border") { shift = /* @__PURE__ */ __name((dir) => padding[dir] + border[dir] * locationMultiplier + labelPaddingShift, "shift"); } else if (type === "margin") { shift = /* @__PURE__ */ __name((dir) => padding[dir] + border[dir] + margin[dir] * locationMultiplier + labelPaddingShift, "shift"); } if (position === "top") { offsetY = -shift("top"); } else if (position === "right") { offsetX = shift("right"); } else if (position === "bottom") { offsetY = shift("bottom"); } else if (position === "left") { offsetX = -shift("left"); } return { offsetX, offsetY }; } __name(offset, "offset"); function collide(a, b) { return Math.abs(a.x - b.x) < Math.abs(a.w + b.w) / 2 && Math.abs(a.y - b.y) < Math.abs(a.h + b.h) / 2; } __name(collide, "collide"); function overlapAdjustment(position, currentRect, prevRect) { if (position === "top") { currentRect.y = prevRect.y - prevRect.h - labelPadding; } else if (position === "right") { currentRect.x = prevRect.x + prevRect.w / 2 + labelPadding + currentRect.w / 2; } else if (position === "bottom") {