@unpunnyfuns/swatchbook-addon 0.58.0 → 0.58.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { i as preview_exports } from "./preview-
|
|
1
|
+
import { i as preview_exports } from "./preview-CL-T0T9_.mjs";
|
|
2
2
|
import { c as PARAM_KEY, h as VIRTUAL_MODULE_ID, m as TOOL_ID, n as AXES_GLOBAL_KEY, r as COLOR_FORMAT_GLOBAL_KEY, t as ADDON_ID } from "./constants-B31xFInv.mjs";
|
|
3
3
|
import { definePreviewAddon } from "storybook/internal/csf";
|
|
4
4
|
export * from "@unpunnyfuns/swatchbook-blocks";
|
|
@@ -171,20 +171,17 @@ function normalizeTuple(partial) {
|
|
|
171
171
|
* 3. `globals.swatchbookAxes` — toolbar-set tuple.
|
|
172
172
|
* 4. virtual module default.
|
|
173
173
|
*/
|
|
174
|
-
function resolveTuple(
|
|
175
|
-
const
|
|
176
|
-
const paramAxes = param?.axes;
|
|
174
|
+
function resolveTuple(axesGlobal, paramSwatchbook) {
|
|
175
|
+
const paramAxes = paramSwatchbook?.axes;
|
|
177
176
|
if (paramAxes) return normalizeTuple(paramAxes);
|
|
178
|
-
if (
|
|
179
|
-
const hit = tupleForName(
|
|
177
|
+
if (paramSwatchbook?.permutation) {
|
|
178
|
+
const hit = tupleForName(paramSwatchbook.permutation);
|
|
180
179
|
if (hit) return normalizeTuple(hit);
|
|
181
180
|
}
|
|
182
|
-
|
|
183
|
-
if (globalAxes && typeof globalAxes === "object") return normalizeTuple(globalAxes);
|
|
181
|
+
if (axesGlobal && typeof axesGlobal === "object") return normalizeTuple(axesGlobal);
|
|
184
182
|
return defaultTuple$1();
|
|
185
183
|
}
|
|
186
|
-
function resolveColorFormat(
|
|
187
|
-
const raw = globals[COLOR_FORMAT_GLOBAL_KEY];
|
|
184
|
+
function resolveColorFormat(raw) {
|
|
188
185
|
if (typeof raw === "string" && COLOR_FORMATS.includes(raw)) return raw;
|
|
189
186
|
return "hex";
|
|
190
187
|
}
|
|
@@ -200,8 +197,11 @@ const previewResolveAt = buildResolveAt(axes, cells, jointOverrides, defaultTupl
|
|
|
200
197
|
const themedDecorator = (Story, context) => {
|
|
201
198
|
const globals = context.globals;
|
|
202
199
|
const parameters = context.parameters;
|
|
203
|
-
const
|
|
204
|
-
const
|
|
200
|
+
const axesGlobal = globals[AXES_GLOBAL_KEY];
|
|
201
|
+
const colorFormatGlobal = globals[COLOR_FORMAT_GLOBAL_KEY];
|
|
202
|
+
const paramSwatchbook = parameters.swatchbook;
|
|
203
|
+
const tuple = useMemo(() => resolveTuple(axesGlobal, paramSwatchbook), [axesGlobal, paramSwatchbook]);
|
|
204
|
+
const colorFormat = useMemo(() => resolveColorFormat(colorFormatGlobal), [colorFormatGlobal]);
|
|
205
205
|
const themeName = useMemo(() => matchThemeName(tuple), [tuple]);
|
|
206
206
|
useEffect(() => {
|
|
207
207
|
ensureStylesheet(css, cssVarPrefix);
|
|
@@ -311,12 +311,12 @@ function installGlobalAxisApplier() {
|
|
|
311
311
|
channel.on(INIT_REQUEST_EVENT, broadcastInit);
|
|
312
312
|
const apply = (globals) => {
|
|
313
313
|
ensureStylesheet(css, cssVarPrefix);
|
|
314
|
-
setRootAxes(resolveTuple(globals,
|
|
314
|
+
setRootAxes(resolveTuple(globals[AXES_GLOBAL_KEY], void 0));
|
|
315
315
|
};
|
|
316
316
|
let lastApplied = "";
|
|
317
317
|
const onGlobals = (payload) => {
|
|
318
318
|
if (!payload.globals) return;
|
|
319
|
-
const fingerprint = matchThemeName(resolveTuple(payload.globals,
|
|
319
|
+
const fingerprint = matchThemeName(resolveTuple(payload.globals[AXES_GLOBAL_KEY], void 0));
|
|
320
320
|
if (fingerprint === lastApplied) return;
|
|
321
321
|
lastApplied = fingerprint;
|
|
322
322
|
apply(payload.globals);
|
|
@@ -350,4 +350,4 @@ if (import.meta.hot) import.meta.hot.on(HMR_EVENT, (payload) => {
|
|
|
350
350
|
//#endregion
|
|
351
351
|
export { preview_exports as i, globalTypes as n, initialGlobals as r, decorators as t };
|
|
352
352
|
|
|
353
|
-
//# sourceMappingURL=preview-
|
|
353
|
+
//# sourceMappingURL=preview-CL-T0T9_.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"preview-CL-T0T9_.mjs","names":["virtualDisabledAxes","virtualDefaultTuple","virtualAxes","virtualPresets","virtualCells","virtualJointOverrides","virtualVarianceByPath","defaultTuple","virtualListing"],"sources":["../src/preview.tsx"],"sourcesContent":["/// <reference types=\"vite/client\" />\nimport { buildResolveAt } from '@unpunnyfuns/swatchbook-core/resolve-at';\nimport type {\n Axis as CoreAxis,\n Cells as CoreCells,\n JointOverrides,\n} from '@unpunnyfuns/swatchbook-core';\nimport type { Decorator, Preview } from '@storybook/react-vite';\nimport { useEffect, useMemo } from 'react';\nimport { addons } from 'storybook/preview-api';\nimport { dataAttr } from '@unpunnyfuns/swatchbook-core/data-attr';\nimport { ensureStyleElement } from '@unpunnyfuns/swatchbook-core/style-element';\nimport { tupleToName } from '@unpunnyfuns/swatchbook-core/themes';\n// Side-effect import for integrations that opted into `autoInject`\n// (e.g. Tailwind's `@theme` block). When no integration opts in, the\n// virtual module body is empty — still a valid no-op.\nimport 'virtual:swatchbook/integration-side-effects';\nimport {\n axes as virtualAxes,\n cells as virtualCells,\n css,\n cssVarPrefix,\n defaultTuple as virtualDefaultTuple,\n diagnostics,\n disabledAxes as virtualDisabledAxes,\n jointOverrides as virtualJointOverrides,\n listing as virtualListing,\n presets as virtualPresets,\n varianceByPath as virtualVarianceByPath,\n} from 'virtual:swatchbook/tokens';\nimport {\n AxesContext,\n COLOR_FORMATS,\n ColorFormatContext,\n SwatchbookContext,\n ThemeContext,\n} from '@unpunnyfuns/swatchbook-blocks';\nimport type { ColorFormat, ProjectSnapshot } from '@unpunnyfuns/swatchbook-blocks';\nimport {\n AXES_GLOBAL_KEY,\n COLOR_FORMAT_GLOBAL_KEY,\n HMR_EVENT,\n INIT_EVENT,\n INIT_REQUEST_EVENT,\n PREVIEW_MOUSEDOWN_EVENT,\n STYLE_ELEMENT_ID,\n TOKENS_UPDATED_EVENT,\n} from '#/constants.ts';\nimport type { StoryParameters, SwatchbookGlobals } from '#/globals.ts';\n\n/**\n * The `html, body { ... }` rules that paint the iframe's own chrome\n * (outside any decorator wrapper — Docs mode, autodocs, empty gutters)\n * with the active theme's surface + text vars. Composed alongside the\n * emitted token CSS so both load through the same `<style>` element.\n */\nfunction iframeChromeRules(prefix: string): string {\n const surface = prefix ? `--${prefix}-color-surface-default` : '--color-surface-default';\n const text = prefix ? `--${prefix}-color-text-default` : '--color-text-default';\n return `\nhtml, body {\n background: var(${surface}, Canvas);\n color: var(${text}, CanvasText);\n margin: 0;\n}\n`;\n}\n\n/**\n * Inject the per-theme stylesheet plus the iframe-chrome block. Shared\n * with the HMR re-emit path below so a token refresh updates the\n * iframe's chrome rules from the same source.\n */\nfunction ensureStylesheet(cssText: string, prefix: string): void {\n ensureStyleElement(STYLE_ELEMENT_ID, `${cssText}\\n${iframeChromeRules(prefix)}`);\n}\n\n/**\n * Apply `cb(axisName, value)` for every pinned (disabled) axis whose\n * default-tuple value is set. `virtualDefaultTuple` carries the\n * post-filter axis defaults; disabled axes don't appear in\n * `virtualAxes` but their pinned context value still lives here, so\n * sampling it gives the same result the old \"first permutation's\n * input\" lookup did.\n */\nfunction forEachPinnedAxis(cb: (name: string, value: string) => void): void {\n for (const name of virtualDisabledAxes) {\n const value = virtualDefaultTuple[name];\n if (value !== undefined) cb(name, value);\n }\n}\n\n/**\n * Compose a stable theme name from a tuple — `axisValues.join(' · ')`\n * in axis order. Used for the `ThemeContext` value the blocks read and\n * the addon-channel signals downstream consumers subscribe to. Returns\n * empty string when there are no axes (no name to write).\n */\nfunction matchThemeName(tuple: Readonly<Record<string, string>>): string {\n if (virtualAxes.length === 0) return '';\n return tupleToName(virtualAxes, tuple);\n}\n\n/**\n * Write one `data-<prefix>-<axis>=<context>` per axis on `<html>`.\n * The smart CSS emitter targets these single-axis selectors (and\n * joint compounds across multiple) — that's the actual scoping\n * surface the cascade resolves through. Prefix follows `cssVarPrefix`\n * so attr namespace and emitted selectors stay in lockstep.\n */\nfunction setRootAxes(tuple: Readonly<Record<string, string>>): void {\n if (typeof document === 'undefined') return;\n const root = document.documentElement;\n for (const axis of virtualAxes) {\n const attr = dataAttr(cssVarPrefix, axis.name);\n const value = tuple[axis.name];\n if (value === undefined) {\n root.removeAttribute(attr);\n } else {\n root.setAttribute(attr, value);\n }\n }\n forEachPinnedAxis((name, value) => {\n root.setAttribute(dataAttr(cssVarPrefix, name), value);\n });\n}\n\n/**\n * Subset of an INIT_EVENT-shaped object the manager bundle needs. The 9\n * fields are the union of what the toolbar and panel read; named so\n * `broadcastInit` (module-level virtual exports) and the HMR re-emit\n * (`payload`-shaped) compose the same payload from the same shape.\n */\ninterface InitFieldsSource {\n axes: typeof virtualAxes;\n disabledAxes: typeof virtualDisabledAxes;\n presets: typeof virtualPresets;\n diagnostics: typeof diagnostics;\n cssVarPrefix: string;\n cells: typeof virtualCells;\n jointOverrides: typeof virtualJointOverrides;\n varianceByPath: typeof virtualVarianceByPath;\n defaultTuple: typeof virtualDefaultTuple;\n}\n\nfunction pickInitFields(source: InitFieldsSource): InitFieldsSource {\n return {\n axes: source.axes,\n disabledAxes: source.disabledAxes,\n presets: source.presets,\n diagnostics: source.diagnostics,\n cssVarPrefix: source.cssVarPrefix,\n cells: source.cells,\n jointOverrides: source.jointOverrides,\n varianceByPath: source.varianceByPath,\n defaultTuple: source.defaultTuple,\n };\n}\n\n/**\n * Emit the full virtual-module payload to the manager over Storybook's\n * channel so the toolbar + panel (which run in the manager bundle and\n * can't import our virtual module) can render from it.\n */\nfunction broadcastInit(): void {\n const channel = addons.getChannel();\n channel.emit(\n INIT_EVENT,\n pickInitFields({\n axes: virtualAxes,\n disabledAxes: virtualDisabledAxes,\n presets: virtualPresets,\n diagnostics,\n cssVarPrefix,\n cells: virtualCells,\n jointOverrides: virtualJointOverrides,\n varianceByPath: virtualVarianceByPath,\n defaultTuple: virtualDefaultTuple,\n }),\n );\n}\n\n/** Axis-default tuple, used as the baseline before overrides. */\nfunction defaultTuple(): Record<string, string> {\n const out: Record<string, string> = {};\n for (const axis of virtualAxes) out[axis.name] = axis.default;\n return out;\n}\n\n/**\n * Reverse-engineer a tuple from a `Light · Brand A · Normal`-shape\n * theme name. Splits on ` · ` and zips with `virtualAxes` in declared\n * order — matches `matchThemeName`'s production direction so a\n * round-trip is lossless. Returns `undefined` when the segment count\n * doesn't match the axis count.\n */\nfunction tupleForName(name: string): Record<string, string> | undefined {\n if (!name) return undefined;\n const parts = name.split(' · ');\n if (parts.length !== virtualAxes.length) return undefined;\n const out: Record<string, string> = {};\n for (let i = 0; i < virtualAxes.length; i++) {\n const axis = virtualAxes[i] as (typeof virtualAxes)[number];\n const value = parts[i];\n if (value === undefined) return undefined;\n out[axis.name] = value;\n }\n return out;\n}\n\n/**\n * Merge a partial tuple onto the axis defaults, dropping keys for axes that\n * don't exist and silently falling back to the default for contexts that\n * aren't listed on the axis.\n */\nfunction normalizeTuple(partial: Readonly<Record<string, string>>): Record<string, string> {\n const out = defaultTuple();\n for (const axis of virtualAxes) {\n const candidate = partial[axis.name];\n if (candidate !== undefined && axis.contexts.includes(candidate)) {\n out[axis.name] = candidate;\n }\n }\n return out;\n}\n\n/**\n * Resolve the active tuple from all input channels, in priority order:\n * 1. `parameters.swatchbook.axes` — per-story tuple.\n * 2. `parameters.swatchbook.permutation` — per-story composed name.\n * 3. `globals.swatchbookAxes` — toolbar-set tuple.\n * 4. virtual module default.\n */\nfunction resolveTuple(\n axesGlobal: SwatchbookGlobals[typeof AXES_GLOBAL_KEY],\n paramSwatchbook: StoryParameters['swatchbook'],\n): Record<string, string> {\n const paramAxes = paramSwatchbook?.axes;\n if (paramAxes) {\n return normalizeTuple(paramAxes);\n }\n if (paramSwatchbook?.permutation) {\n const hit = tupleForName(paramSwatchbook.permutation);\n if (hit) return normalizeTuple(hit);\n }\n if (axesGlobal && typeof axesGlobal === 'object') {\n return normalizeTuple(axesGlobal as Record<string, string>);\n }\n return defaultTuple();\n}\n\nfunction resolveColorFormat(raw: SwatchbookGlobals[typeof COLOR_FORMAT_GLOBAL_KEY]): ColorFormat {\n if (typeof raw === 'string' && (COLOR_FORMATS as readonly string[]).includes(raw)) {\n return raw as ColorFormat;\n }\n return 'hex';\n}\n\n/**\n * Single shared `resolveAt` instance for the lifetime of the preview\n * iframe. The inputs (`virtualAxes`, `virtualCells`, …) are all\n * module-level virtual-module exports with stable identity, so this\n * never needs to rebuild; downstream `ProjectSnapshot` consumers can\n * key memos on the snapshot wrapper without worrying about\n * `resolveAt` churning when Storybook recreates `context.globals`.\n */\nconst previewResolveAt = buildResolveAt(\n virtualAxes as readonly CoreAxis[],\n virtualCells as CoreCells,\n virtualJointOverrides as JointOverrides,\n virtualDefaultTuple,\n);\n\nconst themedDecorator: Decorator = (Story, context) => {\n const globals = context.globals as SwatchbookGlobals;\n const parameters = context.parameters as StoryParameters;\n const axesGlobal = globals[AXES_GLOBAL_KEY];\n const colorFormatGlobal = globals[COLOR_FORMAT_GLOBAL_KEY];\n const paramSwatchbook = parameters.swatchbook;\n const tuple = useMemo(\n () => resolveTuple(axesGlobal, paramSwatchbook),\n [axesGlobal, paramSwatchbook],\n );\n const colorFormat = useMemo(() => resolveColorFormat(colorFormatGlobal), [colorFormatGlobal]);\n const themeName = useMemo(() => matchThemeName(tuple), [tuple]);\n\n useEffect(() => {\n ensureStylesheet(css, cssVarPrefix);\n broadcastInit();\n }, []);\n\n useEffect(() => {\n setRootAxes(tuple);\n }, [tuple]);\n\n const wrapperAttrs: Record<string, string> = {};\n for (const axis of virtualAxes) {\n const value = tuple[axis.name];\n if (value !== undefined) wrapperAttrs[dataAttr(cssVarPrefix, axis.name)] = value;\n }\n forEachPinnedAxis((name, value) => {\n wrapperAttrs[dataAttr(cssVarPrefix, name)] = value;\n });\n\n const snapshot = useMemo<ProjectSnapshot>(\n () => ({\n axes: virtualAxes,\n disabledAxes: virtualDisabledAxes,\n presets: virtualPresets,\n activeTheme: themeName,\n activeAxes: tuple,\n cssVarPrefix,\n diagnostics,\n css,\n listing: virtualListing,\n cells: virtualCells,\n jointOverrides: virtualJointOverrides,\n varianceByPath: virtualVarianceByPath,\n defaultTuple: virtualDefaultTuple,\n resolveAt: previewResolveAt,\n }),\n [themeName, tuple],\n );\n\n return (\n <SwatchbookContext.Provider value={snapshot}>\n <ThemeContext.Provider value={themeName}>\n <AxesContext.Provider value={tuple}>\n <ColorFormatContext.Provider value={colorFormat}>\n <div\n {...wrapperAttrs}\n style={{\n padding: '1rem',\n minHeight: '100%',\n }}\n >\n <Story />\n </div>\n </ColorFormatContext.Provider>\n </AxesContext.Provider>\n </ThemeContext.Provider>\n </SwatchbookContext.Provider>\n );\n};\n\n/**\n * Named exports consumed by `definePreviewAddon(previewExports)` in the\n * addon's CSF Next factory (`src/index.ts`).\n */\nexport const decorators: NonNullable<Preview['decorators']> = [themedDecorator];\n\nexport const globalTypes: NonNullable<Preview['globalTypes']> = {\n [AXES_GLOBAL_KEY]: {\n name: 'Axes',\n description: 'Per-axis context selection — the active permutation tuple.',\n },\n [COLOR_FORMAT_GLOBAL_KEY]: {\n name: 'Color format',\n description: 'Display format for color tokens in blocks. Emitted CSS is unaffected.',\n },\n};\n\nfunction buildInitialAxes(): Record<string, string> {\n const out: Record<string, string> = {};\n for (const axis of virtualAxes) out[axis.name] = axis.default;\n return out;\n}\n\nexport const initialGlobals: NonNullable<Preview['initialGlobals']> = {\n [AXES_GLOBAL_KEY]: buildInitialAxes(),\n [COLOR_FORMAT_GLOBAL_KEY]: 'hex',\n};\n\n/**\n * Module-level channel subscription: writes the active tuple's attributes\n * onto `<html>` regardless of whether a story decorator is rendering.\n *\n * The {@link themedDecorator} already sets these inside story renders, but\n * it never runs on MDX docs pages that embed blocks without `<Story />`.\n * Without attrs on an ancestor, the per-tuple CSS selectors\n * (`[data-mode=\"Dark\"][data-brand=\"…\"]`) don't match and everything falls\n * back to the `:root` default tuple — so colors stay defaults even after\n * the toolbar switches axes. Subscribing globally fixes MDX docs at the\n * cost of one idempotent redundant write per story render.\n */\nfunction installGlobalAxisApplier(): void {\n if (typeof document === 'undefined') return;\n const channel = addons.getChannel();\n /**\n * Inject the stylesheet and emit the init payload once on module load so\n * the manager's toolbar populates and CSS vars are available even when no\n * story/decorator ever runs (bare MDX docs pages). Without these, the\n * toolbar sits in its disabled \"loading…\" state and nothing is styled.\n */\n ensureStylesheet(css, cssVarPrefix);\n broadcastInit();\n /**\n * If the manager subscribes to INIT_EVENT after our initial broadcast,\n * it misses the payload and the toolbar stays in its \"loading…\" state\n * until something else re-fires it. Honor an explicit request event so\n * a late-mounting manager can ask for the payload.\n */\n channel.on(INIT_REQUEST_EVENT, broadcastInit);\n const apply = (globals: SwatchbookGlobals): void => {\n ensureStylesheet(css, cssVarPrefix);\n const tuple = resolveTuple(globals[AXES_GLOBAL_KEY], undefined);\n setRootAxes(tuple);\n };\n // Storybook fires `globalsUpdated`, `setGlobals`, and `updateGlobals`\n // for the same logical change (preview init + every toolbar tick).\n // Subscribing to all three is intentional — `setGlobals` carries the\n // initial URL-persisted globals; `updateGlobals` is the toolbar\n // signal; `globalsUpdated` is the cross-frame echo. Apply the same\n // handler to all three but dedupe via a stringified-tuple guard so\n // downstream `setRootAxes` + `useSyncExternalStore` consumers\n // re-render at most once per real change instead of three times per\n // tick.\n let lastApplied = '';\n const onGlobals = (payload: { globals?: SwatchbookGlobals }): void => {\n if (!payload.globals) return;\n const tuple = resolveTuple(payload.globals[AXES_GLOBAL_KEY], undefined);\n const fingerprint = matchThemeName(tuple);\n if (fingerprint === lastApplied) return;\n lastApplied = fingerprint;\n apply(payload.globals);\n };\n channel.on('globalsUpdated', onGlobals);\n channel.on('setGlobals', onGlobals);\n channel.on('updateGlobals', onGlobals);\n}\n\ninstallGlobalAxisApplier();\n\n/**\n * Bridge `mousedown` inside the preview iframe to the manager via a\n * dedicated channel event. The toolbar popover's outside-click listener\n * runs on the manager's document, which can't observe mousedowns inside\n * the preview; without this bridge, clicking the canvas leaves the\n * popover open. Idempotent: fires at most once per real mousedown.\n */\nfunction installPreviewMouseDownBridge(): void {\n if (typeof document === 'undefined') return;\n const channel = addons.getChannel();\n document.addEventListener('mousedown', () => {\n channel.emit(PREVIEW_MOUSEDOWN_EVENT);\n });\n}\n\ninstallPreviewMouseDownBridge();\n\n/**\n * Wire the dev-time token-refresh HMR path. The plugin emits `HMR_EVENT`\n * with the fresh virtual-module payload whenever a watched source file\n * changes; we re-inject the stylesheet and forward to the Storybook\n * channel so the toolbar re-renders and blocks can re-subscribe with\n * the new snapshot — no full preview reload, so args / scroll / open\n * overlays survive the refresh. No-ops in production where\n * `import.meta.hot` is undefined.\n */\ninterface HmrSnapshot {\n axes: typeof virtualAxes;\n disabledAxes: typeof virtualDisabledAxes;\n presets: typeof virtualPresets;\n diagnostics: typeof diagnostics;\n css: string;\n cssVarPrefix: string;\n listing: typeof virtualListing;\n cells: typeof virtualCells;\n jointOverrides: typeof virtualJointOverrides;\n varianceByPath: typeof virtualVarianceByPath;\n defaultTuple: typeof virtualDefaultTuple;\n}\nif (import.meta.hot) {\n import.meta.hot.on(HMR_EVENT, (payload: HmrSnapshot) => {\n ensureStylesheet(payload.css, payload.cssVarPrefix);\n const channel = addons.getChannel();\n channel.emit(INIT_EVENT, pickInitFields(payload));\n channel.emit(TOKENS_UPDATED_EVENT, payload);\n });\n}\n"],"mappings":"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"}
|
package/dist/preview.mjs
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { n as globalTypes, r as initialGlobals, t as decorators } from "./preview-
|
|
1
|
+
import { n as globalTypes, r as initialGlobals, t as decorators } from "./preview-CL-T0T9_.mjs";
|
|
2
2
|
export { decorators, globalTypes, initialGlobals };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@unpunnyfuns/swatchbook-addon",
|
|
3
|
-
"version": "0.58.
|
|
3
|
+
"version": "0.58.1",
|
|
4
4
|
"description": "Storybook addon for DTCG design tokens — toolbar, panel, and useToken hook.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "unpunnyfuns <unpunnyfuns@gmail.com>",
|
|
@@ -75,9 +75,9 @@
|
|
|
75
75
|
"dependencies": {
|
|
76
76
|
"jiti": "^2.4.0",
|
|
77
77
|
"picomatch": "^4.0.4",
|
|
78
|
-
"@unpunnyfuns/swatchbook-blocks": "0.58.
|
|
79
|
-
"@unpunnyfuns/swatchbook-core": "0.58.
|
|
80
|
-
"@unpunnyfuns/swatchbook-switcher": "0.58.
|
|
78
|
+
"@unpunnyfuns/swatchbook-blocks": "0.58.1",
|
|
79
|
+
"@unpunnyfuns/swatchbook-core": "0.58.1",
|
|
80
|
+
"@unpunnyfuns/swatchbook-switcher": "0.58.1"
|
|
81
81
|
},
|
|
82
82
|
"peerDependencies": {
|
|
83
83
|
"@storybook/react-vite": "^10.3.5",
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"preview-NOHYIleu.mjs","names":["virtualDisabledAxes","virtualDefaultTuple","virtualAxes","virtualPresets","virtualCells","virtualJointOverrides","virtualVarianceByPath","defaultTuple","virtualListing"],"sources":["../src/preview.tsx"],"sourcesContent":["/// <reference types=\"vite/client\" />\nimport { buildResolveAt } from '@unpunnyfuns/swatchbook-core/resolve-at';\nimport type {\n Axis as CoreAxis,\n Cells as CoreCells,\n JointOverrides,\n} from '@unpunnyfuns/swatchbook-core';\nimport type { Decorator, Preview } from '@storybook/react-vite';\nimport { useEffect, useMemo } from 'react';\nimport { addons } from 'storybook/preview-api';\nimport { dataAttr } from '@unpunnyfuns/swatchbook-core/data-attr';\nimport { ensureStyleElement } from '@unpunnyfuns/swatchbook-core/style-element';\nimport { tupleToName } from '@unpunnyfuns/swatchbook-core/themes';\n// Side-effect import for integrations that opted into `autoInject`\n// (e.g. Tailwind's `@theme` block). When no integration opts in, the\n// virtual module body is empty — still a valid no-op.\nimport 'virtual:swatchbook/integration-side-effects';\nimport {\n axes as virtualAxes,\n cells as virtualCells,\n css,\n cssVarPrefix,\n defaultTuple as virtualDefaultTuple,\n diagnostics,\n disabledAxes as virtualDisabledAxes,\n jointOverrides as virtualJointOverrides,\n listing as virtualListing,\n presets as virtualPresets,\n varianceByPath as virtualVarianceByPath,\n} from 'virtual:swatchbook/tokens';\nimport {\n AxesContext,\n COLOR_FORMATS,\n ColorFormatContext,\n SwatchbookContext,\n ThemeContext,\n} from '@unpunnyfuns/swatchbook-blocks';\nimport type { ColorFormat, ProjectSnapshot } from '@unpunnyfuns/swatchbook-blocks';\nimport {\n AXES_GLOBAL_KEY,\n COLOR_FORMAT_GLOBAL_KEY,\n HMR_EVENT,\n INIT_EVENT,\n INIT_REQUEST_EVENT,\n PREVIEW_MOUSEDOWN_EVENT,\n STYLE_ELEMENT_ID,\n TOKENS_UPDATED_EVENT,\n} from '#/constants.ts';\nimport type { StoryParameters, SwatchbookGlobals } from '#/globals.ts';\n\n/**\n * The `html, body { ... }` rules that paint the iframe's own chrome\n * (outside any decorator wrapper — Docs mode, autodocs, empty gutters)\n * with the active theme's surface + text vars. Composed alongside the\n * emitted token CSS so both load through the same `<style>` element.\n */\nfunction iframeChromeRules(prefix: string): string {\n const surface = prefix ? `--${prefix}-color-surface-default` : '--color-surface-default';\n const text = prefix ? `--${prefix}-color-text-default` : '--color-text-default';\n return `\nhtml, body {\n background: var(${surface}, Canvas);\n color: var(${text}, CanvasText);\n margin: 0;\n}\n`;\n}\n\n/**\n * Inject the per-theme stylesheet plus the iframe-chrome block. Shared\n * with the HMR re-emit path below so a token refresh updates the\n * iframe's chrome rules from the same source.\n */\nfunction ensureStylesheet(cssText: string, prefix: string): void {\n ensureStyleElement(STYLE_ELEMENT_ID, `${cssText}\\n${iframeChromeRules(prefix)}`);\n}\n\n/**\n * Apply `cb(axisName, value)` for every pinned (disabled) axis whose\n * default-tuple value is set. `virtualDefaultTuple` carries the\n * post-filter axis defaults; disabled axes don't appear in\n * `virtualAxes` but their pinned context value still lives here, so\n * sampling it gives the same result the old \"first permutation's\n * input\" lookup did.\n */\nfunction forEachPinnedAxis(cb: (name: string, value: string) => void): void {\n for (const name of virtualDisabledAxes) {\n const value = virtualDefaultTuple[name];\n if (value !== undefined) cb(name, value);\n }\n}\n\n/**\n * Compose a stable theme name from a tuple — `axisValues.join(' · ')`\n * in axis order. Used for the `ThemeContext` value the blocks read and\n * the addon-channel signals downstream consumers subscribe to. Returns\n * empty string when there are no axes (no name to write).\n */\nfunction matchThemeName(tuple: Readonly<Record<string, string>>): string {\n if (virtualAxes.length === 0) return '';\n return tupleToName(virtualAxes, tuple);\n}\n\n/**\n * Write one `data-<prefix>-<axis>=<context>` per axis on `<html>`.\n * The smart CSS emitter targets these single-axis selectors (and\n * joint compounds across multiple) — that's the actual scoping\n * surface the cascade resolves through. Prefix follows `cssVarPrefix`\n * so attr namespace and emitted selectors stay in lockstep.\n */\nfunction setRootAxes(tuple: Readonly<Record<string, string>>): void {\n if (typeof document === 'undefined') return;\n const root = document.documentElement;\n for (const axis of virtualAxes) {\n const attr = dataAttr(cssVarPrefix, axis.name);\n const value = tuple[axis.name];\n if (value === undefined) {\n root.removeAttribute(attr);\n } else {\n root.setAttribute(attr, value);\n }\n }\n forEachPinnedAxis((name, value) => {\n root.setAttribute(dataAttr(cssVarPrefix, name), value);\n });\n}\n\n/**\n * Subset of an INIT_EVENT-shaped object the manager bundle needs. The 9\n * fields are the union of what the toolbar and panel read; named so\n * `broadcastInit` (module-level virtual exports) and the HMR re-emit\n * (`payload`-shaped) compose the same payload from the same shape.\n */\ninterface InitFieldsSource {\n axes: typeof virtualAxes;\n disabledAxes: typeof virtualDisabledAxes;\n presets: typeof virtualPresets;\n diagnostics: typeof diagnostics;\n cssVarPrefix: string;\n cells: typeof virtualCells;\n jointOverrides: typeof virtualJointOverrides;\n varianceByPath: typeof virtualVarianceByPath;\n defaultTuple: typeof virtualDefaultTuple;\n}\n\nfunction pickInitFields(source: InitFieldsSource): InitFieldsSource {\n return {\n axes: source.axes,\n disabledAxes: source.disabledAxes,\n presets: source.presets,\n diagnostics: source.diagnostics,\n cssVarPrefix: source.cssVarPrefix,\n cells: source.cells,\n jointOverrides: source.jointOverrides,\n varianceByPath: source.varianceByPath,\n defaultTuple: source.defaultTuple,\n };\n}\n\n/**\n * Emit the full virtual-module payload to the manager over Storybook's\n * channel so the toolbar + panel (which run in the manager bundle and\n * can't import our virtual module) can render from it.\n */\nfunction broadcastInit(): void {\n const channel = addons.getChannel();\n channel.emit(\n INIT_EVENT,\n pickInitFields({\n axes: virtualAxes,\n disabledAxes: virtualDisabledAxes,\n presets: virtualPresets,\n diagnostics,\n cssVarPrefix,\n cells: virtualCells,\n jointOverrides: virtualJointOverrides,\n varianceByPath: virtualVarianceByPath,\n defaultTuple: virtualDefaultTuple,\n }),\n );\n}\n\n/** Axis-default tuple, used as the baseline before overrides. */\nfunction defaultTuple(): Record<string, string> {\n const out: Record<string, string> = {};\n for (const axis of virtualAxes) out[axis.name] = axis.default;\n return out;\n}\n\n/**\n * Reverse-engineer a tuple from a `Light · Brand A · Normal`-shape\n * theme name. Splits on ` · ` and zips with `virtualAxes` in declared\n * order — matches `matchThemeName`'s production direction so a\n * round-trip is lossless. Returns `undefined` when the segment count\n * doesn't match the axis count.\n */\nfunction tupleForName(name: string): Record<string, string> | undefined {\n if (!name) return undefined;\n const parts = name.split(' · ');\n if (parts.length !== virtualAxes.length) return undefined;\n const out: Record<string, string> = {};\n for (let i = 0; i < virtualAxes.length; i++) {\n const axis = virtualAxes[i] as (typeof virtualAxes)[number];\n const value = parts[i];\n if (value === undefined) return undefined;\n out[axis.name] = value;\n }\n return out;\n}\n\n/**\n * Merge a partial tuple onto the axis defaults, dropping keys for axes that\n * don't exist and silently falling back to the default for contexts that\n * aren't listed on the axis.\n */\nfunction normalizeTuple(partial: Readonly<Record<string, string>>): Record<string, string> {\n const out = defaultTuple();\n for (const axis of virtualAxes) {\n const candidate = partial[axis.name];\n if (candidate !== undefined && axis.contexts.includes(candidate)) {\n out[axis.name] = candidate;\n }\n }\n return out;\n}\n\n/**\n * Resolve the active tuple from all input channels, in priority order:\n * 1. `parameters.swatchbook.axes` — per-story tuple.\n * 2. `parameters.swatchbook.permutation` — per-story composed name.\n * 3. `globals.swatchbookAxes` — toolbar-set tuple.\n * 4. virtual module default.\n */\nfunction resolveTuple(\n globals: SwatchbookGlobals,\n parameters: StoryParameters,\n): Record<string, string> {\n const param = parameters.swatchbook;\n const paramAxes = param?.axes;\n if (paramAxes) {\n return normalizeTuple(paramAxes);\n }\n if (param?.permutation) {\n const hit = tupleForName(param.permutation);\n if (hit) return normalizeTuple(hit);\n }\n const globalAxes = globals[AXES_GLOBAL_KEY];\n if (globalAxes && typeof globalAxes === 'object') {\n return normalizeTuple(globalAxes as Record<string, string>);\n }\n return defaultTuple();\n}\n\nfunction resolveColorFormat(globals: SwatchbookGlobals): ColorFormat {\n const raw = globals[COLOR_FORMAT_GLOBAL_KEY];\n if (typeof raw === 'string' && (COLOR_FORMATS as readonly string[]).includes(raw)) {\n return raw as ColorFormat;\n }\n return 'hex';\n}\n\n/**\n * Single shared `resolveAt` instance for the lifetime of the preview\n * iframe. The inputs (`virtualAxes`, `virtualCells`, …) are all\n * module-level virtual-module exports with stable identity, so this\n * never needs to rebuild; downstream `ProjectSnapshot` consumers can\n * key memos on the snapshot wrapper without worrying about\n * `resolveAt` churning when Storybook recreates `context.globals`.\n */\nconst previewResolveAt = buildResolveAt(\n virtualAxes as readonly CoreAxis[],\n virtualCells as CoreCells,\n virtualJointOverrides as JointOverrides,\n virtualDefaultTuple,\n);\n\nconst themedDecorator: Decorator = (Story, context) => {\n const globals = context.globals as SwatchbookGlobals;\n const parameters = context.parameters as StoryParameters;\n const tuple = useMemo(() => resolveTuple(globals, parameters), [globals, parameters]);\n const colorFormat = useMemo(() => resolveColorFormat(globals), [globals]);\n const themeName = useMemo(() => matchThemeName(tuple), [tuple]);\n\n useEffect(() => {\n ensureStylesheet(css, cssVarPrefix);\n broadcastInit();\n }, []);\n\n useEffect(() => {\n setRootAxes(tuple);\n }, [tuple]);\n\n const wrapperAttrs: Record<string, string> = {};\n for (const axis of virtualAxes) {\n const value = tuple[axis.name];\n if (value !== undefined) wrapperAttrs[dataAttr(cssVarPrefix, axis.name)] = value;\n }\n forEachPinnedAxis((name, value) => {\n wrapperAttrs[dataAttr(cssVarPrefix, name)] = value;\n });\n\n const snapshot = useMemo<ProjectSnapshot>(\n () => ({\n axes: virtualAxes,\n disabledAxes: virtualDisabledAxes,\n presets: virtualPresets,\n activeTheme: themeName,\n activeAxes: tuple,\n cssVarPrefix,\n diagnostics,\n css,\n listing: virtualListing,\n cells: virtualCells,\n jointOverrides: virtualJointOverrides,\n varianceByPath: virtualVarianceByPath,\n defaultTuple: virtualDefaultTuple,\n resolveAt: previewResolveAt,\n }),\n [themeName, tuple],\n );\n\n return (\n <SwatchbookContext.Provider value={snapshot}>\n <ThemeContext.Provider value={themeName}>\n <AxesContext.Provider value={tuple}>\n <ColorFormatContext.Provider value={colorFormat}>\n <div\n {...wrapperAttrs}\n style={{\n padding: '1rem',\n minHeight: '100%',\n }}\n >\n <Story />\n </div>\n </ColorFormatContext.Provider>\n </AxesContext.Provider>\n </ThemeContext.Provider>\n </SwatchbookContext.Provider>\n );\n};\n\n/**\n * Named exports consumed by `definePreviewAddon(previewExports)` in the\n * addon's CSF Next factory (`src/index.ts`).\n */\nexport const decorators: NonNullable<Preview['decorators']> = [themedDecorator];\n\nexport const globalTypes: NonNullable<Preview['globalTypes']> = {\n [AXES_GLOBAL_KEY]: {\n name: 'Axes',\n description: 'Per-axis context selection — the active permutation tuple.',\n },\n [COLOR_FORMAT_GLOBAL_KEY]: {\n name: 'Color format',\n description: 'Display format for color tokens in blocks. Emitted CSS is unaffected.',\n },\n};\n\nfunction buildInitialAxes(): Record<string, string> {\n const out: Record<string, string> = {};\n for (const axis of virtualAxes) out[axis.name] = axis.default;\n return out;\n}\n\nexport const initialGlobals: NonNullable<Preview['initialGlobals']> = {\n [AXES_GLOBAL_KEY]: buildInitialAxes(),\n [COLOR_FORMAT_GLOBAL_KEY]: 'hex',\n};\n\n/**\n * Module-level channel subscription: writes the active tuple's attributes\n * onto `<html>` regardless of whether a story decorator is rendering.\n *\n * The {@link themedDecorator} already sets these inside story renders, but\n * it never runs on MDX docs pages that embed blocks without `<Story />`.\n * Without attrs on an ancestor, the per-tuple CSS selectors\n * (`[data-mode=\"Dark\"][data-brand=\"…\"]`) don't match and everything falls\n * back to the `:root` default tuple — so colors stay defaults even after\n * the toolbar switches axes. Subscribing globally fixes MDX docs at the\n * cost of one idempotent redundant write per story render.\n */\nfunction installGlobalAxisApplier(): void {\n if (typeof document === 'undefined') return;\n const channel = addons.getChannel();\n /**\n * Inject the stylesheet and emit the init payload once on module load so\n * the manager's toolbar populates and CSS vars are available even when no\n * story/decorator ever runs (bare MDX docs pages). Without these, the\n * toolbar sits in its disabled \"loading…\" state and nothing is styled.\n */\n ensureStylesheet(css, cssVarPrefix);\n broadcastInit();\n /**\n * If the manager subscribes to INIT_EVENT after our initial broadcast,\n * it misses the payload and the toolbar stays in its \"loading…\" state\n * until something else re-fires it. Honor an explicit request event so\n * a late-mounting manager can ask for the payload.\n */\n channel.on(INIT_REQUEST_EVENT, broadcastInit);\n const apply = (globals: SwatchbookGlobals): void => {\n ensureStylesheet(css, cssVarPrefix);\n const tuple = resolveTuple(globals, {});\n setRootAxes(tuple);\n };\n // Storybook fires `globalsUpdated`, `setGlobals`, and `updateGlobals`\n // for the same logical change (preview init + every toolbar tick).\n // Subscribing to all three is intentional — `setGlobals` carries the\n // initial URL-persisted globals; `updateGlobals` is the toolbar\n // signal; `globalsUpdated` is the cross-frame echo. Apply the same\n // handler to all three but dedupe via a stringified-tuple guard so\n // downstream `setRootAxes` + `useSyncExternalStore` consumers\n // re-render at most once per real change instead of three times per\n // tick.\n let lastApplied = '';\n const onGlobals = (payload: { globals?: SwatchbookGlobals }): void => {\n if (!payload.globals) return;\n const tuple = resolveTuple(payload.globals, {});\n const fingerprint = matchThemeName(tuple);\n if (fingerprint === lastApplied) return;\n lastApplied = fingerprint;\n apply(payload.globals);\n };\n channel.on('globalsUpdated', onGlobals);\n channel.on('setGlobals', onGlobals);\n channel.on('updateGlobals', onGlobals);\n}\n\ninstallGlobalAxisApplier();\n\n/**\n * Bridge `mousedown` inside the preview iframe to the manager via a\n * dedicated channel event. The toolbar popover's outside-click listener\n * runs on the manager's document, which can't observe mousedowns inside\n * the preview; without this bridge, clicking the canvas leaves the\n * popover open. Idempotent: fires at most once per real mousedown.\n */\nfunction installPreviewMouseDownBridge(): void {\n if (typeof document === 'undefined') return;\n const channel = addons.getChannel();\n document.addEventListener('mousedown', () => {\n channel.emit(PREVIEW_MOUSEDOWN_EVENT);\n });\n}\n\ninstallPreviewMouseDownBridge();\n\n/**\n * Wire the dev-time token-refresh HMR path. The plugin emits `HMR_EVENT`\n * with the fresh virtual-module payload whenever a watched source file\n * changes; we re-inject the stylesheet and forward to the Storybook\n * channel so the toolbar re-renders and blocks can re-subscribe with\n * the new snapshot — no full preview reload, so args / scroll / open\n * overlays survive the refresh. No-ops in production where\n * `import.meta.hot` is undefined.\n */\ninterface HmrSnapshot {\n axes: typeof virtualAxes;\n disabledAxes: typeof virtualDisabledAxes;\n presets: typeof virtualPresets;\n diagnostics: typeof diagnostics;\n css: string;\n cssVarPrefix: string;\n listing: typeof virtualListing;\n cells: typeof virtualCells;\n jointOverrides: typeof virtualJointOverrides;\n varianceByPath: typeof virtualVarianceByPath;\n defaultTuple: typeof virtualDefaultTuple;\n}\nif (import.meta.hot) {\n import.meta.hot.on(HMR_EVENT, (payload: HmrSnapshot) => {\n ensureStylesheet(payload.css, payload.cssVarPrefix);\n const channel = addons.getChannel();\n channel.emit(INIT_EVENT, pickInitFields(payload));\n channel.emit(TOKENS_UPDATED_EVENT, payload);\n });\n}\n"],"mappings":"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"}
|