storybook-addon-vis 2.0.4 → 2.0.5

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/manager.js CHANGED
@@ -1,2 +1,2 @@
1
- import {memo,useState,useEffect}from'react';import {addons,types}from'storybook/internal/manager-api';import {RefreshIcon}from'@storybook/icons';import {AddonPanel,ScrollArea,IconButton,Placeholder}from'storybook/internal/components';import {styled}from'storybook/internal/theming';import {SNAPSHOT_ROOT_DIR}from'vitest-plugin-vis/client-api';import {jsx,jsxs,Fragment}from'react/jsx-runtime';var h=memo(function({active:s,snapshotResults:r=[],onRefresh:S}){let a=r.reduce((n,e)=>{let R=`(${e.snapshotRootDir.slice(SNAPSHOT_ROOT_DIR.length+1)}) ${e.fileName}`;return n[R]=[...n[R]??[],e],n},{});return jsx(AddonPanel,{active:s,children:r.length>0?jsx(ScrollArea,{vertical:true,children:Object.entries(a).map(([n,e])=>jsx("div",{children:e.some(i=>i.type==="diff")?jsxs(Fragment,{children:[jsx(g,{failed:true,children:n}),e.map(i=>jsx("img",{src:`data:image/png;base64,${i.base64}`,alt:i.fileName},i.filePath))]}):jsxs(Fragment,{children:[jsxs(g,{children:[jsx("span",{children:n}),jsx(IconButton,{onClick:()=>S(),children:jsx(RefreshIcon,{})})]}),jsx("img",{src:`data:image/png;base64,${e[0].base64}`,alt:e[0].fileName},e[0].filePath)]})},n))}):jsx(Placeholder,{children:"There is no snapshots for this story"})})}),g=styled.div(({theme:t,failed:s})=>({display:"flex",alignItems:"center",gap:"0.5rem",paddingBlock:"0.5rem",paddingInline:"0.2rem",backgroundColor:s?t.background.negative:t.background.positive,color:t.barTextColor}));var p="storybook-addon-vis",E=`${p}/vis_panel`;var O="IMAGE_SNAPSHOT_RESULTS_REQUEST",d="IMAGE_SNAPSHOT_RESULTS_RESPONSE";function l({name:t,importPath:s}){return {type:O,name:t,importPath:s}}addons.register(p,t=>{addons.add(E,{type:types.PANEL,title:"Vis",match:({tabId:s,viewMode:r})=>!s&&r==="story",render({active:s}){if(!s)return null;let[r,S]=useState([]),a=t.getCurrentStoryData();return useEffect(()=>{let n=[t.on(p,e=>{e.name===a.name&&e.importPath===a.importPath&&e.type===d&&S(e.results);})];return t.emit(p,l(a)),()=>n.forEach(e=>e())},[a]),jsx(h,{active:s,snapshotResults:r,onRefresh:()=>{t.emit(p,l(a));}})}});});//# sourceMappingURL=manager.js.map
1
+ import {memo,useState,useEffect}from'react';import {addons,types}from'storybook/internal/manager-api';import {RefreshIcon}from'@storybook/icons';import {AddonPanel,ScrollArea,IconButton,Placeholder}from'storybook/internal/components';import {styled}from'storybook/internal/theming';import {SNAPSHOT_ROOT_DIR}from'vitest-plugin-vis/client-api';import {jsx,jsxs,Fragment}from'react/jsx-runtime';var E=memo(function({active:s,snapshotResults:r=[],onRefresh:S}){let n=r.reduce((a,e)=>{let R=`(${e.snapshotRootDir.slice(SNAPSHOT_ROOT_DIR.length+1)}) ${e.fileName}`;return a[R]=[...a[R]??[],e],a},{});return jsx(AddonPanel,{active:s,children:r.length>0?jsx(ScrollArea,{vertical:true,children:Object.entries(n).map(([a,e])=>jsx("div",{children:e.some(i=>i.type==="diff")?jsxs(Fragment,{children:[jsx(g,{failed:true,children:a}),e.map(i=>jsx("img",{src:`data:image/png;base64,${i.base64}`,alt:i.fileName},i.filePath))]}):jsxs(Fragment,{children:[jsxs(g,{children:[jsx("span",{children:a}),jsx(IconButton,{onClick:()=>S(),children:jsx(RefreshIcon,{})})]}),jsx("img",{src:`data:image/png;base64,${e[0].base64}`,alt:e[0].fileName},e[0].filePath)]})},a))}):jsx(Placeholder,{children:"There is no snapshots for this story"})})}),g=styled.div(({theme:t,failed:s})=>({display:"flex",alignItems:"center",gap:"0.5rem",paddingBlock:"0.5rem",paddingInline:"0.2rem",backgroundColor:s?t.background.negative:t.background.positive,color:t.barTextColor}));var p="storybook-addon-vis",h=`${p}/vis_panel`;var O="IMAGE_SNAPSHOT_RESULTS_REQUEST",d="IMAGE_SNAPSHOT_RESULTS_RESPONSE";function l({name:t,importPath:s}){return {type:O,name:t,importPath:s}}addons.register(p,t=>{globalThis.CONFIG_TYPE==="DEVELOPMENT"&&addons.add(h,{type:types.PANEL,title:"Vis",match:({tabId:s,viewMode:r})=>!s&&r==="story",render({active:s}){if(!s)return null;let[r,S]=useState([]),n=t.getCurrentStoryData();return useEffect(()=>{let a=[t.on(p,e=>{e.name===n.name&&e.importPath===n.importPath&&e.type===d&&S(e.results);})];return t.emit(p,l(n)),()=>a.forEach(e=>e())},[n]),jsx(E,{active:s,snapshotResults:r,onRefresh:()=>{t.emit(p,l(n));}})}});});//# sourceMappingURL=manager.js.map
2
2
  //# sourceMappingURL=manager.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/components/vis_panel.tsx","../src/shared/contants.ts","../src/shared/events.ts","../src/manager.tsx"],"names":["VisPanel","memo","active","snapshotResults","onRefresh","groupedResults","acc","result","key","SNAPSHOT_ROOT_DIR","jsx","AddonPanel","ScrollArea","results","jsxs","Fragment","SnapshotRow","IconButton","RefreshIcon","Placeholder","styled","theme","failed","NAME","VIS_PANEL_ID","IMAGE_SNAPSHOT_RESULTS_REQUEST","IMAGE_SNAPSHOT_RESULTS_RESPONSE","requestImageSnapshotResults","name","importPath","addons","api","types","tabId","viewMode","setSnapshotResults","useState","storyData","useEffect","disposes","event","dispose"],"mappings":"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","file":"manager.js","sourcesContent":["import { RefreshIcon } from '@storybook/icons'\nimport { memo } from 'react'\nimport { AddonPanel, IconButton, Placeholder, ScrollArea } from 'storybook/internal/components'\nimport { styled } from 'storybook/internal/theming'\nimport { SNAPSHOT_ROOT_DIR } from 'vitest-plugin-vis/client-api'\nimport type { ImageSnapshotResults } from '../shared/events.ts'\n\ninterface PanelProps {\n\tactive: boolean\n\tsnapshotResults: ImageSnapshotResults[]\n\tonRefresh: () => void\n}\n\nexport const VisPanel = memo(function VisPanel({ active, snapshotResults = [], onRefresh }: PanelProps) {\n\tconst groupedResults = snapshotResults.reduce(\n\t\t(acc, result) => {\n\t\t\tconst suiteName = result.snapshotRootDir.slice(SNAPSHOT_ROOT_DIR.length + 1)\n\t\t\tconst key = `(${suiteName}) ${result.fileName}`\n\t\t\tacc[key] = [...(acc[key] ?? []), result]\n\t\t\treturn acc\n\t\t},\n\t\t{} as Record<string, ImageSnapshotResults[]>,\n\t)\n\treturn (\n\t\t<AddonPanel active={active}>\n\t\t\t{snapshotResults.length > 0 ? (\n\t\t\t\t<ScrollArea vertical>\n\t\t\t\t\t{Object.entries(groupedResults).map(([key, results]) => (\n\t\t\t\t\t\t<div key={key}>\n\t\t\t\t\t\t\t{results.some((result) => result.type === 'diff') ? (\n\t\t\t\t\t\t\t\t<>\n\t\t\t\t\t\t\t\t\t<SnapshotRow failed>{key}</SnapshotRow>\n\t\t\t\t\t\t\t\t\t{results.map((result) => (\n\t\t\t\t\t\t\t\t\t\t<img key={result.filePath} src={`data:image/png;base64,${result.base64}`} alt={result.fileName} />\n\t\t\t\t\t\t\t\t\t))}\n\t\t\t\t\t\t\t\t</>\n\t\t\t\t\t\t\t) : (\n\t\t\t\t\t\t\t\t<>\n\t\t\t\t\t\t\t\t\t<SnapshotRow>\n\t\t\t\t\t\t\t\t\t\t<span>{key}</span>\n\t\t\t\t\t\t\t\t\t\t<IconButton onClick={() => onRefresh()}>\n\t\t\t\t\t\t\t\t\t\t\t<RefreshIcon />\n\t\t\t\t\t\t\t\t\t\t</IconButton>\n\t\t\t\t\t\t\t\t\t</SnapshotRow>\n\t\t\t\t\t\t\t\t\t<img\n\t\t\t\t\t\t\t\t\t\tkey={results[0].filePath}\n\t\t\t\t\t\t\t\t\t\tsrc={`data:image/png;base64,${results[0].base64}`}\n\t\t\t\t\t\t\t\t\t\talt={results[0].fileName}\n\t\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t\t</>\n\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t</div>\n\t\t\t\t\t))}\n\t\t\t\t</ScrollArea>\n\t\t\t) : (\n\t\t\t\t<Placeholder>There is no snapshots for this story</Placeholder>\n\t\t\t)}\n\t\t</AddonPanel>\n\t)\n})\n\nconst SnapshotRow = styled.div<{ failed?: boolean }>(({ theme, failed }) => ({\n\tdisplay: 'flex',\n\talignItems: 'center',\n\tgap: '0.5rem',\n\tpaddingBlock: '0.5rem',\n\tpaddingInline: '0.2rem',\n\tbackgroundColor: failed ? theme.background.negative : theme.background.positive,\n\tcolor: theme.barTextColor,\n}))\n","export const NAME = 'storybook-addon-vis'\nexport const VIS_PANEL_ID = `${NAME}/vis_panel`\n","export type VisEvent = ImageSnapshotResultsRequest | ImageSnapshotResultsResponse\n\nexport const IMAGE_SNAPSHOT_RESULTS_REQUEST = 'IMAGE_SNAPSHOT_RESULTS_REQUEST'\nexport const IMAGE_SNAPSHOT_RESULTS_RESPONSE = 'IMAGE_SNAPSHOT_RESULTS_RESPONSE'\n\nexport function requestImageSnapshotResults({ name, importPath }: { name: string; importPath: string }) {\n\treturn {\n\t\ttype: IMAGE_SNAPSHOT_RESULTS_REQUEST,\n\t\tname,\n\t\timportPath,\n\t}\n}\n\nexport type ImageSnapshotResultsRequest = {\n\ttype: typeof IMAGE_SNAPSHOT_RESULTS_REQUEST\n\tname: string\n\timportPath: string\n}\n\nexport type ImageSnapshotResultsResponse = {\n\ttype: typeof IMAGE_SNAPSHOT_RESULTS_RESPONSE\n\tname: string\n\timportPath: string\n\tresults: ImageSnapshotResults[]\n}\n\nexport type ImageSnapshotResults = {\n\tfilePath: string\n\tfileName: string\n\tsnapshotRootDir: string\n\ttype: 'baseline' | 'diff' | 'result'\n\tbase64: string\n}\n","import { useEffect, useState } from 'react'\nimport { addons, types } from 'storybook/internal/manager-api'\nimport { VisPanel } from './components/vis_panel.tsx'\nimport { NAME, VIS_PANEL_ID } from './shared/contants.ts'\nimport {\n\tIMAGE_SNAPSHOT_RESULTS_RESPONSE,\n\trequestImageSnapshotResults,\n\ttype ImageSnapshotResults,\n\ttype VisEvent,\n} from './shared/events.ts'\n\n// Register the addon\naddons.register(NAME, (api) => {\n\t// Register the tool\n\taddons.add(VIS_PANEL_ID, {\n\t\ttype: types.PANEL,\n\t\ttitle: 'Vis',\n\t\tmatch: ({ tabId, viewMode }) => !tabId && viewMode === 'story',\n\t\trender({ active }) {\n\t\t\tif (!active) return null\n\t\t\tconst [snapshotResults, setSnapshotResults] = useState<ImageSnapshotResults[]>([])\n\n\t\t\tconst storyData = api.getCurrentStoryData()\n\n\t\t\tuseEffect(() => {\n\t\t\t\tconst disposes = [\n\t\t\t\t\tapi.on(NAME, (event: VisEvent) => {\n\t\t\t\t\t\tif (event.name !== storyData.name) return\n\t\t\t\t\t\tif (event.importPath !== storyData.importPath) return\n\n\t\t\t\t\t\tif (event.type === IMAGE_SNAPSHOT_RESULTS_RESPONSE) {\n\t\t\t\t\t\t\tsetSnapshotResults(event.results)\n\t\t\t\t\t\t}\n\t\t\t\t\t}),\n\t\t\t\t\t// api.on('UNIVERSAL_STORE:storybook/test', (event) => {\n\t\t\t\t\t// \tconsole.log('storybook/test', event)\n\t\t\t\t\t// }),\n\t\t\t\t]\n\t\t\t\tapi.emit(NAME, requestImageSnapshotResults(storyData))\n\t\t\t\treturn () => disposes.forEach((dispose) => dispose())\n\t\t\t}, [storyData])\n\t\t\treturn (\n\t\t\t\t<VisPanel\n\t\t\t\t\tactive={active}\n\t\t\t\t\tsnapshotResults={snapshotResults}\n\t\t\t\t\tonRefresh={() => {\n\t\t\t\t\t\tapi.emit(NAME, requestImageSnapshotResults(storyData))\n\t\t\t\t\t}}\n\t\t\t\t/>\n\t\t\t)\n\t\t},\n\t})\n})\n"]}
