storybook-addon-tag-badges
Version:
Display Storybook tags as badges in the sidebar and toolbar.
1 lines • 25.3 kB
Source Map (JSON)
{"version":3,"sources":["../src/utils/tag.ts","../src/defaultConfig.ts","../src/constants.ts","../src/utils/display.ts","../src/useBadgesToDisplay.ts","../src/components/Badge.tsx","../src/components/Sidebar.tsx","../src/renderLabel.tsx"],"names":["getTagParts","tag","prefix","rest","getTagPrefix","getTagSuffix","matchTag","patterns","normalisedPatterns","pattern","suffix","prefixPattern","suffixPattern","matchTags","tags","config","defaultConfig","str","version","isExperimental","hue","KEY","DISPLAY_DEFAULTS","normaliseDisplayProperty","value","defaultValue","prop","normaliseDisplay","display","shouldDisplay","context","type","normalised","outcome","condition","useBadgesToDisplay","parameters","parentTags","useMemo","displayOutcome","acc","current","WithTooltipPatched","styled","WithTooltip","BadgeUI","as","bgColor","borderColor","fgColor","theme","TooltipUI","Badge","text","tooltip","restProps","useTheme","React","Fragment","TooltipMessage","getBadgeProps","entry","WithBadge","cfg","Container","Sidebar","children","item","addons","api","useStorybookApi","parentItem","badgesToDisplay","renderLabel"],"mappings":"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","file":"index.cjs","sourcesContent":["import type { TagPatterns } from '../types/TagPattern'\n\n/**\n * Splits a tag into a prefix and suffix, separated by a colon.\n * If no colons are present, `suffix` is `null`. If more than one\n * colons are present, `suffix` is a concatenation of all the parts\n * beyond the first one.\n * @param tag The tag being queried.\n * @returns The prefix and suffix.\n */\nexport function getTagParts(tag: string): {\n prefix: string\n suffix: string | null\n} {\n const [prefix, ...rest] = tag.split(':')\n return { prefix, suffix: rest.join(':') || null }\n}\n\n/**\n * Gets the prefix of a tag, i.e. the part before the\n * colon if it contains one, or the whole tag otherwise.\n * @param tag The tag being queried.\n * @returns The prefix or the whole tag.\n */\nexport function getTagPrefix(tag: string): string {\n return getTagParts(tag).prefix\n}\n\n/**\n * Gets the suffix of a tag, i.e. the part after the\n * colon if it contains one, or `null` otherwise.\n * @param tag The tag being queried.\n * @returns The suffix if it exists.\n */\nexport function getTagSuffix(tag: string): string | null {\n return getTagParts(tag).suffix\n}\n\n/**\n * Checks if a given tag matches any of the provided patterns.\n * Patterns can be regular expressions, strings, or objects with prefix and suffix patterns.\n * @param tag The tag to match against the patterns.\n * @param patterns The pattern or patterns to match the tag against.\n * @returns `true` if the tag matches any of the patterns, `false` otherwise.\n */\nexport function matchTag(tag: string, patterns: TagPatterns): boolean {\n const normalisedPatterns = [patterns].flat()\n for (const pattern of normalisedPatterns) {\n if (pattern instanceof RegExp) {\n if (tag.match(pattern)) {\n return true\n }\n } else if (typeof pattern === 'string') {\n if (tag === pattern) {\n return true\n }\n } else {\n const { prefix, suffix } = getTagParts(tag)\n const prefixPattern = pattern.prefix ?? '[^:]+'\n const suffixPattern = pattern.suffix ?? '.+'\n\n if (\n prefix.match(prefixPattern) &&\n ((suffix && suffixPattern) || (!suffix && !suffixPattern)) &&\n suffix?.match(suffixPattern)\n ) {\n return true\n }\n }\n }\n\n return false\n}\n\n/**\n * Filters an array of tags based on the provided pattern configuration.\n * @param tags An array of tags to filter.\n * @param config The pattern configuration to match tags against.\n * @returns An array of tags that match the given pattern configuration.\n */\nexport function matchTags(tags: string[], config: TagPatterns): string[] {\n return tags.filter((tag) => matchTag(tag, config))\n}\n","import type { TagBadgeParameters } from './types/TagBadgeParameters'\n\nexport const defaultConfig: TagBadgeParameters = [\n {\n tags: 'new',\n badge: {\n text: 'New',\n bgColor: 'hsl(130, 100%, 74%)',\n borderColor: 'hsl(130, 100%, 34%)',\n fgColor: 'hsl(130, 100%, 6%)',\n },\n },\n {\n tags: ['alpha', 'beta', 'rc', 'experimental'],\n badge: ({ tag }) => {\n const upperFirst = (str: string): string =>\n str[0].toUpperCase() + str.slice(1)\n\n return {\n text: tag === 'rc' ? 'Release candidate' : upperFirst(tag),\n bgColor: 'hsl(257, 100%, 84%)',\n borderColor: 'hsl(257, 100%, 64%)',\n fgColor: 'hsl(257, 100%, 12%)',\n }\n },\n },\n {\n tags: 'deprecated',\n badge: {\n text: 'Deprecated',\n bgColor: 'hsl(36, 100%, 74%)',\n borderColor: 'hsl(36, 100%, 34%)',\n fgColor: 'hsl(36, 100%, 12%)',\n },\n },\n {\n tags: 'outdated',\n badge: {\n text: 'Outdated',\n bgColor: 'hsl(12, 100%, 74%)',\n borderColor: 'hsl(12, 100%, 34%)',\n fgColor: 'hsl(12, 100%, 12%)',\n },\n },\n {\n tags: 'danger',\n badge: {\n text: 'Danger',\n bgColor: 'hsl(0, 100%, 44%)',\n borderColor: 'hsl(0, 100%, 64%)',\n fgColor: 'hsl(0, 100%, 94%)',\n },\n },\n {\n tags: ['code-only'],\n badge: {\n text: 'Code Only',\n bgColor: 'hsl(84, 0%, 84%)',\n borderColor: 'hsl(84, 0%, 34%)',\n fgColor: 'hsl(84, 0%, 12%)',\n },\n },\n {\n tags: {\n prefix: 'version',\n },\n badge: ({ getTagSuffix, tag }) => {\n const version = getTagSuffix(tag)\n const isExperimental = version?.startsWith('0')\n const hue = isExperimental ? 66 : 194\n\n return {\n text: `${version}`,\n bgColor: `hsl(${hue}, 100%, 74%)`,\n borderColor: `hsl(${hue}, 100%, 34%)`,\n fgColor: `hsl(${hue}, 100%, 12%)`,\n tooltip: `Version ${version}${isExperimental ? '. Experimental!' : ''}`,\n }\n },\n },\n]\n","export const ADDON_ID = 'storybook/addon-tag-badges'\nexport const TOOL_ID = `${ADDON_ID}/tool`\nexport const KEY = `tagBadges`\n","import { HashEntry } from '@storybook/manager-api'\nimport type { ArrayElement } from '../types/ArrayElement'\nimport type { TagBadgeParameters } from '../types/TagBadgeParameters'\nimport type {\n Display,\n DisplayOption,\n DisplayOptionItem,\n} from '../types/DisplayOption'\nimport { API_HashEntry } from '@storybook/types'\n\nexport interface ShouldDisplayOptions {\n config: Partial<ArrayElement<TagBadgeParameters>>\n context: 'sidebar' | 'toolbar'\n type: HashEntry['type']\n}\n\ntype NormalisedDisplayOption =\n | {\n skipInherited?: boolean\n type: API_HashEntry['type']\n }\n | {\n skipInherited: boolean\n type?: API_HashEntry['type']\n }\n\ntype NormalisedDisplayOptions = NormalisedDisplayOption[]\n\nexport const DISPLAY_DEFAULTS = {\n sidebar: [\n { skipInherited: true },\n { type: 'component', skipInherited: false },\n { type: 'group', skipInherited: false },\n ],\n toolbar: [{ type: 'docs' }, { type: 'story' }],\n} satisfies {\n sidebar: NormalisedDisplayOptions\n toolbar: NormalisedDisplayOptions\n}\n\nfunction normaliseDisplayProperty(\n value: DisplayOption<API_HashEntry['type']> | undefined,\n defaultValue: NormalisedDisplayOptions,\n): NormalisedDisplayOptions {\n if (value === undefined) {\n return [...defaultValue]\n }\n\n const toNormalise = (\n Array.isArray(value) ? value : [value]\n ) satisfies DisplayOptionItem<API_HashEntry['type']>[]\n\n return toNormalise\n .map((prop) => {\n if (typeof prop === 'boolean') {\n return prop ? [{ skipInherited: false }] : []\n } else if (typeof prop === 'string') {\n return [{ type: prop }]\n }\n return prop\n })\n .flat()\n}\n\nexport function normaliseDisplay(display?: Display): {\n sidebar: NormalisedDisplayOptions\n toolbar: NormalisedDisplayOptions\n} {\n return {\n sidebar: normaliseDisplayProperty(\n display?.sidebar,\n DISPLAY_DEFAULTS.sidebar,\n ),\n toolbar: normaliseDisplayProperty(\n display?.toolbar,\n DISPLAY_DEFAULTS.toolbar,\n ),\n }\n}\n\nexport enum DisplayOutcome {\n NEVER = 'never',\n SKIP_INHERITED = 'skip-inherited',\n ALWAYS = 'always',\n}\n\n/**\n * Determines whether a badge should be displayed based on the provided config\n * and based on the display context (toolbar, sidebar).\n *\n * @param options The options to determine display.\n * @param options.config The configuration for the badge.\n * @param options.context The context where the badge might be displayed.\n * @param options.type The type of the current entry.\n *\n * @returns {DisplayOutcome} `ALWAYS` if the badge should be displayed, `NEVER` if\n * it shouldn't, and `SKIP_INHERITED` if it should only when the parent entry doesn't\n * show a badge for the same tag already.\n */\nexport function shouldDisplay({\n config,\n context,\n type,\n}: ShouldDisplayOptions): DisplayOutcome {\n if (type === 'root') {\n return DisplayOutcome.NEVER\n }\n\n const normalised = normaliseDisplay(config.display)[context]\n let outcome = DisplayOutcome.NEVER\n\n for (const condition of normalised) {\n // When a type is defined, it must always match the type of the HashEntry.\n // If it doesn't, we don't return true yet.\n if (condition.type !== undefined && condition.type !== type) {\n continue\n }\n\n // By default, we hide badges for tags that are already displayed\n // by a parent entry in the sidebar. This option does nothing in\n // the toolbar context.\n if (context !== 'toolbar' && condition.skipInherited !== false) {\n outcome = DisplayOutcome.SKIP_INHERITED\n continue\n }\n\n // If we reach this, the HashEntry should be displayed unconditionally.\n // Return early as there is no point in iterating further.\n outcome = DisplayOutcome.ALWAYS\n break\n }\n\n return outcome\n}\n","import { useMemo } from 'react'\n\nimport { DisplayOutcome, shouldDisplay } from './utils/display'\nimport { matchTags } from './utils/tag'\nimport {\n API_ComponentEntry,\n API_GroupEntry,\n API_LeafEntry,\n} from '@storybook/types'\nimport { TagBadgeParameters } from './types/TagBadgeParameters'\nimport { BadgeOrBadgeFn } from './types/Badge'\n\ninterface UseBadgesToDisplayOptions {\n context: 'sidebar' | 'toolbar'\n parameters: TagBadgeParameters\n parentTags?: string[]\n tags: string[]\n type:\n | API_ComponentEntry['type']\n | API_GroupEntry['type']\n | API_LeafEntry['type']\n}\n\ntype BadgesToDisplay = { badge: BadgeOrBadgeFn; tag: string }[]\n\nexport function useBadgesToDisplay({\n context,\n parameters,\n parentTags,\n tags,\n type,\n}: UseBadgesToDisplayOptions): BadgesToDisplay {\n return useMemo(() => {\n /* Handle potentially missing data from callees. */\n if (!tags || !type) {\n return []\n }\n\n return (parameters || [])\n .map((config) => ({\n ...config,\n displayOutcome: shouldDisplay({ context, config, type }),\n }))\n .filter(({ displayOutcome }) => displayOutcome !== DisplayOutcome.NEVER)\n .flatMap((config) =>\n matchTags(tags, config.tags).map((tag) => ({\n badge: config.badge,\n displayOutcome: config.displayOutcome,\n tag,\n })),\n )\n .filter(\n ({ displayOutcome, tag }) =>\n displayOutcome !== DisplayOutcome.SKIP_INHERITED ||\n !parentTags?.includes(tag),\n )\n .reduce((acc: BadgesToDisplay, current) => {\n if (acc.every(({ tag }) => tag !== current.tag)) {\n acc.push(current)\n }\n return acc\n }, [])\n }, [parameters, parentTags, tags, type])\n}\n","import React, { Fragment } from 'react'\nimport type { HashEntry } from '@storybook/manager-api'\nimport { WithTooltip, TooltipMessage } from '@storybook/components'\nimport { styled, useTheme } from '@storybook/theming'\n\nimport type { Badge as BadgeConfigType, BadgeOrBadgeFn } from '../types/Badge'\nimport { getTagParts, getTagPrefix, getTagSuffix } from '../utils/tag'\n\ninterface BadgeProps extends BadgeConfigType {\n context: 'sidebar' | 'toolbar'\n}\n\ninterface WithBadgeProps {\n config: BadgeOrBadgeFn\n entry: HashEntry\n tag: string\n context: 'sidebar' | 'toolbar'\n}\n\nconst WithTooltipPatched = styled(WithTooltip)`\n line-height: 1px;\n`\n\nconst BadgeUI = styled.div<\n Pick<BadgeProps, 'bgColor' | 'borderColor' | 'fgColor' | 'context'>\n>(({ as, bgColor, borderColor, fgColor, context, theme }) => ({\n display: 'inline-block',\n fontSize: 11,\n lineHeight: '.75rem',\n alignSelf: 'center',\n padding: context === 'sidebar' ? '3px 8px' : '4px 12px',\n border: 'none',\n cursor:\n as === 'button' ? 'help' : context === 'sidebar' ? 'cursor' : 'initial',\n borderRadius: '3em',\n fontWeight: theme.typography.weight.bold,\n background: bgColor ?? theme.color.mediumlight,\n boxShadow:\n theme.base === 'light'\n ? `inset 0 0 0 1px ${borderColor ?? `color-mix(in oklab, ${fgColor ?? theme.color.dark} 10%, transparent 90%)`}`\n : `inset 0 0 0 1px ${borderColor ?? 'none'}`,\n color: fgColor ?? theme.color.dark,\n}))\n\nconst TooltipUI = styled.div(({ theme }) => ({\n padding: '8px 12px',\n boxSizing: 'border-box',\n color: theme.color.defaultText,\n lineHeight: '1.125rem',\n}))\n\nexport const Badge: React.FC<BadgeProps> = ({\n context,\n text,\n tooltip,\n ...restProps\n}) => {\n const theme = useTheme()\n\n return (\n <Fragment>\n {!tooltip || context == 'sidebar' ? (\n <BadgeUI {...restProps} context={context} theme={theme}>\n {text}\n </BadgeUI>\n ) : (\n <WithTooltipPatched\n closeOnOutsideClick\n placement={'bottom'}\n tooltip={\n typeof tooltip === 'string' ? (\n <TooltipUI>{tooltip}</TooltipUI>\n ) : (\n <TooltipMessage {...tooltip} />\n )\n }\n >\n <BadgeUI as=\"button\" {...restProps} context={context} theme={theme}>\n {text}\n </BadgeUI>\n </WithTooltipPatched>\n )}\n </Fragment>\n )\n}\n\nexport function getBadgeProps(\n config: BadgeOrBadgeFn,\n entry: HashEntry,\n tag: string,\n): Omit<BadgeProps, 'context'> {\n const props =\n typeof config === 'function'\n ? config({ entry, getTagParts, getTagPrefix, getTagSuffix, tag })\n : config\n\n return props\n}\n\nexport const WithBadge: React.FC<WithBadgeProps> = ({\n config,\n entry,\n tag,\n ...restProps\n}) => {\n const cfg = getBadgeProps(config, entry, tag)\n\n return <Badge {...cfg} {...restProps} />\n}\n","import React, { type FC, type ReactNode } from 'react'\nimport { addons, useStorybookApi } from '@storybook/manager-api'\nimport type { API_HashEntry } from '@storybook/types'\nimport { styled } from '@storybook/theming'\n\nimport { KEY } from '../constants'\nimport { TagBadgeParameters } from '../types/TagBadgeParameters'\nimport { useBadgesToDisplay } from '../useBadgesToDisplay'\nimport { WithBadge } from './Badge'\n\ninterface SidebarProps {\n children: ReactNode\n item: API_HashEntry\n}\n\nconst Container = styled.div`\n display: flex;\n flex: 1;\n justify-content: space-between;\n margin-right: 32px;\n`\n\nexport const Sidebar: FC<SidebarProps> = ({ children, item }) => {\n const { [KEY]: parameters } = addons.getConfig() as {\n [KEY]: TagBadgeParameters\n }\n const api = useStorybookApi()\n\n if (\n item.type !== 'component' &&\n item.type !== 'group' &&\n item.type !== 'docs' &&\n item.type !== 'story'\n ) {\n return children\n }\n\n let parentTags\n if (item.parent) {\n const parentItem = api.resolveStory(item.parent)\n if (parentItem && parentItem.type !== 'root') {\n parentTags = parentItem.tags\n }\n }\n\n const badgesToDisplay = useBadgesToDisplay({\n context: 'sidebar',\n parameters,\n parentTags,\n tags: item.tags,\n type: item.type,\n })\n\n return (\n <Container>\n {children}\n {badgesToDisplay.length ? (\n <WithBadge\n config={badgesToDisplay[0].badge}\n context=\"sidebar\"\n entry={item}\n tag={badgesToDisplay[0].tag}\n />\n ) : (\n ''\n )}\n </Container>\n )\n}\n","import React from 'react'\nimport { API_HashEntry } from '@storybook/types'\n\nimport { Sidebar } from './components/Sidebar'\n\nexport function renderLabel(item: API_HashEntry) {\n if (\n item.type !== 'story' &&\n item.type !== 'group' &&\n item.type !== 'docs' &&\n item.type !== 'component'\n ) {\n return\n }\n\n return <Sidebar item={item}>{item.name}</Sidebar>\n}\n"]}