UNPKG

storybook-addon-grid

Version:
239 lines (231 loc) 6.92 kB
// src/manager.tsx import { addons, types } from "@storybook/manager-api"; // src/constants.ts var ADDON_ID = "storybook-addon-grid"; var PARAM_KEY = "grid"; // src/Tool.tsx import React3 from "react"; import { useAddonState as useAddonState2, useParameter as useParameter2, useStorybookApi } from "@storybook/manager-api"; import { IconButton } from "@storybook/components"; import { STORY_RENDERED } from "@storybook/core-events"; // src/Grids.tsx import React2 from "react"; import { createPortal } from "react-dom"; import { useAddonState, useParameter } from "@storybook/manager-api"; import { CacheProvider, createCache } from "@storybook/theming"; // src/ui.tsx import React from "react"; import { Global, styled } from "@storybook/theming"; import { Fragment, jsx, jsxs } from "react/jsx-runtime"; var MAX_COLUMNS = 24; var Wrapper = styled.div({ position: "relative", zIndex: 1, opacity: 0, pointerEvents: "none", '&[data-visible="true"]': { opacity: 1 } }); var Grid = styled.div( ({ gap, gutter, maxWidth, columns }) => { let gutterRight = "0", gutterLeft = "0"; if (Array.isArray(gutter)) { [gutterLeft, gutterRight] = gutter; } else if (gutter != null) { gutterLeft = gutterRight = gutter; } return { position: "fixed", inset: "0", display: "grid", gridTemplateColumns: `repeat(min(${columns}, ${MAX_COLUMNS}), 1fr)`, gridTemplateRows: "100%", gridColumnGap: gap, width: "100%", height: "100%", margin: "0 auto", maxWidth, padding: `0 ${gutterRight} 0 ${gutterLeft}`, boxSizing: "border-box" }; } ); var Column = styled.div(({ color }) => ({ width: "100%", height: "100%", backgroundColor: color })); function Grids({ visible, columns = 12, gap = "20px", color = "rgba(255, 0, 0, 0.1)", gutter = "50px", maxWidth = "1024px" }) { let columnDivs = React.useMemo( () => Array.from({ length: typeof columns === "number" ? columns : MAX_COLUMNS }).map((_, index) => /* @__PURE__ */ jsx(Column, { color }, index)), [columns, color] ); let gridNodes = /* @__PURE__ */ jsx(Grid, { gap, gutter, maxWidth, columns, children: columnDivs }); return /* @__PURE__ */ jsxs(Fragment, { children: [ /* @__PURE__ */ jsx(Global, { styles: { [`#root`]: { position: "relative", zIndex: 0 } } }), /* @__PURE__ */ jsx(Wrapper, { "data-addon-id": ADDON_ID, "data-visible": visible, children: gridNodes }) ] }); } // src/Grids.tsx import { Fragment as Fragment2, jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime"; function ManagerRenderedGrids() { let { columns, gap, color, gutter, maxWidth, disable } = useParameter(PARAM_KEY, {}); let [state] = useAddonState(ADDON_ID); return /* @__PURE__ */ jsx2(Grids, { columns, color, gap, visible: disable != null ? !disable : state?.visible ?? false, gutter, maxWidth }); } var styleCache = /* @__PURE__ */ new WeakMap(); var ManagerRenderedGridsContainer = React2.memo( function ManagerRenderedGridsContainer2() { let previewIframe = document.querySelector( "#storybook-preview-iframe" ); if (!previewIframe) return null; let iframeDocument = previewIframe.contentWindow?.document; if (!iframeDocument) return null; let head = iframeDocument.head; if (!head || !iframeDocument.body) return null; if (!styleCache.has(head)) styleCache.set( head, createCache({ key: ADDON_ID, container: head }) ); return createPortal( /* @__PURE__ */ jsx2(CacheProvider, { value: styleCache.get(head), children: /* @__PURE__ */ jsx2(ManagerRenderedGrids, {}) }), iframeDocument.body ); } ); // src/Tool.tsx import { jsx as jsx3, jsxs as jsxs3 } from "react/jsx-runtime"; var shortcut = ["control", "G"]; var Tool = React3.memo(ToolComponent); function ToolComponent() { let parameters = useParameter2(PARAM_KEY, {}); let [state, setState] = useAddonState2(ADDON_ID, { visible: false }); let [ready, setReady] = React3.useState(false); let api = useStorybookApi(); let toggleGrid = React3.useCallback(() => { setState( (prev) => ({ visible: !prev?.visible || false }) ); }, []); React3.useEffect(() => { api.setAddonShortcut(ADDON_ID, { label: "Toggle Column Guides", action: toggleGrid, actionName: "toggle-column-grid", defaultShortcut: shortcut, showInMenu: true }); }, [api, toggleGrid]); React3.useEffect(() => { let mounted = true; function handler() { mounted && setReady(true); } api.once(STORY_RENDERED, handler); return () => { mounted = false; }; }, [api]); let disabled = typeof parameters.disable === "boolean" ? parameters.disable : false; let isActive = disabled ? !disabled : state.visible; return /* @__PURE__ */ jsxs3(React3.Fragment, { children: [ /* @__PURE__ */ jsx3(IconButton, { title: "Toggle Column Guides", disabled, active: isActive, onClick: toggleGrid, children: /* @__PURE__ */ jsxs3("svg", { xmlns: "http://www.w3.org/2000/svg", viewBox: "0 0 24 24", width: "14", height: "14", fill: "none", stroke: "currentColor", strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: "2", children: [ /* @__PURE__ */ jsx3("path", { d: "M3 6.2c0-1.12 0-1.68.218-2.108a2 2 0 0 1 .874-.874C4.52 3 5.08 3 6.2 3h.6c1.12 0 1.68 0 2.108.218a2 2 0 0 1 .874.874C10 4.52 10 5.08 10 6.2v11.6c0 1.12 0 1.68-.218 2.108a2 2 0 0 1-.874.874C8.48 21 7.92 21 6.8 21h-.6c-1.12 0-1.68 0-2.108-.218a2 2 0 0 1-.874-.874C3 19.48 3 18.92 3 17.8V6.2Z" }), /* @__PURE__ */ jsx3("path", { d: "M14 6.2c0-1.12 0-1.68.218-2.108a2 2 0 0 1 .874-.874C15.52 3 16.08 3 17.2 3h.6c1.12 0 1.68 0 2.108.218a2 2 0 0 1 .874.874C21 4.52 21 5.08 21 6.2v11.6c0 1.12 0 1.68-.218 2.108a2 2 0 0 1-.874.874C19.48 21 18.92 21 17.8 21h-.6c-1.12 0-1.68 0-2.108-.218a2 2 0 0 1-.874-.874C14 19.48 14 18.92 14 17.8V6.2Z" }) ] }) }), ready && !disabled ? /* @__PURE__ */ jsx3(ManagerRenderedGridsContainer, {}) : null ] }, ADDON_ID); } // src/manager.tsx import { jsx as jsx4 } from "react/jsx-runtime"; addons.register(ADDON_ID, () => { addons.add(ADDON_ID, { type: types.TOOL, title: "Column Grid", paramKey: PARAM_KEY, match: ({ viewMode, tabId }) => !!(viewMode && viewMode.match(/^(story|docs)$/)) && !tabId, render() { return /* @__PURE__ */ jsx4(Tool, {}); } }); });