1
+ {"version":3,"sources":["../src/components/vis_panel.tsx","../src/shared/contants.ts","../src/shared/events.ts","../src/manager.tsx"],"names":["VisPanel","memo","active","snapshotResults","onRefresh","groupedResults","acc","result","key","SNAPSHOT_ROOT_DIR","jsx","AddonPanel","ScrollArea","results","jsxs","Fragment","SnapshotRow","IconButton","RefreshIcon","Placeholder","styled","theme","failed","NAME","VIS_PANEL_ID","IMAGE_SNAPSHOT_RESULTS_REQUEST","IMAGE_SNAPSHOT_RESULTS_RESPONSE","requestImageSnapshotResults","name","importPath","addons","api","types","tabId","viewMode","setSnapshotResults","useState","storyData","useEffect","disposes","event","dispose"],"mappings":"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","file":"manager.js","sourcesContent":["import { RefreshIcon } from '@storybook/icons'\nimport { memo } from 'react'\nimport { AddonPanel, IconButton, Placeholder, ScrollArea } from 'storybook/internal/components'\nimport { styled } from 'storybook/internal/theming'\nimport { SNAPSHOT_ROOT_DIR } from 'vitest-plugin-vis/client-api'\nimport type { ImageSnapshotResults } from '../shared/events.ts'\n\ninterface PanelProps {\n\tactive: boolean\n\tsnapshotResults: ImageSnapshotResults[]\n\tonRefresh: () => void\n}\n\nexport const VisPanel = memo(function VisPanel({ active, snapshotResults = [], onRefresh }: PanelProps) {\n\tconst groupedResults = snapshotResults.reduce(\n\t\t(acc, result) => {\n\t\t\tconst suiteName = result.snapshotRootDir.slice(SNAPSHOT_ROOT_DIR.length + 1)\n\t\t\tconst key = `(${suiteName}) ${result.fileName}`\n\t\t\tacc[key] = [...(acc[key] ?? []), result]\n\t\t\treturn acc\n\t\t},\n\t\t{} as Record<string, ImageSnapshotResults[]>,\n\t)\n\treturn (\n\t\t<AddonPanel active={active}>\n\t\t\t{snapshotResults.length > 0 ? (\n\t\t\t\t<ScrollArea vertical>\n\t\t\t\t\t{Object.entries(groupedResults).map(([key, results]) => (\n\t\t\t\t\t\t<div key={key}>\n\t\t\t\t\t\t\t{results.some((result) => result.type === 'diff') ? (\n\t\t\t\t\t\t\t\t<>\n\t\t\t\t\t\t\t\t\t<SnapshotRow failed>{key}</SnapshotRow>\n\t\t\t\t\t\t\t\t\t{results.map((result) => (\n\t\t\t\t\t\t\t\t\t\t<img key={result.filePath} src={`data:image/png;base64,${result.base64}`} alt={result.fileName} />\n\t\t\t\t\t\t\t\t\t))}\n\t\t\t\t\t\t\t\t</>\n\t\t\t\t\t\t\t) : (\n\t\t\t\t\t\t\t\t<>\n\t\t\t\t\t\t\t\t\t<SnapshotRow>\n\t\t\t\t\t\t\t\t\t\t<span>{key}</span>\n\t\t\t\t\t\t\t\t\t\t<IconButton onClick={() => onRefresh()}>\n\t\t\t\t\t\t\t\t\t\t\t<RefreshIcon />\n\t\t\t\t\t\t\t\t\t\t</IconButton>\n\t\t\t\t\t\t\t\t\t</SnapshotRow>\n\t\t\t\t\t\t\t\t\t<img\n\t\t\t\t\t\t\t\t\t\tkey={results[0].filePath}\n\t\t\t\t\t\t\t\t\t\tsrc={`data:image/png;base64,${results[0].base64}`}\n\t\t\t\t\t\t\t\t\t\talt={results[0].fileName}\n\t\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t\t</>\n\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t</div>\n\t\t\t\t\t))}\n\t\t\t\t</ScrollArea>\n\t\t\t) : (\n\t\t\t\t<Placeholder>There is no snapshots for this story</Placeholder>\n\t\t\t)}\n\t\t</AddonPanel>\n\t)\n})\n\nconst SnapshotRow = styled.div<{ failed?: boolean }>(({ theme, failed }) => ({\n\tdisplay: 'flex',\n\talignItems: 'center',\n\tgap: '0.5rem',\n\tpaddingBlock: '0.5rem',\n\tpaddingInline: '0.2rem',\n\tbackgroundColor: failed ? theme.background.negative : theme.background.positive,\n\tcolor: theme.barTextColor,\n}))\n","export const NAME = 'storybook-addon-vis'\nexport const VIS_PANEL_ID = `${NAME}/vis_panel`\n","export type VisEvent = ImageSnapshotResultsRequest | ImageSnapshotResultsResponse\n\nexport const IMAGE_SNAPSHOT_RESULTS_REQUEST = 'IMAGE_SNAPSHOT_RESULTS_REQUEST'\nexport const IMAGE_SNAPSHOT_RESULTS_RESPONSE = 'IMAGE_SNAPSHOT_RESULTS_RESPONSE'\n\nexport function requestImageSnapshotResults({ name, importPath }: { name: string; importPath: string }) {\n\treturn {\n\t\ttype: IMAGE_SNAPSHOT_RESULTS_REQUEST,\n\t\tname,\n\t\timportPath,\n\t}\n}\n\nexport type ImageSnapshotResultsRequest = {\n\ttype: typeof IMAGE_SNAPSHOT_RESULTS_REQUEST\n\tname: string\n\timportPath: string\n}\n\nexport type ImageSnapshotResultsResponse = {\n\ttype: typeof IMAGE_SNAPSHOT_RESULTS_RESPONSE\n\tname: string\n\timportPath: string\n\tresults: ImageSnapshotResults[]\n}\n\nexport type ImageSnapshotResults = {\n\tfilePath: string\n\tfileName: string\n\tsnapshotRootDir: string\n\ttype: 'baseline' | 'diff' | 'result'\n\tbase64: string\n}\n","import { useEffect, useState } from 'react'\nimport { addons, types } from 'storybook/internal/manager-api'\nimport { VisPanel } from './components/vis_panel.tsx'\nimport { NAME, VIS_PANEL_ID } from './shared/contants.ts'\nimport {\n\tIMAGE_SNAPSHOT_RESULTS_RESPONSE,\n\trequestImageSnapshotResults,\n\ttype ImageSnapshotResults,\n\ttype VisEvent,\n} from './shared/events.ts'\n\n// Register the addon\naddons.register(NAME, (api) => {\n\t// Register the tool\n\tif ((globalThis as any).CONFIG_TYPE === 'DEVELOPMENT') {\n\t\taddons.add(VIS_PANEL_ID, {\n\t\t\ttype: types.PANEL,\n\t\t\ttitle: 'Vis',\n\t\t\tmatch: ({ tabId, viewMode }) => !tabId && viewMode === 'story',\n\t\t\trender({ active }) {\n\t\t\t\tif (!active) return null\n\t\t\t\tconst [snapshotResults, setSnapshotResults] = useState<ImageSnapshotResults[]>([])\n\n\t\t\t\tconst storyData = api.getCurrentStoryData()\n\n\t\t\t\tuseEffect(() => {\n\t\t\t\t\tconst disposes = [\n\t\t\t\t\t\tapi.on(NAME, (event: VisEvent) => {\n\t\t\t\t\t\t\tif (event.name !== storyData.name) return\n\t\t\t\t\t\t\tif (event.importPath !== storyData.importPath) return\n\n\t\t\t\t\t\t\tif (event.type === IMAGE_SNAPSHOT_RESULTS_RESPONSE) {\n\t\t\t\t\t\t\t\tsetSnapshotResults(event.results)\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}),\n\t\t\t\t\t\t// api.on('UNIVERSAL_STORE:storybook/test', (event) => {\n\t\t\t\t\t\t// \tconsole.log('storybook/test', event)\n\t\t\t\t\t\t// }),\n\t\t\t\t\t]\n\t\t\t\t\tapi.emit(NAME, requestImageSnapshotResults(storyData))\n\t\t\t\t\treturn () => disposes.forEach((dispose) => dispose())\n\t\t\t\t}, [storyData])\n\t\t\t\treturn (\n\t\t\t\t\t<VisPanel\n\t\t\t\t\t\tactive={active}\n\t\t\t\t\t\tsnapshotResults={snapshotResults}\n\t\t\t\t\t\tonRefresh={() => {\n\t\t\t\t\t\t\tapi.emit(NAME, requestImageSnapshotResults(storyData))\n\t\t\t\t\t\t}}\n\t\t\t\t\t/>\n\t\t\t\t)\n\t\t\t},\n\t\t})\n\t}\n})\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "storybook-addon-vis",
3
- "version": "2.0.4",
3
+ "version": "2.0.5",
4
4
  "description": "Storybook Vitest visual testing addon",
5
5
  "keywords": [
6
6
  "image-snapshot",
@@ -145,6 +145,7 @@
145
145
  "nuke": "rimraf node_modules",
146
146
  "prerelease": "zx scripts/prepublish-checks.js",
147
147
  "sb": "storybook dev -p 6006",
148
+ "sb:build": "cross-env NODE_ENV=production storybook build",
148
149
  "t:n": "vitest run -c vitest.config.node.ts",
149
150
  "t:wb": "cross-env BROWSER=firefox BROWSERPROVIDER=webdriverio vitest run",
150
151
  "test": "vitest run",
package/src/manager.tsx CHANGED
@@ -12,42 +12,44 @@ import {
12
12
  // Register the addon
13
13
  addons.register(NAME, (api) => {
14
14
  // Register the tool
15
- addons.add(VIS_PANEL_ID, {
16
- type: types.PANEL,
17
- title: 'Vis',
18
- match: ({ tabId, viewMode }) => !tabId && viewMode === 'story',
19
- render({ active }) {
20
- if (!active) return null
21
- const [snapshotResults, setSnapshotResults] = useState<ImageSnapshotResults[]>([])
15
+ if ((globalThis as any).CONFIG_TYPE === 'DEVELOPMENT') {
16
+ addons.add(VIS_PANEL_ID, {
17
+ type: types.PANEL,
18
+ title: 'Vis',
19
+ match: ({ tabId, viewMode }) => !tabId && viewMode === 'story',
20
+ render({ active }) {
21
+ if (!active) return null
22
+ const [snapshotResults, setSnapshotResults] = useState<ImageSnapshotResults[]>([])
22
23
 
23
- const storyData = api.getCurrentStoryData()
24
+ const storyData = api.getCurrentStoryData()
24
25
 
25
- useEffect(() => {
26
- const disposes = [
27
- api.on(NAME, (event: VisEvent) => {
28
- if (event.name !== storyData.name) return
29
- if (event.importPath !== storyData.importPath) return
26
+ useEffect(() => {
27
+ const disposes = [
28
+ api.on(NAME, (event: VisEvent) => {
29
+ if (event.name !== storyData.name) return
30
+ if (event.importPath !== storyData.importPath) return
30
31
 
31
- if (event.type === IMAGE_SNAPSHOT_RESULTS_RESPONSE) {
32
- setSnapshotResults(event.results)
33
- }
34
- }),
35
- // api.on('UNIVERSAL_STORE:storybook/test', (event) => {
36
- // console.log('storybook/test', event)
37
- // }),
38
- ]
39
- api.emit(NAME, requestImageSnapshotResults(storyData))
40
- return () => disposes.forEach((dispose) => dispose())
41
- }, [storyData])
42
- return (
43
- <VisPanel
44
- active={active}
45
- snapshotResults={snapshotResults}
46
- onRefresh={() => {
47
- api.emit(NAME, requestImageSnapshotResults(storyData))
48
- }}
49
- />
50
- )
51
- },
52
- })
32
+ if (event.type === IMAGE_SNAPSHOT_RESULTS_RESPONSE) {
33
+ setSnapshotResults(event.results)
34
+ }
35
+ }),
36
+ // api.on('UNIVERSAL_STORE:storybook/test', (event) => {
37
+ // console.log('storybook/test', event)
38
+ // }),
39
+ ]
40
+ api.emit(NAME, requestImageSnapshotResults(storyData))
41
+ return () => disposes.forEach((dispose) => dispose())
42
+ }, [storyData])
43
+ return (
44
+ <VisPanel
45
+ active={active}
46
+ snapshotResults={snapshotResults}
47
+ onRefresh={() => {
48
+ api.emit(NAME, requestImageSnapshotResults(storyData))
49
+ }}
50
+ />
51
+ )
52
+ },
53
+ })
54
+ }
53
55
  })