UNPKG

@storybook/addon-a11y

Version:

Storybook Addon A11y: Test UI component compliance with WCAG web accessibility standards

2,199 lines • 97 kB
import {
  ADDON_ID,
  DOCUMENTATION_DISCREPANCY_LINK,
  EVENTS,
  PANEL_ID,
  PARAM_KEY,
  STATUS_TYPE_ID_A11Y,
  STATUS_TYPE_ID_COMPONENT_TEST,
  VISION_GLOBAL_KEY,
  filterDefs,
  filters
} from "./_browser-chunks/chunk-7OPMK7TU.js";
import "./_browser-chunks/chunk-4BE7D4DS.js";

// src/manager.tsx
import React8 from "react";
import { Badge as Badge3 } from "storybook/internal/components";
import { addons, types, useAddonState as useAddonState2, useStorybookApi as useStorybookApi3 } from "storybook/manager-api";

// src/components/A11YPanel.tsx
import React6, { useMemo as useMemo3 } from "react";
import { Badge as Badge2, Button as Button4 } from "storybook/internal/components";
import { SyncIcon as SyncIcon2 } from "@storybook/icons";
import { styled as styled5 } from "storybook/theming";

// src/types.ts
var RuleType = {
  VIOLATION: "violations",
  PASS: "passes",
  INCOMPLETION: "incomplete"
};

// src/components/A11yContext.tsx
import React, {
  createContext,
  useCallback,
  useContext,
  useEffect,
  useMemo,
  useRef,
  useState
} from "react";
import {
  STORY_CHANGED,
  STORY_FINISHED,
  STORY_HOT_UPDATED,
  STORY_RENDER_PHASE_CHANGED
} from "storybook/internal/core-events";
import { HIGHLIGHT, REMOVE_HIGHLIGHT, SCROLL_INTO_VIEW } from "storybook/highlight";
import {
  experimental_getStatusStore,
  experimental_useStatusStore,
  useAddonState,
  useChannel,
  useGlobals,
  useParameter,
  useStorybookApi,
  useStorybookState
} from "storybook/manager-api";
import { convert, themes } from "storybook/theming";

// src/AccessibilityRuleMaps.ts
var axeRuleMapping_wcag_2_0_a_aa = {
  "area-alt": {
    title: "<area> alt text",
    axeSummary: "Ensure <area> elements of image maps have alternative text",
    friendlySummary: "Add alt text to all <area> elements of image maps."
  },
  "aria-allowed-attr": {
    title: "Supported ARIA attributes",
    axeSummary: "Ensure an element's role supports its ARIA attributes",
    friendlySummary: "Only use ARIA attributes that are permitted for the element's role."
  },
  "aria-braille-equivalent": {
    title: "Braille equivalent",
    axeSummary: "Ensure aria-braillelabel and aria-brailleroledescription have a non-braille equivalent",
    friendlySummary: "If you use braille ARIA labels, also provide a matching non-braille label."
  },
  "aria-command-name": {
    title: "ARIA command name",
    axeSummary: "Ensure every ARIA button, link and menuitem has an accessible name",
    friendlySummary: "Every ARIA button, link, or menuitem needs a label or accessible name."
  },
  "aria-conditional-attr": {
    title: "ARIA attribute valid for role",
    axeSummary: "Ensure ARIA attributes are used as described in the specification of the element's role",
    friendlySummary: "Follow the element role's specification when using ARIA attributes."
  },
  "aria-deprecated-role": {
    title: "Deprecated ARIA role",
    axeSummary: "Ensure elements do not use deprecated roles",
    friendlySummary: "Don't use deprecated ARIA roles on elements."
  },
  "aria-hidden-body": {
    title: "Hidden body",
    axeSummary: 'Ensure aria-hidden="true" is not present on the document <body>',
    friendlySummary: 'Never set aria-hidden="true" on the <body> element.'
  },
  "aria-hidden-focus": {
    title: "Hidden element focus",
    axeSummary: "Ensure aria-hidden elements are not focusable nor contain focusable elements",
    friendlySummary: "Elements marked hidden (aria-hidden) should not be focusable or contain focusable items."
  },
  "aria-input-field-name": {
    title: "ARIA input field name",
    axeSummary: "Ensure every ARIA input field has an accessible name",
    friendlySummary: "Give each ARIA text input or field a label or accessible name."
  },
  "aria-meter-name": {
    title: "ARIA meter name",
    axeSummary: "Ensure every ARIA meter node has an accessible name",
    friendlySummary: 'Give each element with role="meter" a label or accessible name.'
  },
  "aria-progressbar-name": {
    title: "ARIA progressbar name",
    axeSummary: "Ensure every ARIA progressbar node has an accessible name",
    friendlySummary: 'Give each element with role="progressbar" a label or accessible name.'
  },
  "aria-prohibited-attr": {
    title: "ARIA prohibited attributes",
    axeSummary: "Ensure ARIA attributes are not prohibited for an element's role",
    friendlySummary: "Don't use ARIA attributes that are forbidden for that element's role."
  },
  "aria-required-attr": {
    title: "ARIA required attributes",
    axeSummary: "Ensure elements with ARIA roles have all required ARIA attributes",
    friendlySummary: "Include all required ARIA attributes for elements with that ARIA role."
  },
  "aria-required-children": {
    title: "ARIA required children",
    axeSummary: "Ensure elements with an ARIA role that require child roles contain them",
    friendlySummary: "If an ARIA role requires specific child roles, include those child elements."
  },
  "aria-required-parent": {
    title: "ARIA required parent",
    axeSummary: "Ensure elements with an ARIA role that require parent roles are contained by them",
    friendlySummary: "Place elements with certain ARIA roles inside the required parent role element."
  },
  "aria-roles": {
    title: "ARIA role value",
    axeSummary: "Ensure all elements with a role attribute use a valid value",
    friendlySummary: "Use only valid values in the role attribute (no typos or invalid roles)."
  },
  "aria-toggle-field-name": {
    title: "ARIA toggle field name",
    axeSummary: "Ensure every ARIA toggle field has an accessible name",
    friendlySummary: "Every ARIA toggle field (elements with the checkbox, radio, or switch roles) needs an accessible name."
  },
  "aria-tooltip-name": {
    title: "ARIA tooltip name",
    axeSummary: "Ensure every ARIA tooltip node has an accessible name",
    friendlySummary: 'Give each element with role="tooltip" a descriptive accessible name.'
  },
  "aria-valid-attr-value": {
    title: "ARIA attribute values valid",
    axeSummary: "Ensure all ARIA attributes have valid values",
    friendlySummary: "Use only valid values for ARIA attributes (no typos or invalid values)."
  },
  "aria-valid-attr": {
    title: "ARIA attribute valid",
    axeSummary: "Ensure attributes that begin with aria- are valid ARIA attributes",
    friendlySummary: "Use only valid aria-* attributes (make sure the attribute name is correct)."
  },
  blink: {
    title: "<blink> element",
    axeSummary: "Ensure <blink> elements are not used",
    friendlySummary: "Don't use the deprecated <blink> element."
  },
  "button-name": {
    title: "Button name",
    axeSummary: "Ensure buttons have discernible text",
    friendlySummary: "Every <button> needs a visible label or accessible name."
  },
  bypass: {
    title: "Navigation bypass",
    axeSummary: "Ensure each page has at least one mechanism to bypass navigation and jump to content",
    friendlySummary: 'Provide a way to skip repetitive navigation (e.g. a "Skip to content" link).'
  },
  "color-contrast": {
    title: "Color contrast",
    axeSummary: "Ensure the contrast between foreground and background text meets WCAG 2 AA minimum thresholds",
    friendlySummary: "The color contrast between text and its background meets WCAG AA contrast ratio."
  },
  "definition-list": {
    title: "Definition list structure",
    axeSummary: "Ensure <dl> elements are structured correctly",
    friendlySummary: "Definition lists (<dl>) should directly contain <dt> and <dd> elements in order."
  },
  dlitem: {
    title: "Definition list items",
    axeSummary: "Ensure <dt> and <dd> elements are contained by a <dl>",
    friendlySummary: "Ensure <dt> and <dd> elements are contained by a <dl>"
  },
  "document-title": {
    title: "Document title",
    axeSummary: "Ensure each HTML document contains a non-empty <title> element",
    friendlySummary: "Include a non-empty <title> element for every page."
  },
  "duplicate-id-aria": {
    title: "Unique id",
    axeSummary: "Ensure every id attribute value used in ARIA and in labels is unique",
    friendlySummary: "Every id used for ARIA or form labels should be unique on the page."
  },
  "form-field-multiple-labels": {
    title: "Multiple form field labels",
    axeSummary: "Ensure a form field does not have multiple <label> elements",
    friendlySummary: "Don't give a single form field more than one <label>."
  },
  "frame-focusable-content": {
    title: "Focusable frames",
    axeSummary: 'Ensure <frame> and <iframe> with focusable content do not have tabindex="-1"',
    friendlySummary: `Don't set tabindex="-1" on a <frame> or <iframe> that contains focusable elements.`
  },
  "frame-title-unique": {
    title: "Unique frame title",
    axeSummary: "Ensure <iframe> and <frame> elements contain a unique title attribute",
    friendlySummary: "Use a unique title attribute for each <frame> or <iframe> on the page."
  },
  "frame-title": {
    title: "Frame title",
    axeSummary: "Ensure <iframe> and <frame> elements have an accessible name",
    friendlySummary: "Every <frame> and <iframe> needs a title or accessible name."
  },
  "html-has-lang": {
    title: "<html> has lang",
    axeSummary: "Ensure every HTML document has a lang attribute",
    friendlySummary: "Add a lang attribute to the <html> element."
  },
  "html-lang-valid": {
    title: "<html> lang valid",
    axeSummary: "Ensure the <html lang> attribute has a valid value",
    friendlySummary: "Use a valid language code in the <html lang> attribute."
  },
  "html-xml-lang-mismatch": {
    title: "HTML and XML lang mismatch",
    axeSummary: "Ensure that HTML elements with both lang and xml:lang agree on the page's language",
    friendlySummary: "If using both lang and xml:lang on <html>, make sure they are the same language."
  },
  "image-alt": {
    title: "Image alt text",
    axeSummary: "Ensure <img> elements have alternative text or a role of none/presentation",
    friendlySummary: 'Give every image alt text or mark it as decorative with alt="".'
  },
  "input-button-name": {
    title: "Input button name",
    axeSummary: "Ensure input buttons have discernible text",
    friendlySummary: 'Give each <input type="button"> or similar a clear label (text or aria-label).'
  },
  "input-image-alt": {
    title: "Input image alt",
    axeSummary: 'Ensure <input type="image"> elements have alternative text',
    friendlySummary: '<input type="image"> must have alt text describing its image.'
  },
  label: {
    title: "Form label",
    axeSummary: "Ensure every form element has a label",
    friendlySummary: "Every form field needs an associated label."
  },
  "link-in-text-block": {
    title: "Identifiable links",
    axeSummary: "Ensure links are distinguishable from surrounding text without relying on color",
    friendlySummary: "Make sure links are obviously identifiable without relying only on color."
  },
  "link-name": {
    title: "Link name",
    axeSummary: "Ensure links have discernible text",
    friendlySummary: "Give each link meaningful text or an aria-label so its purpose is clear."
  },
  list: {
    title: "List structure",
    axeSummary: "Ensure that lists are structured correctly",
    friendlySummary: "Use proper list structure. Only use <li> inside <ul> or <ol>."
  },
  listitem: {
    title: "List item",
    axeSummary: "Ensure <li> elements are used semantically",
    friendlySummary: "Only use <li> tags inside <ul> or <ol> lists."
  },
  marquee: {
    title: "<marquee> element",
    axeSummary: "Ensure <marquee> elements are not used",
    friendlySummary: "Don't use the deprecated <marquee> element."
  },
  "meta-refresh": {
    title: "<meta> refresh",
    axeSummary: 'Ensure <meta http-equiv="refresh"> is not used for delayed refresh',
    friendlySummary: 'Avoid auto-refreshing or redirecting pages using <meta http-equiv="refresh">.'
  },
  "meta-viewport": {
    title: "<meta> viewport scaling",
    axeSummary: 'Ensure <meta name="viewport"> does not disable text scaling and zooming',
    friendlySummary: `Don't disable user zooming in <meta name="viewport"> to allow scaling.`
  },
  "nested-interactive": {
    title: "Nested interactive controls",
    axeSummary: "Ensure interactive controls are not nested (nesting causes screen reader/focus issues)",
    friendlySummary: "Do not nest interactive elements; it can confuse screen readers and keyboard focus."
  },
  "no-autoplay-audio": {
    title: "Autoplaying video",
    axeSummary: "Ensure <video> or <audio> do not autoplay audio > 3 seconds without a control to stop/mute",
    friendlySummary: "Don't autoplay audio for more than 3 seconds without providing a way to stop or mute it."
  },
  "object-alt": {
    title: "<object> alt text",
    axeSummary: "Ensure <object> elements have alternative text",
    friendlySummary: "Provide alternative text or content for <object> elements."
  },
  "role-img-alt": {
    title: 'role="img" alt text',
    axeSummary: 'Ensure elements with role="img" have alternative text',
    friendlySummary: 'Any element with role="img" needs alt text.'
  },
  "scrollable-region-focusable": {
    title: "Scrollable element focusable",
    axeSummary: "Ensure elements with scrollable content are keyboard-accessible",
    friendlySummary: "If an area can scroll, ensure it can be focused and scrolled via keyboard."
  },
  "select-name": {
    title: "<select> name",
    axeSummary: "Ensure <select> elements have an accessible name",
    friendlySummary: "Give each <select> field a label or other accessible name."
  },
  "server-side-image-map": {
    title: "Server-side image map",
    axeSummary: "Ensure that server-side image maps are not used",
    friendlySummary: "Don't use server-side image maps."
  },
  "svg-img-alt": {
    title: "SVG image alt text",
    axeSummary: "Ensure <svg> images/graphics have accessible text",
    friendlySummary: 'SVG images with role="img" or similar need a text description.'
  },
  "td-headers-attr": {
    title: "Table headers attribute",
    axeSummary: "Ensure each cell in a table using headers only refers to <th> in that table",
    friendlySummary: "In tables using the headers attribute, only reference other cells in the same table."
  },
  "th-has-data-cells": {
    title: "<th> has data cell",
    axeSummary: "Ensure <th> (or header role) elements have data cells they describe",
    friendlySummary: "Every table header (<th> or header role) should correspond to at least one data cell."
  },
  "valid-lang": {
    title: "Valid lang",
    axeSummary: "Ensure lang attributes have valid values",
    friendlySummary: "Use valid language codes in all lang attributes."
  },
  "video-caption": {
    title: "<video> captions",
    axeSummary: "Ensure <video> elements have captions",
    friendlySummary: "Provide captions for all <video> content."
  }
}, axeRuleMapping_wcag_2_1_a_aa = {
  "autocomplete-valid": {
    title: "autocomplete attribute valid",
    axeSummary: "Ensure the autocomplete attribute is correct and suitable for the form field",
    friendlySummary: "Use valid autocomplete values that match the form field's purpose."
  },
  "avoid-inline-spacing": {
    title: "Forced inline spacing",
    axeSummary: "Ensure that text spacing set via inline styles can be adjusted with custom CSS",
    friendlySummary: "Don't lock in text spacing with forced (!important) inline styles\u2014allow user CSS to adjust text spacing."
  }
}, axeRuleMapping_wcag_2_2_a_aa = {
  "target-size": {
    title: "Touch target size",
    axeSummary: "Ensure touch targets have sufficient size and space",
    friendlySummary: "Make sure interactive elements are big enough and not too close together for touch."
  }
}, axeRuleMapping_best_practices = {
  accesskeys: {
    title: "Unique accesskey",
    axeSummary: "Ensure every accesskey attribute value is unique",
    friendlySummary: "Use unique values for all accesskey attributes."
  },
  "aria-allowed-role": {
    title: "Appropriate role value",
    axeSummary: "Ensure the role attribute has an appropriate value for the element",
    friendlySummary: "ARIA roles should have a valid value for the element."
  },
  "aria-dialog-name": {
    title: "ARIA dialog name",
    axeSummary: "Ensure every ARIA dialog and alertdialog has an accessible name",
    friendlySummary: "Give each ARIA dialog or alertdialog a title or accessible name."
  },
  "aria-text": {
    title: 'ARIA role="text"',
    axeSummary: 'Ensure role="text" is used on elements with no focusable descendants',
    friendlySummary: `Only use role="text" on elements that don't contain focusable elements.`
  },
  "aria-treeitem-name": {
    title: "ARIA treeitem name",
    axeSummary: "Ensure every ARIA treeitem node has an accessible name",
    friendlySummary: "Give each ARIA treeitem a label or accessible name."
  },
  "empty-heading": {
    title: "Empty heading",
    axeSummary: "Ensure headings have discernible text",
    friendlySummary: "Don't leave heading elements empty or hide them."
  },
  "empty-table-header": {
    title: "Empty table header",
    axeSummary: "Ensure table headers have discernible text",
    friendlySummary: "Make sure table header cells have visible text."
  },
  "frame-tested": {
    title: "Test all frames",
    axeSummary: "Ensure <iframe> and <frame> elements contain the axe-core script",
    friendlySummary: "Make sure axe-core is injected into all frames or iframes so they are tested."
  },
  "heading-order": {
    title: "Heading order",
    axeSummary: "Ensure the order of headings is semantically correct (no skipping levels)",
    friendlySummary: "Use proper heading order (don't skip heading levels)."
  },
  "image-redundant-alt": {
    title: "Redundant image alt text",
    axeSummary: "Ensure image alternative text is not repeated as nearby text",
    friendlySummary: "Avoid repeating the same information in both an image's alt text and nearby text."
  },
  "label-title-only": {
    title: "Visible form element label",
    axeSummary: "Ensure each form element has a visible label (not only title/ARIA)",
    friendlySummary: "Every form input needs a visible label (not only a title attribute or hidden text)."
  },
  "landmark-banner-is-top-level": {
    title: "Top-level landmark banner",
    axeSummary: "Ensure the banner landmark is at top level (not nested)",
    friendlySummary: "Use the banner landmark (e.g. site header) only at the top level of the page, not inside another landmark."
  },
  "landmark-complementary-is-top-level": {
    title: "Top-level <aside>",
    axeSummary: "Ensure the complementary landmark (<aside>) is top level",
    friendlySummary: 'The complementary landmark <aside> or role="complementary" should be a top-level region, not nested in another landmark.'
  },
  "landmark-contentinfo-is-top-level": {
    title: "Top-level contentinfo",
    axeSummary: "Ensure the contentinfo landmark (footer) is top level",
    friendlySummary: "Make sure the contentinfo landmark (footer) is at the top level of the page and not contained in another landmark."
  },
  "landmark-main-is-top-level": {
    title: "Top-level main",
    axeSummary: "Ensure the main landmark is at top level",
    friendlySummary: "The main landmark should be a top-level element and not nested inside another landmark."
  },
  "landmark-no-duplicate-banner": {
    title: "Duplicate banner landmark",
    axeSummary: "Ensure the document has at most one banner landmark",
    friendlySummary: 'Have only one role="banner" or <header> on a page.'
  },
  "landmark-no-duplicate-contentinfo": {
    title: "Duplicate contentinfo",
    axeSummary: "Ensure the document has at most one contentinfo landmark",
    friendlySummary: 'Have only one role="contentinfo" or <footer> on a page.'
  },
  "landmark-no-duplicate-main": {
    title: "Duplicate main",
    axeSummary: "Ensure the document has at most one main landmark",
    friendlySummary: 'Have only one role="main" or <main> on a page.'
  },
  "landmark-one-main": {
    title: "main landmark",
    axeSummary: "Ensure the document has a main landmark",
    friendlySummary: 'Include a main landmark on each page using a <main> region or role="main".'
  },
  "landmark-unique": {
    title: "Unique landmark",
    axeSummary: "Ensure landmarks have a unique role or role/label combination",
    friendlySummary: "If you use multiple landmarks of the same type, give them unique labels (names)."
  },
  "meta-viewport-large": {
    title: "Significant viewport scaling",
    axeSummary: 'Ensure <meta name="viewport"> can scale a significant amount (e.g. 500%)',
    friendlySummary: '<meta name="viewport"> should allow users to significantly scale content.'
  },
  "page-has-heading-one": {
    title: "Has <h1>",
    axeSummary: "Ensure the page (or at least one frame) contains a level-one heading",
    friendlySummary: "Every page or frame should have at least one <h1> heading."
  },
  "presentation-role-conflict": {
    title: "Presentational content",
    axeSummary: 'Ensure elements with role="presentation"/"none" have no ARIA or tabindex',
    friendlySummary: `Don't give elements with role="none"/"presentation" any ARIA attributes or a tabindex.`
  },
  region: {
    title: "Landmark regions",
    axeSummary: "Ensure all page content is contained by landmarks",
    friendlySummary: "Wrap all page content in appropriate landmark regions (<header>, <main>, <footer>, etc.)."
  },
  "scope-attr-valid": {
    title: "scope attribute",
    axeSummary: "Ensure the scope attribute is used correctly on tables",
    friendlySummary: "Use the scope attribute only on <th> elements, with proper values (col, row, etc.)."
  },
  "skip-link": {
    title: "Skip link",
    axeSummary: 'Ensure all "skip" links have a focusable target',
    friendlySummary: 'Make sure any "skip to content" link targets an existing, focusable element.'
  },
  tabindex: {
    title: "tabindex values",
    axeSummary: "Ensure tabindex attribute values are not greater than 0",
    friendlySummary: "Don't use tabindex values greater than 0."
  },
  "table-duplicate-name": {
    title: "Duplicate names for table",
    axeSummary: "Ensure the <caption> does not duplicate the summary attribute text",
    friendlySummary: "Don't use the same text in both a table's <caption> and its summary attribute."
  }
}, axeRuleMapping_wcag_2_x_aaa = {
  "color-contrast-enhanced": {
    title: "Enhanced color contrast",
    axeSummary: "Ensure contrast between text and background meets WCAG 2 AAA enhanced contrast thresholds",
    friendlySummary: "Use extra-high contrast for text and background to meet WCAG AAA level."
  },
  "identical-links-same-purpose": {
    title: "Same link name, same purpose",
    axeSummary: "Ensure links with the same accessible name serve a similar purpose",
    friendlySummary: "If two links have the same text, they should do the same thing (lead to the same content)."
  },
  "meta-refresh-no-exceptions": {
    title: 'No <meta http-equiv="refresh">',
    axeSummary: 'Ensure <meta http-equiv="refresh"> is not used for delayed refresh (no exceptions)',
    friendlySummary: `Don't auto-refresh or redirect pages using <meta http-equiv="refresh"> even with a delay.`
  }
}, axeRuleMapping_experimental = {
  "css-orientation-lock": {
    title: "CSS orientation lock",
    axeSummary: "Ensure content is not locked to a specific display orientation (works in all orientations)",
    friendlySummary: "Don't lock content to one screen orientation; support both portrait and landscape modes."
  },
  "focus-order-semantics": {
    title: "Focus order semantic role",
    axeSummary: "Ensure elements in the tab order have a role appropriate for interactive content",
    friendlySummary: "Ensure elements in the tab order have a role appropriate for interactive content"
  },
  "hidden-content": {
    title: "Hidden content",
    axeSummary: "Informs users about hidden content",
    friendlySummary: "Display hidden content on the page for test analysis."
  },
  "label-content-name-mismatch": {
    title: "Content name mismatch",
    axeSummary: "Ensure elements labeled by their content include that text in their accessible name",
    friendlySummary: "If an element's visible text serves as its label, include that text in its accessible name."
  },
  "p-as-heading": {
    title: "No <p> headings",
    axeSummary: "Ensure <p> elements aren't styled to look like headings (use real headings)",
    friendlySummary: "Don't just style a <p> to look like a heading \u2013 use an actual heading tag for headings."
  },
  "table-fake-caption": {
    title: "Table caption",
    axeSummary: "Ensure that tables with a caption use the <caption> element",
    friendlySummary: "Use a <caption> element for table captions instead of just styled text."
  },
  "td-has-header": {
    title: "<td> has header",
    axeSummary: "Ensure each non-empty data cell in large tables (3\xD73+) has one or more headers",
    friendlySummary: "Every data cell in large tables should be associated with at least one header cell."
  }
}, axeRuleMapping_deprecated = {
  "aria-roledescription": {
    title: "aria-roledescription",
    axeSummary: "Ensure aria-roledescription is only used on elements with an implicit or explicit role",
    friendlySummary: "Only use aria-roledescription on elements that already have a defined role."
  }
}, combinedRulesMap = {
  ...axeRuleMapping_wcag_2_0_a_aa,
  ...axeRuleMapping_wcag_2_1_a_aa,
  ...axeRuleMapping_wcag_2_2_a_aa,
  ...axeRuleMapping_wcag_2_x_aaa,
  ...axeRuleMapping_best_practices,
  ...axeRuleMapping_experimental,
  ...axeRuleMapping_deprecated
};

// src/axeRuleMappingHelper.ts
var getTitleForAxeResult = (axeResult) => combinedRulesMap[axeResult.id]?.title || axeResult.id, getFriendlySummaryForAxeResult = (axeResult) => combinedRulesMap[axeResult.id]?.friendlySummary || axeResult.description;

// src/components/A11yContext.tsx
var unhighlightedSelectors = ["html", "body", "main"], theme = convert(themes.light), colorsByType = {
  [RuleType.VIOLATION]: theme.color.negative,
  [RuleType.PASS]: theme.color.positive,
  [RuleType.INCOMPLETION]: theme.color.warning
}, A11yContext = createContext({
  parameters: {},
  results: void 0,
  highlighted: !1,
  toggleHighlight: () => {
  },
  tab: RuleType.VIOLATION,
  handleCopyLink: () => {
  },
  setTab: () => {
  },
  setStatus: () => {
  },
  status: "initial",
  error: void 0,
  handleManual: () => {
  },
  discrepancy: null,
  selectedItems: /* @__PURE__ */ new Map(),
  allExpanded: !1,
  toggleOpen: () => {
  },
  handleCollapseAll: () => {
  },
  handleExpandAll: () => {
  },
  handleJumpToElement: () => {
  },
  handleSelectionChange: () => {
  }
}), A11yContextProvider = (props) => {
  let parameters = useParameter("a11y", {}), [globals] = useGlobals() ?? [], api = useStorybookApi(), getInitialStatus = useCallback((manual2 = !1) => manual2 ? "manual" : "initial", []), manual = useMemo(() => globals?.a11y?.manual ?? !1, [globals?.a11y?.manual]), a11ySelection = useMemo(() => {
    let value = api.getQueryParam("a11ySelection");
    return value && api.setQueryParams({ a11ySelection: "" }), value;
  }, [api]), [state, setState] = useAddonState(ADDON_ID, {
    ui: {
      highlighted: !1,
      tab: RuleType.VIOLATION
    },
    results: void 0,
    error: void 0,
    status: getInitialStatus(manual)
  }), { ui, results, error, status } = state, { storyId } = useStorybookState(), currentStoryA11yStatusValue = experimental_useStatusStore(
    (allStatuses) => allStatuses[storyId]?.[STATUS_TYPE_ID_A11Y]?.value
  );
  useEffect(() => experimental_getStatusStore("storybook/component-test").onAllStatusChange(
    (statuses, previousStatuses) => {
      let current = statuses[storyId]?.[STATUS_TYPE_ID_COMPONENT_TEST], previous = previousStatuses[storyId]?.[STATUS_TYPE_ID_COMPONENT_TEST];
      current?.value === "status-value:error" && previous?.value !== "status-value:error" && setState((prev) => ({ ...prev, status: "component-test-error" }));
    }
  ), [setState, storyId]);
  let handleToggleHighlight = useCallback(() => {
    setState((prev) => ({
      ...prev,
      ui: { ...prev.ui, highlighted: !prev.ui.highlighted }
    }));
  }, [setState]), statusTimerRef = useRef(null);
  useEffect(() => () => {
    statusTimerRef.current !== null && clearTimeout(statusTimerRef.current);
  }, []);
  let [selectedItems, setSelectedItems] = useState(() => {
    let initialValue = /* @__PURE__ */ new Map();
    if (a11ySelection && /^[a-z]+.[a-z-]+.[0-9]+$/.test(a11ySelection)) {
      let [type, id] = a11ySelection.split(".");
      initialValue.set(`${type}.${id}`, a11ySelection);
    }
    return initialValue;
  }), allExpanded = useMemo(() => results?.[ui.tab]?.every((result) => selectedItems.has(`${ui.tab}.${result.id}`)) ?? !1, [results, selectedItems, ui.tab]), toggleOpen = useCallback(
    (event, type, item) => {
      event.stopPropagation();
      let key = `${type}.${item.id}`;
      setSelectedItems((prev) => new Map(prev.delete(key) ? prev : prev.set(key, `${key}.1`)));
    },
    []
  ), handleCollapseAll = useCallback(() => {
    setSelectedItems(/* @__PURE__ */ new Map());
  }, []), handleExpandAll = useCallback(() => {
    setSelectedItems(
      (prev) => new Map(
        results?.[ui.tab]?.map((result) => {
          let key = `${ui.tab}.${result.id}`;
          return [key, prev.get(key) ?? `${key}.1`];
        }) ?? []
      )
    );
  }, [results, ui.tab]), handleSelectionChange = useCallback((key) => {
    let [type, id] = key.split(".");
    setSelectedItems((prev) => new Map(prev.set(`${type}.${id}`, key)));
  }, []), handleError = useCallback(
    (err) => {
      setState((prev) => ({ ...prev, status: "error", error: err }));
    },
    [setState]
  ), handleResult = useCallback(
    (axeResults, id) => {
      storyId === id && (setState((prev) => ({ ...prev, status: "ran", results: axeResults })), statusTimerRef.current !== null && clearTimeout(statusTimerRef.current), statusTimerRef.current = setTimeout(() => {
        statusTimerRef.current = null, setState((prev) => prev.status === "ran" ? { ...prev, status: "ready" } : prev), setSelectedItems((prev) => {
          if (prev.size === 1) {
            let [key] = prev.values();
            document.getElementById(key)?.scrollIntoView({ behavior: "smooth", block: "center" });
          }
          return prev;
        });
      }, 900));
    },
    [storyId, setState, setSelectedItems]
  ), handleSelect = useCallback(
    (itemId, details) => {
      let [type, id] = itemId.split("."), { helpUrl, nodes } = results?.[type]?.find((r) => r.id === id) || {}, openedWindow = helpUrl && window.open(helpUrl, "_blank", "noopener,noreferrer");
      if (nodes && !openedWindow) {
        let index = nodes.findIndex((n) => details.selectors.some((s) => s === String(n.target))) ?? -1;
        if (index !== -1) {
          let key = `${type}.${id}.${index + 1}`;
          setSelectedItems(/* @__PURE__ */ new Map([[`${type}.${id}`, key]])), setTimeout(() => {
            document.getElementById(key)?.scrollIntoView({ behavior: "smooth", block: "center" });
          }, 100);
        }
      }
    },
    [results]
  ), handleReport = useCallback(
    ({ reporters }) => {
      let a11yReport = reporters.find((r) => r.type === "a11y");
      a11yReport && ("error" in a11yReport.result ? handleError(a11yReport.result.error) : handleResult(a11yReport.result, storyId));
    },
    [handleError, handleResult, storyId]
  ), handleReset = useCallback(
    ({ newPhase }) => {
      newPhase === "loading" ? setState((prev) => ({
        ...prev,
        results: void 0,
        status: manual ? "manual" : "initial"
      })) : newPhase === "afterEach" && !manual && setState((prev) => ({ ...prev, status: "running" }));
    },
    [manual, setState]
  ), emit = useChannel(
    {
      [EVENTS.RESULT]: handleResult,
      [EVENTS.ERROR]: handleError,
      [EVENTS.SELECT]: handleSelect,
      [STORY_CHANGED]: () => setSelectedItems(/* @__PURE__ */ new Map()),
      [STORY_RENDER_PHASE_CHANGED]: handleReset,
      [STORY_FINISHED]: handleReport,
      [STORY_HOT_UPDATED]: () => {
        setState((prev) => ({ ...prev, status: "running" })), emit(EVENTS.MANUAL, storyId, parameters);
      }
    },
    [handleReset, handleReport, handleSelect, handleError, handleResult, parameters, storyId]
  ), handleManual = useCallback(() => {
    setState((prev) => ({ ...prev, status: "running" })), emit(EVENTS.MANUAL, storyId, parameters);
  }, [emit, parameters, setState, storyId]), handleCopyLink = useCallback(async (linkPath) => {
    let { createCopyToClipboardFunction } = await import("storybook/internal/components");
    await createCopyToClipboardFunction()(`${window.location.origin}${linkPath}`);
  }, []), handleJumpToElement = useCallback(
    (target) => emit(SCROLL_INTO_VIEW, target),
    [emit]
  );
  useEffect(() => {
    setState((prev) => ({ ...prev, status: getInitialStatus(manual) }));
  }, [getInitialStatus, manual, setState]);
  let isInitial = status === "initial";
  useEffect(() => {
    a11ySelection && setState((prev) => {
      let update = { ...prev.ui, highlighted: !0 }, [type] = a11ySelection.split(".") ?? [];
      return type && Object.values(RuleType).includes(type) && (update.tab = type), { ...prev, ui: update };
    });
  }, [a11ySelection]), useEffect(() => {
    if (emit(REMOVE_HIGHLIGHT, `${ADDON_ID}/selected`), emit(REMOVE_HIGHLIGHT, `${ADDON_ID}/others`), !ui.highlighted || isInitial)
      return;
    let selected = Array.from(selectedItems.values()).flatMap((key) => {
      let [type, id, number] = key.split(".");
      if (type !== ui.tab)
        return [];
      let target = results?.[type]?.find((r) => r.id === id)?.nodes[Number(number) - 1]?.target;
      return target ? [String(target)] : [];
    });
    selected.length && emit(HIGHLIGHT, {
      id: `${ADDON_ID}/selected`,
      priority: 1,
      selectors: selected,
      styles: {
        outline: `1px solid color-mix(in srgb, ${colorsByType[ui.tab]}, transparent 30%)`,
        backgroundColor: "transparent"
      },
      hoverStyles: {
        outlineWidth: "2px"
      },
      focusStyles: {
        backgroundColor: "transparent"
      },
      menu: results?.[ui.tab].map((result) => {
        let selectors = result.nodes.flatMap((n) => n.target).map(String).filter((e) => selected.includes(e));
        return [
          {
            id: `${ui.tab}.${result.id}:info`,
            title: getTitleForAxeResult(result),
            description: getFriendlySummaryForAxeResult(result),
            selectors
          },
          {
            id: `${ui.tab}.${result.id}`,
            iconLeft: "info",
            iconRight: "shareAlt",
            title: "Learn how to resolve this violation",
            clickEvent: EVENTS.SELECT,
            selectors
          }
        ];
      })
    });
    let others = results?.[ui.tab].flatMap((r) => r.nodes.flatMap((n) => n.target).map(String)).filter((e) => ![...unhighlightedSelectors, ...selected].includes(e));
    others?.length && emit(HIGHLIGHT, {
      id: `${ADDON_ID}/others`,
      selectors: others,
      styles: {
        outline: `1px solid color-mix(in srgb, ${colorsByType[ui.tab]}, transparent 30%)`,
        backgroundColor: `color-mix(in srgb, ${colorsByType[ui.tab]}, transparent 60%)`
      },
      hoverStyles: {
        outlineWidth: "2px"
      },
      focusStyles: {
        backgroundColor: "transparent"
      },
      menu: results?.[ui.tab].map((result) => {
        let selectors = result.nodes.flatMap((n) => n.target).map(String).filter((e) => !selected.includes(e));
        return [
          {
            id: `${ui.tab}.${result.id}:info`,
            title: getTitleForAxeResult(result),
            description: getFriendlySummaryForAxeResult(result),
            selectors
          },
          {
            id: `${ui.tab}.${result.id}`,
            iconLeft: "info",
            iconRight: "shareAlt",
            title: "Learn how to resolve this violation",
            clickEvent: EVENTS.SELECT,
            selectors
          }
        ];
      })
    });
  }, [isInitial, emit, ui.highlighted, results, ui.tab, selectedItems]);
  let discrepancy = useMemo(() => {
    if (!currentStoryA11yStatusValue)
      return null;
    if (currentStoryA11yStatusValue === "status-value:success" && results?.violations.length)
      return "cliPassedBrowserFailed";
    if (currentStoryA11yStatusValue === "status-value:error" && !results?.violations.length) {
      if (status === "ready" || status === "ran")
        return "browserPassedCliFailed";
      if (status === "manual")
        return "cliFailedButModeManual";
    }
    return null;
  }, [results?.violations.length, status, currentStoryA11yStatusValue]);
  return React.createElement(
    A11yContext.Provider,
    {
      value: {
        parameters,
        results,
        highlighted: ui.highlighted,
        toggleHighlight: handleToggleHighlight,
        tab: ui.tab,
        setTab: useCallback(
          (type) => setState((prev) => ({ ...prev, ui: { ...prev.ui, tab: type } })),
          [setState]
        ),
        handleCopyLink,
        status,
        setStatus: useCallback(
          (status2) => setState((prev) => ({ ...prev, status: status2 })),
          [setState]
        ),
        error,
        handleManual,
        discrepancy,
        selectedItems,
        toggleOpen,
        allExpanded,
        handleCollapseAll,
        handleExpandAll,
        handleJumpToElement,
        handleSelectionChange
      },
      ...props
    }
  );
}, useA11yContext = () => useContext(A11yContext);

// src/components/Report/Report.tsx
import React3 from "react";
import { Badge, Button as Button2, EmptyTabContent } from "storybook/internal/components";
import { ChevronSmallDownIcon } from "@storybook/icons";
import { styled as styled2 } from "storybook/theming";

// src/components/Report/Details.tsx
import React2, { Fragment, useCallback as useCallback2, useState as useState3 } from "react";
import { Button, Link, SyntaxHighlighter } from "storybook/internal/components";
import { CheckIcon, CopyIcon, LocationIcon } from "@storybook/icons";

// ../../../node_modules/@babel/runtime/helpers/esm/extends.js
function _extends() {
  return _extends = Object.assign ? Object.assign.bind() : function(n) {
    for (var e = 1; e < arguments.length; e++) {
      var t = arguments[e];
      for (var r in t) ({}).hasOwnProperty.call(t, r) && (n[r] = t[r]);
    }
    return n;
  }, _extends.apply(null, arguments);
}

// ../../../node_modules/@radix-ui/react-tabs/dist/index.mjs
import { forwardRef as $1IHzk$forwardRef, createElement as $1IHzk$createElement, useRef as $1IHzk$useRef, useEffect as $1IHzk$useEffect } from "react";

// ../../../node_modules/@radix-ui/primitive/dist/index.mjs
function $e42e1063c40fb3ef$export$b9ecd428b558ff10(originalEventHandler, ourEventHandler, { checkForDefaultPrevented = !0 } = {}) {
  return function(event) {
    if (originalEventHandler?.(event), checkForDefaultPrevented === !1 || !event.defaultPrevented) return ourEventHandler?.(event);
  };
}

// ../../../node_modules/@radix-ui/react-context/dist/index.mjs
import { createContext as $3bkAK$createContext, useMemo as $3bkAK$useMemo, createElement as $3bkAK$createElement, useContext as $3bkAK$useContext } from "react";
function $c512c27ab02ef895$export$50c7b4e9d9f19c1(scopeName, createContextScopeDeps = []) {
  let defaultContexts = [];
  function $c512c27ab02ef895$export$fd42f52fd3ae1109(rootComponentName, defaultContext) {
    let BaseContext = $3bkAK$createContext(defaultContext), index = defaultContexts.length;
    defaultContexts = [
      ...defaultContexts,
      defaultContext
    ];
    function Provider(props) {
      let { scope, children, ...context } = props, Context = scope?.[scopeName][index] || BaseContext, value = $3bkAK$useMemo(
        () => context,
        Object.values(context)
      );
      return $3bkAK$createElement(Context.Provider, {
        value
      }, children);
    }
    function useContext2(consumerName, scope) {
      let Context = scope?.[scopeName][index] || BaseContext, context = $3bkAK$useContext(Context);
      if (context) return context;
      if (defaultContext !== void 0) return defaultContext;
      throw new Error(`\`${consumerName}\` must be used within \`${rootComponentName}\``);
    }
    return Provider.displayName = rootComponentName + "Provider", [
      Provider,
      useContext2
    ];
  }
  let createScope = () => {
    let scopeContexts = defaultContexts.map((defaultContext) => $3bkAK$createContext(defaultContext));
    return function(scope) {
      let contexts = scope?.[scopeName] || scopeContexts;
      return $3bkAK$useMemo(
        () => ({
          [`__scope${scopeName}`]: {
            ...scope,
            [scopeName]: contexts
          }
        }),
        [
          scope,
          contexts
        ]
      );
    };
  };
  return createScope.scopeName = scopeName, [
    $c512c27ab02ef895$export$fd42f52fd3ae1109,
    $c512c27ab02ef895$var$composeContextScopes(createScope, ...createContextScopeDeps)
  ];
}
function $c512c27ab02ef895$var$composeContextScopes(...scopes) {
  let baseScope = scopes[0];
  if (scopes.length === 1) return baseScope;
  let createScope1 = () => {
    let scopeHooks = scopes.map(
      (createScope) => ({
        useScope: createScope(),
        scopeName: createScope.scopeName
      })
    );
    return function(overrideScopes) {
      let nextScopes1 = scopeHooks.reduce((nextScopes, { useScope, scopeName }) => {
        let currentScope = useScope(overrideScopes)[`__scope${scopeName}`];
        return {
          ...nextScopes,
          ...currentScope
        };
      }, {});
      return $3bkAK$useMemo(
        () => ({
          [`__scope${baseScope.scopeName}`]: nextScopes1
        }),
        [
          nextScopes1
        ]
      );
    };
  };
  return createScope1.scopeName = baseScope.scopeName, createScope1;
}

// ../../../node_modules/@radix-ui/react-roving-focus/dist/index.mjs
import { forwardRef as $98Iye$forwardRef, createElement as $98Iye$createElement, useRef as $98Iye$useRef, useState as $98Iye$useState, useEffect as $98Iye$useEffect, useCallback as $98Iye$useCallback } from "react";

// ../../../node_modules/@radix-ui/react-collection/dist/index.mjs
import $6vYhU$react from "react";

// ../../../node_modules/@radix-ui/react-compose-refs/dist/index.mjs
import { useCallback as $3vqmr$useCallback } from "react";
function $6ed0406888f73fc4$var$setRef(ref, value) {
  typeof ref == "function" ? ref(value) : ref != null && (ref.current = value);
}
function $6ed0406888f73fc4$export$43e446d32b3d21af(...refs) {
  return (node) => refs.forEach(
    (ref) => $6ed0406888f73fc4$var$setRef(ref, node)
  );
}
function $6ed0406888f73fc4$export$c7b2cbe3552a0d05(...refs) {
  return $3vqmr$useCallback($6ed0406888f73fc4$export$43e446d32b3d21af(...refs), refs);
}

// ../../../node_modules/@radix-ui/react-collection/node_modules/@radix-ui/react-slot/dist/index.mjs
import { forwardRef as $9IrjX$forwardRef, Children as $9IrjX$Children, isValidElement as $9IrjX$isValidElement, createElement as $9IrjX$createElement, cloneElement as $9IrjX$cloneElement, Fragment as $9IrjX$Fragment } from "react";
var $5e63c961fc1ce211$export$8c6ed5c666ac1360 = $9IrjX$forwardRef((props, forwardedRef) => {
  let { children, ...slotProps } = props, childrenArray = $9IrjX$Children.toArray(children), slottable = childrenArray.find($5e63c961fc1ce211$var$isSlottable);
  if (slottable) {
    let newElement = slottable.props.children, newChildren = childrenArray.map((child) => child === slottable ? $9IrjX$Children.count(newElement) > 1 ? $9IrjX$Children.only(null) : $9IrjX$isValidElement(newElement) ? newElement.props.children : null : child);
    return $9IrjX$createElement($5e63c961fc1ce211$var$SlotClone, _extends({}, slotProps, {
      ref: forwardedRef
    }), $9IrjX$isValidElement(newElement) ? $9IrjX$cloneElement(newElement, void 0, newChildren) : null);
  }
  return $9IrjX$createElement($5e63c961fc1ce211$var$SlotClone, _extends({}, slotProps, {
    ref: forwardedRef
  }), children);
});
$5e63c961fc1ce211$export$8c6ed5c666ac1360.displayName = "Slot";
var $5e63c961fc1ce211$var$SlotClone = $9IrjX$forwardRef((props, forwardedRef) => {
  let { children, ...slotProps } = props;
  return $9IrjX$isValidElement(children) ? $9IrjX$cloneElement(children, {
    ...$5e63c961fc1ce211$var$mergeProps(slotProps, children.props),
    ref: forwardedRef ? $6ed0406888f73fc4$export$43e446d32b3d21af(forwardedRef, children.ref) : children.ref
  }) : $9IrjX$Children.count(children) > 1 ? $9IrjX$Children.only(null) : null;
});
$5e63c961fc1ce211$var$SlotClone.displayName = "SlotClone";
var $5e63c961fc1ce211$export$d9f1ccf0bdb05d45 = ({ children }) => $9IrjX$createElement($9IrjX$Fragment, null, children);
function $5e63c961fc1ce211$var$isSlottable(child) {
  return $9IrjX$isValidElement(child) && child.type === $5e63c961fc1ce211$export$d9f1ccf0bdb05d45;
}
function $5e63c961fc1ce211$var$mergeProps(slotProps, childProps) {
  let overrideProps = {
    ...childProps
  };
  for (let propName in childProps) {
    let slotPropValue = slotProps[propName], childPropValue = childProps[propName];
    /^on[A-Z]/.test(propName) ? slotPropValue && childPropValue ? overrideProps[propName] = (...args) => {
      childPropValue(...args), slotPropValue(...args);
    } : slotPropValue && (overrideProps[propName] = slotPropValue) : propName === "style" ? overrideProps[propName] = {
      ...slotPropValue,
      ...childPropValue
    } : propName === "className" && (overrideProps[propName] = [
      slotPropValue,
      childPropValue
    ].filter(Boolean).join(" "));
  }
  return {
    ...slotProps,
    ...overrideProps
  };
}

// ../../../node_modules/@radix-ui/react-collection/dist/index.mjs
function $e02a7d9cb1dc128c$export$c74125a8e3af6bb2(name) {
  let PROVIDER_NAME = name + "CollectionProvider", [createCollectionContext, createCollectionScope] = $c512c27ab02ef895$export$50c7b4e9d9f19c1(PROVIDER_NAME), [CollectionProviderImpl, useCollectionContext] = createCollectionContext(PROVIDER_NAME, {
    collectionRef: {
      current: null
    },
    itemMap: /* @__PURE__ */ new Map()
  }), CollectionProvider = (props) => {
    let { scope, children } = props, ref = $6vYhU$react.useRef(null), itemMap = $6vYhU$react.useRef(/* @__PURE__ */ new Map()).current;
    return $6vYhU$react.createElement(CollectionProviderImpl, {
      scope,
      itemMap,
      collectionRef: ref
    }, children);
  };
  Object.assign(CollectionProvider, {
    displayName: PROVIDER_NAME
  });
  let COLLECTION_SLOT_NAME = name + "CollectionSlot", CollectionSlot = $6vYhU$react.forwardRef((props, forwardedRef) => {
    let { scope, children } = props, context = useCollectionContext(COLLECTION_SLOT_NAME, scope), composedRefs = $6ed0406888f73fc4$export$c7b2cbe3552a0d05(forwardedRef, context.collectionRef);
    return $6vYhU$react.createElement($5e63c961fc1ce211$export$8c6ed5c666ac1360, {
      ref: composedRefs
    }, children);
  });
  Object.assign(CollectionSlot, {
    displayName: COLLECTION_SLOT_NAME
  });
  let ITEM_SLOT_NAME = name + "CollectionItemSlot", ITEM_DATA_ATTR = "data-radix-collection-item", CollectionItemSlot = $6vYhU$react.forwardRef((props, forwardedRef) => {
    let { scope, children, ...itemData } = props, ref = $6vYhU$react.useRef(null), composedRefs = $6ed0406888f73fc4$export$c7b2cbe3552a0d05(forwardedRef, ref), context = useCollectionContext(ITEM_SLOT_NAME, scope);
    return $6vYhU$react.useEffect(() => (context.itemMap.set(ref, {
      ref,
      ...itemData
    }), () => {
      context.itemMap.delete(ref);
    })), $6vYhU$react.createElement($5e63c961fc1ce211$export$8c6ed5c666ac1360, {
      [ITEM_DATA_ATTR]: "",
      ref: composedRefs
    }, children);
  });
  Object.assign(CollectionItemSlot, {
    displayName: ITEM_SLOT_NAME
  });
  function useCollection(scope) {
    let context = useCollectionContext(name + "CollectionConsumer", scope);
    return $6vYhU$react.useCallback(() => {
      let collectionNode = context.collectionRef.current;
      if (!collectionNode) return [];
      let orderedNodes = Array.from(collectionNode.querySelectorAll(`[${ITEM_DATA_ATTR}]`));
      return Array.from(context.itemMap.values()).sort(
        (a, b) => orderedNodes.indexOf(a.ref.current) - orderedNodes.indexOf(b.ref.current)
      );
    }, [
      context.collectionRef,
      context.itemMap
    ]);
  }
  return [
    {
      Provider: CollectionProvider,
      Slot: CollectionSlot,
      ItemSlot: CollectionItemSlot
    },
    useCollection,
    createCollectionScope
  ];
}

// ../../../node_modules/@radix-ui/react-id/dist/index.mjs
import * as $2AODx$react from "react";

// ../../../node_modules/@radix-ui/react-use-layout-effect/dist/index.mjs
import { useLayoutEffect as $dxlwH$useLayoutEffect } from "react";
var $9f79659886946c16$export$e5c5a5f917a5871c = globalThis?.document ? $dxlwH$useLayoutEffect : () => {
};

// ../../../node_modules/@radix-ui/react-id/dist/index.mjs
var $1746a345f3d73bb7$var$useReactId = $2AODx$react.useId || (() => {
}), $1746a345f3d73bb7$var$count = 0;
function $1746a345f3d73bb7$export$f680877a34711e37(deterministicId) {
  let [id, setId] = $2AODx$react.useState($1746a345f3d73bb7$var$useReactId());
  return $9f79659886946c16$export$e5c5a5f917a5871c(() => {
    deterministicId || setId(
      (reactId) => reactId ?? String($1746a345f3d73bb7$var$count++)
    );
  }, [
    deterministicId
  ]), deterministicId || (id ? `radix-${id}` : "");
}

// ../../../node_modules/@radix-ui/react-primitive/dist/index.mjs
import { forwardRef as $4q5Fq$forwardRef, useEffect as $4q5Fq$useEffect, createElement as $4q5Fq$createElement } from "react";
import { flushSync as $4q5Fq$flushSync } from "react-dom";

// ../../../node_modules/@radix-ui/react-primitive/node_modules/@radix-ui/react-slot/dist/index.mjs
import { forwardRef as $9IrjX$forwardRef2, Children as $9IrjX$Children2, isValidElement as $9IrjX$isValidElement2, createElement as $9IrjX$createElement2, cloneElement as $9IrjX$cloneElement2, Fragment as $9IrjX$Fragment2 } from "react";
var $5e63c961fc1ce211$export$8c6ed5c666ac13602 = $9IrjX$forwardRef2((props, forwardedRef) => {
  let { children, ...slotProps } = props, childrenArray = $9IrjX$Children2.toArray(children), slottable = childrenArray.find($5e63c961fc1ce211$var$isSlottable2);
  if (slottable) {
    let newElement = slottable.props.children, newChildren = childrenArray.map((child) => child === slottable ? $9IrjX$Children2.count(newElement) > 1 ? $9IrjX$Children2.only(null) : $9IrjX$isValidElement2(newElement) ? newElement.props.children : null : child);
    return $9IrjX$createElement2($5e63c961fc1ce211$var$SlotClone2, _extends({}, slotProps, {
      ref: forwardedRef
    }), $9IrjX$isValidElement2(newElement) ? $9IrjX$cloneElement2(newElement, void 0, newChildren) : null);
  }
  return $9IrjX$createElement2($5e63c961fc1ce211$var$SlotClone2, _extends({}, slotProps, {
    ref: forwardedRef
  }), children);
});
$5e63c961fc1ce211$export$8c6ed5c666ac13602.displayName = "Slot";
var $5e63c961fc1ce211$var$SlotClone2 = $9IrjX$forwardRef2((props, forwardedRef) => {
  let { children, ...slotProps } = props;
  return $9IrjX$isValidElement2(children) ? $9IrjX$cloneElement2(children, {
    ...$5e63c961fc1ce211$var$mergeProps2(slotProps, children.props),
    ref: forwardedRef ? $6ed0406888f73fc4$export$43e446d32b3d21af(forwardedRef, children.ref) : children.ref
  }) : $9IrjX$Children2.count(children) > 1 ? $9IrjX$Children2.only(null) : null;
});
$5e63c961fc1ce211$var$SlotClone2.displayName = "SlotClone";
var $5e63c961fc1ce211$export$d9f1ccf0bdb05d452 = ({ children }) => $9IrjX$createElement2($9IrjX$Fragment2, null, children);
function $5e63c961fc1ce211$var$isSlottable2(child) {
  return $9IrjX$isValidElement2(child) && child.type === $5e63c961fc1ce211$export$d9f1ccf0bdb05d452;
}
function $5e63c961fc1ce211$var$mergeProps2(slotProps, childProps) {
  let overrideProps = {
    ...childProps
  };
  for (let propName in childProps) {
    let slotPropValue = slotProps[propName], childPropValue = childProps[propName];
    /^on[A-Z]/.test(propName) ? slotPropValue && childPropValue ? overrideProps[propName] = (...args) => {
      childPropValue(...args), slotPropValue(...args);
    } : slotPropValue && (overrideProps[propName] = slotPropValue) : propName === "style" ? overrideProps[propName] = {
      ...slotPropValue,
      ...childPropValue
    } : propName === "className" && (overrideProps[propName] = [
      slotPropValue,
      childPropValue
    ].filter(Boolean).join(" "));
  }
  return {
    ...slotProps,
    ...overrideProps
  };
}

// ../../../node_modules/@radix-ui/react-primitive/dist/index.mjs
var $8927f6f2acc4f386$var$NODES = [
  "a",
  "button",
  "div",
  "form",
  "h2",
  "h3",
  "img",
  "input",
  "label",
  "li",
  "nav",
  "ol",
  "p",
  "span",
  "svg",
  "ul"
], $8927f6f2acc4f386$export$250ffa63cdc0d034 = $8927f6f2acc4f386$var$NODES.reduce((primitive, node) => {
  let Node = $4q5Fq$forwardRef((props, forwardedRef) => {
    let { asChild, ...primitiveProps } = props, Comp = asChild ? $5e63c961fc1ce211$export$8c6ed5c666ac13602 : node;
    return $4q5Fq$useEffect(() => {
      window[/* @__PURE__ */ Symbol.for("radix-ui")] = !0;
    }, []), $4q5Fq$createElement(Comp, _extends({}, primitiveProps, {
      ref: forwardedRef
    }));
  });
  return Node.displayName = `Primitive.${node}`, {
    ...primitive,
    [node]: Node
  };
}, {});

// ../../../node_modules/@radix-ui/react-use-callback-ref/dist/index.mjs
import { useRef as $lwiWj$useRef, useEffect as $lwiWj$useEffect, useMemo as $lwiWj$useMemo } from "react";
function $b1b2314f5f9a1d84$export$25bec8c6f54ee79a(callback) {
  let callbackRef = $lwiWj$useRef(callback);
  return $lwiWj$useEffect(() => {
    callbackRef.current = callback;
  }), $lwiWj$useMemo(
    () => (...args) => {
      var _callbackRef$current;
      return (_callbackRef$current = callbackRef.current) === null || _callbackRef$current === void 0 ? void 0 : _callbackRef$current.call(callbackRef, ...args);
    },
    []
  );
}

// ../../../node_modules/@radix-ui/react-use-controllable-state/dist/index.mjs
import { useCallback as $bnPw9$useCallback, useState as $bnPw9$useState, useRef as $bnPw9$useRef, useEffect as $bnPw9$useEffect } from "react";
function $71cd76cc60e0454e$export$6f32135080cb4c3({ prop, defaultProp, onChange = () => {
} }) {
  let [uncontrolledProp, setUncontrolledProp] = $71cd76cc60e0454e$var$useUncontrolledState({
    defaultProp,
    onChange
  }), isControlled = prop !== void 0, value1 = isControlled ? prop : uncontrolledProp, handleChange = $b1b2314f5f9a1d84$export$25bec8c6f54ee79a(onChange), setValue = $bnPw9$useCallback((nextValue) => {
    if (isControlled) {
      let value = typeof nextValue == "function" ? nextValue(prop) : nextValue;
      value !== prop && handleChange(value);
    } else setUncontrolledProp(nextValue);
  }, [
    isControlled,
    prop,
    setUncontrolledProp,
    handleChange
  ]);
  return [
    value1,
    setValue
  ];
}
function $71cd76cc60e0454e$var$useUncontrolledState({ defaultProp, onChange }) {
  let uncontrolledState = $bnPw9$useState(defaultProp), [value] = uncontrolledState, prevValueRef = $bnPw9$useRef(value), handleChange = $b1b2314f5f9a1d84$export$25bec8c6f54ee79a(onChange);
  return $bnPw9$useEffect(() => {
    prevValueRef.current !== value && (handleChange(value), prevValueRef.current = value);
  }, [
    value,
    prevValueRef,
    handleChange
  ]), uncontrolledState;
}

// ../../../node_modules/@radix-ui/react-direction/dist/index.mjs
import { createContext as $7Gjcd$createContext, createElement as $7Gjcd$createElement, useContext as $7Gjcd$useContext } from "react";
var $f631663db3294ace$var$DirectionContext = $7Gjcd$createContext(void 0);
function $f631663db3294ace$export$b39126d51d94e6f3(localDir) {
  let globalDir = $7Gjcd$useContext($f631663db3294ace$var$DirectionContext);
  return localDir || globalDir || "ltr";
}

// ../../../node_modules/@radix-ui/react-roving-focus/dist/index.mjs
var $d7bdfb9eb0fdf311$var$ENTRY_FOCUS = "rovingFocusGroup.onEntryFocus", $d7bdfb9eb0fdf311$var$EVENT_OPTIONS = {
  bubbles: !1,
  cancelable: !0
}, $d7bdfb9eb0fdf311$var$GROUP_NAME = "RovingFocusGroup", [$d7bdfb9eb0fdf311$var$Collection, $d7bdfb9eb0fdf311$var$useCollection, $d7bdfb9eb0fdf311$var$createCollectionScope] = $e02a7d9cb1dc128c$export$c74125a8e3af6bb2($d7bdfb9eb0fdf311$var$GROUP_NAME), [$d7bdfb9eb0fdf311$var$createRovingFocusGroupContext, $d7bdfb9eb0fdf311$export$c7109489551a4f4] = $c512c27ab02ef895$export$50c7b4e9d9f19c1($d7bdfb9eb0fdf311$var$GROUP_NAME, [
  $d7bdfb9eb0fdf311$var$createCollectionScope
]), [$d7bdfb9eb0fdf311$var$RovingFocusProvider, $d7bdfb9eb0fdf311$var$useRovingFocusContext] = $d7bdfb9eb0fdf311$var$createRovingFocusGroupContext($d7bdfb9eb0fdf311$var$GROUP_NAME), $d7bdfb9eb0fdf311$export$8699f7c8af148338 = $98Iye$forwardRef((props, forwardedRef) => $98Iye$createElement($d7bdfb9eb0fdf311$var$Collection.Provider, {
  scope: props.__scopeRovingFocusGroup
}, $98Iye$createElement($d7bdfb9eb0fdf311$var$Collection.Slot, {
  scope: props.__scopeRovingFocusGroup
}, $98Iye$createElement($d7bdfb9eb0fdf311$var$RovingFocusGroupImpl, _extends({}, props, {
  ref: forwardedRef
})))));
Object.assign($d7bdfb9eb0fdf311$export$8699f7c8af148338, {
  displayName: $d7bdfb9eb0fdf311$var$GROUP_NAME
});
var $d7bdfb9eb0fdf311$var$RovingFocusGroupImpl = $98Iye$forwardRef((props, forwardedRef) => {
  let { __scopeRovingFocusGroup, orientation, loop = !1, dir, currentTabStopId: currentTabStopIdProp, defaultCurrentTabStopId, onCurrentTabStopIdChange, onEntryFocus, ...groupProps } = props, ref = $98Iye$useRef(null), composedRefs = $6ed0406888f73fc4$export$c7b2cbe3552a0d05(forwardedRef, ref), direction = $f631663db3294ace$export$b39126d51d94e6f3(dir), [currentTabStopId = null, setCurrentTabStopId] = $71cd76cc60e0454e$export$6f32135080cb4c3({
    prop: currentTabStopIdProp,
    defaultProp: defaultCurrentTabStopId,
    onChange: onCurrentTabStopIdChange
  }), [isTabbingBackOut, setIsTabbingBackOut] = $98Iye$useState(!1), handleEntryFocus = $b1b2314f5f9a1d84$export$25bec8c6f54ee79a(onEntryFocus), getItems = $d7bdfb9eb0fdf311$var$useCollection(__scopeRovingFocusGroup), isClickFocusRef = $98Iye$useRef(!1), [focusableItemsCount, setFocusableItemsCount] = $98Iye$useState(0);
  return $98Iye$useEffect(() => {
    let node = ref.current;
    if (node)
      return node.addEventListener($d7bdfb9eb0fdf311$var$ENTRY_FOCUS, handleEntryFocus), () => node.removeEventListener($d7bdfb9eb0fdf311$var$ENTRY_FOCUS, handleEntryFocus);
  }, [
    handleEntryFocus
  ]), $98Iye$createElement($d7bdfb9eb0fdf311$var$RovingFocusProvider, {
    scope: __scopeRovingFocusGroup,
    orientation,
    dir: direction,
    loop,
    currentTabStopId,
    onItemFocus: $98Iye$useCallback(
      (tabStopId) => setCurrentTabStopId(tabStopId),
      [
        setCurrentTabStopId
      ]
    ),
    onItemShiftTab: $98Iye$useCallback(
      () => setIsTabbingBackOut(!0),
      []
    ),
    onFocusableItemAdd: $98Iye$useCallback(
      () => setFocusableItemsCount(
        (prevCount) => prevCount + 1
      ),
      []
    ),
    onFocusableItemRemove: $98Iye$useCallback(
      () => setFocusableItemsCount(
        (prevCount) => prevCount - 1
      ),
      []
    )
  }, $98Iye$createElement($8927f6f2acc4f386$export$250ffa63cdc0d034.div, _extends({
    tabIndex: isTabbingBackOut || focusableItemsCount === 0 ? -1 : 0,
    "data-orientation": orientation
  }, groupProps, {
    ref: composedRefs,
    style: {
      outline: "none",
      ...props.style
    },
    onMouseDown: $e42e1063c40fb3ef$export$b9ecd428b558ff10(props.onMouseDown, () => {
      isClickFocusRef.current = !0;
    }),
    onFocus: $e42e1063c40fb3ef$export$b9ecd428b558ff10(props.onFocus, (event) => {
      let isKeyboardFocus = !isClickFocusRef.current;
      if (event.target === event.currentTarget && isKeyboardFocus && !isTabbingBackOut) {
        let entryFocusEvent = new CustomEvent($d7bdfb9eb0fdf311$var$ENTRY_FOCUS, $d7bdfb9eb0fdf311$var$EVENT_OPTIONS);
        if (event.currentTarget.dispatchEvent(entryFocusEvent), !entryFocusEvent.defaultPrevented) {
          let items = getItems().filter(
            (item) => item.focusable
          ), activeItem = items.find(
            (item) => item.active
          ), currentItem = items.find(
            (item) => item.id === currentTabStopId
          ), candidateNodes = [
            activeItem,
            currentItem,
            ...items
          ].filter(Boolean).map(
            (item) => item.ref.current
          );
          $d7bdfb9eb0fdf311$var$focusFirst(candidateNodes);
        }
      }
      isClickFocusRef.current = !1;
    }),
    onBlur: $e42e1063c40fb3ef$export$b9ecd428b558ff10(
      props.onBlur,
      () => setIsTabbingBackOut(!1)
    )
  })));
}), $d7bdfb9eb0fdf311$var$ITEM_NAME = "RovingFocusGroupItem", $d7bdfb9eb0fdf311$export$ab9df7c53fe8454 = $98Iye$forwardRef((props, forwardedRef) => {
  let { __scopeRovingFocusGroup, focusable = !0, active = !1, tabStopId, ...itemProps } = props, autoId = $1746a345f3d73bb7$export$f680877a34711e37(), id = tabStopId || autoId, context = $d7bdfb9eb0fdf311$var$useRovingFocusContext($d7bdfb9eb0fdf311$var$ITEM_NAME, __scopeRovingFocusGroup), isCurrentTabStop = context.currentTabStopId === id, getItems = $d7bdfb9eb0fdf311$var$useCollection(__scopeRovingFocusGroup), { onFocusableItemAdd, onFocusableItemRemove } = context;
  return $98Iye$useEffect(() => {
    if (focusable)
      return onFocusableItemAdd(), () => onFocusableItemRemove();
  }, [
    focusable,
    onFocusableItemAdd,
    onFocusableItemRemove
  ]), $98Iye$createElement($d7bdfb9eb0fdf311$var$Collection.ItemSlot, {
    scope: __scopeRovingFocusGroup,
    id,
    focusable,
    active
  }, $98Iye$createElement($8927f6f2acc4f386$export$250ffa63cdc0d034.span, _extends({
    tabIndex: isCurrentTabStop ? 0 : -1,
    "data-orientation": context.orientation
  }, itemProps, {
    ref: forwardedRef,
    onMouseDown: $e42e1063c40fb3ef$export$b9ecd428b558ff10(props.onMouseDown, (event) => {
      focusable ? context.onItemFocus(id) : event.preventDefault();
    }),
    onFocus: $e42e1063c40fb3ef$export$b9ecd428b558ff10(
      props.onFocus,
      () => context.onItemFocus(id)
    ),
    onKeyDown: $e42e1063c40fb3ef$export$b9ecd428b558ff10(props.onKeyDown, (event) => {
      if (event.key === "Tab" && event.shiftKey) {
        context.onItemShiftTab();
        return;
      }
      if (event.target !== event.currentTarget) return;
      let focusIntent = $d7bdfb9eb0fdf311$var$getFocusIntent(event, context.orientation, context.dir);
      if (focusIntent !== void 0) {
        event.preventDefault();
        let candidateNodes = getItems().filter(
          (item) => item.focusable
        ).map(
          (item) => item.ref.current
        );
        if (focusIntent === "last") candidateNodes.reverse();
        else if (focusIntent === "prev" || focusIntent === "next") {
          focusIntent === "prev" && candidateNodes.reverse();
          let currentIndex = candidateNodes.indexOf(event.currentTarget);
          candidateNodes = context.loop ? $d7bdfb9eb0fdf311$var$wrapArray(candidateNodes, currentIndex + 1) : candidateNodes.slice(currentIndex + 1);
        }
        setTimeout(
          () => $d7bdfb9eb0fdf311$var$focusFirst(candidateNodes)
        );
      }
    })
  })));
});
Object.assign($d7bdfb9eb0fdf311$export$ab9df7c53fe8454, {
  displayName: $d7bdfb9eb0fdf311$var$ITEM_NAME
});
var $d7bdfb9eb0fdf311$var$MAP_KEY_TO_FOCUS_INTENT = {
  ArrowLeft: "prev",
  ArrowUp: "prev",
  ArrowRight: "next",
  ArrowDown: "next",
  PageUp: "first",
  Home: "first",
  PageDown: "last",
  End: "last"
};
function $d7bdfb9eb0fdf311$var$getDirectionAwareKey(key, dir) {
  return dir !== "rtl" ? key : key === "ArrowLeft" ? "ArrowRight" : key === "ArrowRight" ? "ArrowLeft" : key;
}
function $d7bdfb9eb0fdf311$var$getFocusIntent(event, orientation, dir) {
  let key = $d7bdfb9eb0fdf311$var$getDirectionAwareKey(event.key, dir);
  if (!(orientation === "vertical" && [
    "ArrowLeft",
    "ArrowRight"
  ].includes(key)) && !(orientation === "horizontal" && [
    "ArrowUp",
    "ArrowDown"
  ].includes(key)))
    return $d7bdfb9eb0fdf311$var$MAP_KEY_TO_FOCUS_INTENT[key];
}
function $d7bdfb9eb0fdf311$var$focusFirst(candidates) {
  let PREVIOUSLY_FOCUSED_ELEMENT = document.activeElement;
  for (let candidate of candidates)
    if (candidate === PREVIOUSLY_FOCUSED_ELEMENT || (candidate.focus(), document.activeElement !== PREVIOUSLY_FOCUSED_ELEMENT)) return;
}
function $d7bdfb9eb0fdf311$var$wrapArray(array, startIndex) {
  return array.map(
    (_, index) => array[(startIndex + index) % array.length]
  );
}
var $d7bdfb9eb0fdf311$export$be92b6f5f03c0fe9 = $d7bdfb9eb0fdf311$export$8699f7c8af148338, $d7bdfb9eb0fdf311$export$6d08773d2e66f8f2 = $d7bdfb9eb0fdf311$export$ab9df7c53fe8454;

// ../../../node_modules/@radix-ui/react-presence/dist/index.mjs
import { Children as $iqq3r$Children, cloneElement as $iqq3r$cloneElement, useState as $iqq3r$useState, useRef as $iqq3r$useRef, useEffect as $iqq3r$useEffect, useCallback as $iqq3r$useCallback, useReducer as $iqq3r$useReducer } from "react";
import { flushSync as $iqq3r$flushSync } from "react-dom";
function $fe963b355347cc68$export$3e6543de14f8614f(initialState, machine) {
  return $iqq3r$useReducer((state, event) => {
    let nextState = machine[state][event];
    return nextState ?? state;
  }, initialState);
}
var $921a889cee6df7e8$export$99c2b779aa4e8b8b = (props) => {
  let { present, children } = props, presence = $921a889cee6df7e8$var$usePresence(present), child = typeof children == "function" ? children({
    present: presence.isPresent
  }) : $iqq3r$Children.only(children), ref = $6ed0406888f73fc4$export$c7b2cbe3552a0d05(presence.ref, child.ref);
  return typeof children == "function" || presence.isPresent ? $iqq3r$cloneElement(child, {
    ref
  }) : null;
};
$921a889cee6df7e8$export$99c2b779aa4e8b8b.displayName = "Presence";
function $921a889cee6df7e8$var$usePresence(present) {
  let [node1, setNode] = $iqq3r$useState(), stylesRef = $iqq3r$useRef({}), prevPresentRef = $iqq3r$useRef(present), prevAnimationNameRef = $iqq3r$useRef("none"), initialState = present ? "mounted" : "unmounted", [state, send] = $fe963b355347cc68$export$3e6543de14f8614f(initialState, {
    mounted: {
      UNMOUNT: "unmounted",
      ANIMATION_OUT: "unmountSuspended"
    },
    unmountSuspended: {
      MOUNT: "mounted",
      ANIMATION_END: "unmounted"
    },
    unmounted: {
      MOUNT: "mounted"
    }
  });
  return $iqq3r$useEffect(() => {
    let currentAnimationName = $921a889cee6df7e8$var$getAnimationName(stylesRef.current);
    prevAnimationNameRef.current = state === "mounted" ? currentAnimationName : "none";
  }, [
    state
  ]), $9f79659886946c16$export$e5c5a5f917a5871c(() => {
    let styles = stylesRef.current, wasPresent = prevPresentRef.current;
    if (wasPresent !== present) {
      let prevAnimationName = prevAnimationNameRef.current, currentAnimationName = $921a889cee6df7e8$var$getAnimationName(styles);
      present ? send("MOUNT") : currentAnimationName === "none" || styles?.display === "none" ? send("UNMOUNT") : send(wasPresent && prevAnimationName !== currentAnimationName ? "ANIMATION_OUT" : "UNMOUNT"), prevPresentRef.current = present;
    }
  }, [
    present,
    send
  ]), $9f79659886946c16$export$e5c5a5f917a5871c(() => {
    if (node1) {
      let handleAnimationEnd = (event) => {
        let isCurrentAnimation = $921a889cee6df7e8$var$getAnimationName(stylesRef.current).includes(event.animationName);
        event.target === node1 && isCurrentAnimation && $iqq3r$flushSync(
          () => send("ANIMATION_END")
        );
      }, handleAnimationStart = (event) => {
        event.target === node1 && (prevAnimationNameRef.current = $921a889cee6df7e8$var$getAnimationName(stylesRef.current));
      };
      return node1.addEventListener("animationstart", handleAnimationStart), node1.addEventListener("animationcancel", handleAnimationEnd), node1.addEventListener("animationend", handleAnimationEnd), () => {
        node1.removeEventListener("animationstart", handleAnimationStart), node1.removeEventListener("animationcancel", handleAnimationEnd), node1.removeEventListener("animationend", handleAnimationEnd);
      };
    } else
      send("ANIMATION_END");
  }, [
    node1,
    send
  ]), {
    isPresent: [
      "mounted",
      "unmountSuspended"
    ].includes(state),
    ref: $iqq3r$useCallback((node) => {
      node && (stylesRef.current = getComputedStyle(node)), setNode(node);
    }, [])
  };
}
function $921a889cee6df7e8$var$getAnimationName(styles) {
  return styles?.animationName || "none";
}

// ../../../node_modules/@radix-ui/react-tabs/dist/index.mjs
var $69cb30bb0017df05$var$TABS_NAME = "Tabs", [$69cb30bb0017df05$var$createTabsContext, $69cb30bb0017df05$export$355f5bd209d7b13a] = $c512c27ab02ef895$export$50c7b4e9d9f19c1($69cb30bb0017df05$var$TABS_NAME, [
  $d7bdfb9eb0fdf311$export$c7109489551a4f4
]), $69cb30bb0017df05$var$useRovingFocusGroupScope = $d7bdfb9eb0fdf311$export$c7109489551a4f4(), [$69cb30bb0017df05$var$TabsProvider, $69cb30bb0017df05$var$useTabsContext] = $69cb30bb0017df05$var$createTabsContext($69cb30bb0017df05$var$TABS_NAME), $69cb30bb0017df05$export$b2539bed5023c21c = $1IHzk$forwardRef((props, forwardedRef) => {
  let { __scopeTabs, value: valueProp, onValueChange, defaultValue, orientation = "horizontal", dir, activationMode = "automatic", ...tabsProps } = props, direction = $f631663db3294ace$export$b39126d51d94e6f3(dir), [value, setValue] = $71cd76cc60e0454e$export$6f32135080cb4c3({
    prop: valueProp,
    onChange: onValueChange,
    defaultProp: defaultValue
  });
  return $1IHzk$createElement($69cb30bb0017df05$var$TabsProvider, {
    scope: __scopeTabs,
    baseId: $1746a345f3d73bb7$export$f680877a34711e37(),
    value,
    onValueChange: setValue,
    orientation,
    dir: direction,
    activationMode
  }, $1IHzk$createElement($8927f6f2acc4f386$export$250ffa63cdc0d034.div, _extends({
    dir: direction,
    "data-orientation": orientation
  }, tabsProps, {
    ref: forwardedRef
  })));
});
Object.assign($69cb30bb0017df05$export$b2539bed5023c21c, {
  displayName: $69cb30bb0017df05$var$TABS_NAME
});
var $69cb30bb0017df05$var$TAB_LIST_NAME = "TabsList", $69cb30bb0017df05$export$9712d22edc0d78c1 = $1IHzk$forwardRef((props, forwardedRef) => {
  let { __scopeTabs, loop = !0, ...listProps } = props, context = $69cb30bb0017df05$var$useTabsContext($69cb30bb0017df05$var$TAB_LIST_NAME, __scopeTabs), rovingFocusGroupScope = $69cb30bb0017df05$var$useRovingFocusGroupScope(__scopeTabs);
  return $1IHzk$createElement($d7bdfb9eb0fdf311$export$be92b6f5f03c0fe9, _extends({
    asChild: !0
  }, rovingFocusGroupScope, {
    orientation: context.orientation,
    dir: context.dir,
    loop
  }), $1IHzk$createElement($8927f6f2acc4f386$export$250ffa63cdc0d034.div, _extends({
    role: "tablist",
    "aria-orientation": context.orientation
  }, listProps, {
    ref: forwardedRef
  })));
});
Object.assign($69cb30bb0017df05$export$9712d22edc0d78c1, {
  displayName: $69cb30bb0017df05$var$TAB_LIST_NAME
});
var $69cb30bb0017df05$var$TRIGGER_NAME = "TabsTrigger", $69cb30bb0017df05$export$8114b9fdfdf9f3ba = $1IHzk$forwardRef((props, forwardedRef) => {
  let { __scopeTabs, value, disabled = !1, ...triggerProps } = props, context = $69cb30bb0017df05$var$useTabsContext($69cb30bb0017df05$var$TRIGGER_NAME, __scopeTabs), rovingFocusGroupScope = $69cb30bb0017df05$var$useRovingFocusGroupScope(__scopeTabs), triggerId = $69cb30bb0017df05$var$makeTriggerId(context.baseId, value), contentId = $69cb30bb0017df05$var$makeContentId(context.baseId, value), isSelected = value === context.value;
  return $1IHzk$createElement($d7bdfb9eb0fdf311$export$6d08773d2e66f8f2, _extends({
    asChild: !0
  }, rovingFocusGroupScope, {
    focusable: !disabled,
    active: isSelected
  }), $1IHzk$createElement($8927f6f2acc4f386$export$250ffa63cdc0d034.button, _extends({
    type: "button",
    role: "tab",
    "aria-selected": isSelected,
    "aria-controls": contentId,
    "data-state": isSelected ? "active" : "inactive",
    "data-disabled": disabled ? "" : void 0,
    disabled,
    id: triggerId
  }, triggerProps, {
    ref: forwardedRef,
    onMouseDown: $e42e1063c40fb3ef$export$b9ecd428b558ff10(props.onMouseDown, (event) => {
      !disabled && event.button === 0 && event.ctrlKey === !1 ? context.onValueChange(value) : event.preventDefault();
    }),
    onKeyDown: $e42e1063c40fb3ef$export$b9ecd428b558ff10(props.onKeyDown, (event) => {
      [
        " ",
        "Enter"
      ].includes(event.key) && context.onValueChange(value);
    }),
    onFocus: $e42e1063c40fb3ef$export$b9ecd428b558ff10(props.onFocus, () => {
      let isAutomaticActivation = context.activationMode !== "manual";
      !isSelected && !disabled && isAutomaticActivation && context.onValueChange(value);
    })
  })));
});
Object.assign($69cb30bb0017df05$export$8114b9fdfdf9f3ba, {
  displayName: $69cb30bb0017df05$var$TRIGGER_NAME
});
var $69cb30bb0017df05$var$CONTENT_NAME = "TabsContent", $69cb30bb0017df05$export$bd905d70e8fd2ebb = $1IHzk$forwardRef((props, forwardedRef) => {
  let { __scopeTabs, value, forceMount, children, ...contentProps } = props, context = $69cb30bb0017df05$var$useTabsContext($69cb30bb0017df05$var$CONTENT_NAME, __scopeTabs), triggerId = $69cb30bb0017df05$var$makeTriggerId(context.baseId, value), contentId = $69cb30bb0017df05$var$makeContentId(context.baseId, value), isSelected = value === context.value, isMountAnimationPreventedRef = $1IHzk$useRef(isSelected);
  return $1IHzk$useEffect(() => {
    let rAF = requestAnimationFrame(
      () => isMountAnimationPreventedRef.current = !1
    );
    return () => cancelAnimationFrame(rAF);
  }, []), $1IHzk$createElement(
    $921a889cee6df7e8$export$99c2b779aa4e8b8b,
    {
      present: forceMount || isSelected
    },
    ({ present }) => $1IHzk$createElement($8927f6f2acc4f386$export$250ffa63cdc0d034.div, _extends({
      "data-state": isSelected ? "active" : "inactive",
      "data-orientation": context.orientation,
      role: "tabpanel",
      "aria-labelledby": triggerId,
      hidden: !present,
      id: contentId,
      tabIndex: 0
    }, contentProps, {
      ref: forwardedRef,
      style: {
        ...props.style,
        animationDuration: isMountAnimationPreventedRef.current ? "0s" : void 0
      }
    }), present && children)
  );
});
Object.assign($69cb30bb0017df05$export$bd905d70e8fd2ebb, {
  displayName: $69cb30bb0017df05$var$CONTENT_NAME
});
function $69cb30bb0017df05$var$makeTriggerId(baseId, value) {
  return `${baseId}-trigger-${value}`;
}
function $69cb30bb0017df05$var$makeContentId(baseId, value) {
  return `${baseId}-content-${value}`;
}
var $69cb30bb0017df05$export$be92b6f5f03c0fe9 = $69cb30bb0017df05$export$b2539bed5023c21c, $69cb30bb0017df05$export$54c2e3dc7acea9f5 = $69cb30bb0017df05$export$9712d22edc0d78c1, $69cb30bb0017df05$export$41fb9f06171c75f4 = $69cb30bb0017df05$export$8114b9fdfdf9f3ba, $69cb30bb0017df05$export$7c6e2c02157bb7d2 = $69cb30bb0017df05$export$bd905d70e8fd2ebb;

// src/components/Report/Details.tsx
import { styled } from "storybook/theming";
var StyledSyntaxHighlighter = styled(SyntaxHighlighter)(
  ({ theme: theme2 }) => ({
    fontSize: theme2.typography.size.s1
  }),
  ({ language }) => (
    // We appended ' {}' to the selector in order to get proper syntax highlighting. This rule hides the last 3 spans
    // (one character each) in the displayed output. Only siblings of .selector (the actual CSS selector characters)
    // are targeted so that the code comment line isn't affected.
    language === "css" && {
      ".selector ~ span:nth-last-of-type(-n+3)": {
        display: "none"
      }
    }
  )
), Info = styled.div({
  display: "flex",
  flexDirection: "column"
}), RuleId = styled.div(({ theme: theme2 }) => ({
  display: "block",
  color: theme2.textMutedColor,
  fontFamily: theme2.typography.fonts.mono,
  fontSize: theme2.typography.size.s1,
  marginTop: -8,
  marginBottom: 12,
  "@container (min-width: 800px)": {
    display: "none"
  }
})), Description = styled.p({
  margin: 0
}), Wrapper = styled.div({
  display: "flex",
  flexDirection: "column",
  padding: "0 15px 20px 15px",
  gap: 20
}), Columns = styled.div({
  gap: 15,
  "@container (min-width: 800px)": {
    display: "grid",
    gridTemplateColumns: "50% 50%"
  }
}), Content = styled.div(({ theme: theme2, side }) => ({
  display: side === "left" ? "flex" : "none",
  flexDirection: "column",
  gap: 15,
  margin: side === "left" ? "15px 0" : 0,
  padding: side === "left" ? "0 15px" : 0,
  borderLeft: side === "left" ? `1px solid ${theme2.color.border}` : "none",
  "&:focus-visible": {
    outline: "none",
    borderRadius: 4,
    boxShadow: `0 0 0 1px inset ${theme2.color.secondary}`
  },
  "@container (min-width: 800px)": {
    display: side === "left" ? "none" : "flex"
  }
})), Item = styled(Button)(({ theme: theme2 }) => ({
  fontFamily: theme2.typography.fonts.mono,
  fontWeight: theme2.typography.weight.regular,
  color: theme2.textMutedColor,
  height: 40,
  overflow: "hidden",
  textOverflow: "ellipsis",
  whiteSpace: "nowrap",
  display: "block",
  width: "100%",
  textAlign: "left",
  padding: "0 12px",
  '&[data-state="active"]': {
    color: theme2.color.secondary,
    backgroundColor: theme2.background.hoverable
  }
})), Messages = styled.div({
  display: "flex",
  flexDirection: "column",
  gap: 10
}), Actions = styled.div({
  display: "flex",
  gap: 10
}), CopyButton = ({ onClick }) => {
  let [copied, setCopied] = useState3(!1), handleClick = useCallback2(() => {
    onClick(), setCopied(!0);
    let timeout = setTimeout(() => setCopied(!1), 2e3);
    return () => clearTimeout(timeout);
  }, [onClick]);
  return React2.createElement(Button, { ariaLabel: !1, onClick: handleClick }, copied ? React2.createElement(CheckIcon, null) : React2.createElement(CopyIcon, null), " ", copied ? "Copied" : "Copy link");
}, Details = ({ id, item, type, selection, handleSelectionChange }) => React2.createElement(Wrapper, { id }, React2.createElement(Info, null, React2.createElement(RuleId, null, item.id), React2.createElement(Description, null, getFriendlySummaryForAxeResult(item), " ", React2.createElement(Link, { href: item.helpUrl, target: "_blank", rel: "noopener noreferrer", withArrow: !0 }, "Learn how to resolve this violation"))), React2.createElement(
  $69cb30bb0017df05$export$be92b6f5f03c0fe9,
  {
    defaultValue: selection,
    orientation: "vertical",
    value: selection,
    onValueChange: handleSelectionChange,
    asChild: !0
  },
  React2.createElement(Columns, null, React2.createElement($69cb30bb0017df05$export$54c2e3dc7acea9f5, { "aria-label": type }, item.nodes.map((node, index) => {
    let key = `${type}.${item.id}.${index + 1}`;
    return React2.createElement(Fragment, { key }, React2.createElement($69cb30bb0017df05$export$41fb9f06171c75f4, { value: key, asChild: !0 }, React2.createElement(Item, { ariaLabel: !1, variant: "ghost", size: "medium", id: key }, index + 1, ". ", node.html)), React2.createElement($69cb30bb0017df05$export$7c6e2c02157bb7d2, { value: key, asChild: !0 }, React2.createElement(Content, { side: "left" }, getContent(node))));
  })), item.nodes.map((node, index) => {
    let key = `${type}.${item.id}.${index + 1}`;
    return React2.createElement($69cb30bb0017df05$export$7c6e2c02157bb7d2, { key, value: key, asChild: !0 }, React2.createElement(Content, { side: "right" }, getContent(node)));
  }))
));
function getContent(node) {
  let { handleCopyLink, handleJumpToElement } = useA11yContext(), { any, all, none, html, target } = node, rules = [...any, ...all, ...none];
  return React2.createElement(React2.Fragment, null, React2.createElement(Messages, null, rules.map((rule) => React2.createElement("div", { key: rule.id }, `${rule.message}${/(\.|: [^.]+\.*)$/.test(rule.message) ? "" : "."}`))), React2.createElement(Actions, null, React2.createElement(Button, { ariaLabel: !1, onClick: () => handleJumpToElement(node.target.toString()) }, React2.createElement(LocationIcon, null), " Jump to element"), React2.createElement(CopyButton, { onClick: () => handleCopyLink(node.linkPath) })), React2.createElement(
    StyledSyntaxHighlighter,
    {
      language: "jsx",
      wrapLongLines: !0
    },
    `/* element */
${html}`
  ), React2.createElement(
    StyledSyntaxHighlighter,
    {
      language: "css",
      wrapLongLines: !0
    },
    `/* selector */
${target} {}`
  ));
}

// src/components/Report/Report.tsx
var impactStatus = {
  minor: "neutral",
  moderate: "warning",
  serious: "negative",
  critical: "critical"
}, impactLabels = {
  minor: "Minor",
  moderate: "Moderate",
  serious: "Serious",
  critical: "Critical"
}, Wrapper2 = styled2.div(({ theme: theme2 }) => ({
  display: "flex",
  flexDirection: "column",
  width: "100%",
  borderBottom: `1px solid ${theme2.appBorderColor}`,
  containerType: "inline-size",
  fontSize: theme2.typography.size.s2
})), Icon = styled2(ChevronSmallDownIcon)({
  transition: "transform 0.1s ease-in-out"
}), HeaderBar = styled2.div(({ theme: theme2 }) => ({
  display: "flex",
  justifyContent: "space-between",
  alignItems: "center",
  gap: 6,
  padding: "6px 10px 6px 15px",
  minHeight: 40,
  background: "none",
  color: "inherit",
  textAlign: "left",
  cursor: "pointer",
  width: "100%",
  "&:hover": {
    color: theme2.color.secondary
  }
})), Title = styled2.div(({ theme: theme2 }) => ({
  display: "flex",
  alignItems: "baseline",
  flexGrow: 1,
  fontSize: theme2.typography.size.s2,
  gap: 8
})), RuleId2 = styled2.div(({ theme: theme2 }) => ({
  display: "none",
  color: theme2.textMutedColor,
  fontFamily: theme2.typography.fonts.mono,
  fontSize: theme2.typography.size.s1,
  "@container (min-width: 800px)": {
    display: "block"
  }
})), Count = styled2.div(({ theme: theme2 }) => ({
  display: "flex",
  alignItems: "center",
  justifyContent: "center",
  color: theme2.textMutedColor,
  width: 28,
  height: 28
})), Report = ({
  items,
  empty,
  type,
  handleSelectionChange,
  selectedItems,
  toggleOpen
}) => React3.createElement(React3.Fragment, null, items && items.length ? items.map((item) => {
  let id = `${type}.${item.id}`, detailsId = `details:${id}`, selection = selectedItems.get(id), title = getTitleForAxeResult(item);
  return React3.createElement(Wrapper2, { key: id }, React3.createElement(HeaderBar, { onClick: (event) => toggleOpen(event, type, item), "data-active": !!selection }, React3.createElement(Title, null, React3.createElement("strong", null, title), React3.createElement(RuleId2, null, item.id)), item.impact && React3.createElement(Badge, { status: type === RuleType.PASS ? "neutral" : impactStatus[item.impact] }, impactLabels[item.impact]), React3.createElement(Count, null, item.nodes.length), React3.createElement(
    Button2,
    {
      onClick: (event) => toggleOpen(event, type, item),
      ariaLabel: `${selection ? "Collapse" : "Expand"} details for: ${title}`,
      "aria-expanded": !!selection,
      "aria-controls": detailsId,
      variant: "ghost",
      padding: "small"
    },
    React3.createElement(Icon, { style: { transform: `rotate(${selection ? -180 : 0}deg)` } })
  )), selection ? React3.createElement(
    Details,
    {
      id: detailsId,
      item,
      type,
      selection,
      handleSelectionChange
    }
  ) : React3.createElement("div", { id: detailsId }));
}) : React3.createElement(EmptyTabContent, { title: empty }));

// src/components/Tabs.tsx
import * as React4 from "react";
import { Button as Button3, TabsView } from "storybook/internal/components";
import { CollapseIcon, ExpandAltIcon, EyeCloseIcon, EyeIcon, SyncIcon } from "@storybook/icons";
import { styled as styled3, useTheme } from "storybook/theming";
var Container = styled3.div({
  width: "100%",
  position: "relative",
  height: "100%",
  overflow: "hidden",
  display: "flex",
  flexDirection: "column"
}), ActionsWrapper = styled3.div({
  display: "flex",
  justifyContent: "flex-end",
  gap: 6
}), Tabs = ({ tabs }) => {
  let {
    tab,
    setTab,
    toggleHighlight,
    highlighted,
    handleManual,
    allExpanded,
    handleCollapseAll,
    handleExpandAll
  } = useA11yContext(), theme2 = useTheme();
  return React4.createElement(Container, null, React4.createElement(
    TabsView,
    {
      backgroundColor: theme2.background.app,
      panelProps: { hasScrollbar: !0 },
      tabs: tabs.map((tab2) => ({
        id: tab2.type,
        title: tab2.label,
        children: tab2.panel
      })),
      selected: tab,
      onSelectionChange: (key) => setTab(key),
      tools: React4.createElement(ActionsWrapper, null, React4.createElement(
        Button3,
        {
          variant: "ghost",
          padding: "small",
          onClick: toggleHighlight,
          ariaLabel: highlighted ? "Hide accessibility test result highlights" : "Highlight elements with accessibility test results"
        },
        highlighted ? React4.createElement(EyeCloseIcon, null) : React4.createElement(EyeIcon, null)
      ), React4.createElement(
        Button3,
        {
          variant: "ghost",
          padding: "small",
          onClick: allExpanded ? handleCollapseAll : handleExpandAll,
          ariaLabel: allExpanded ? "Collapse all results" : "Expand all results",
          "aria-expanded": allExpanded
        },
        allExpanded ? React4.createElement(CollapseIcon, null) : React4.createElement(ExpandAltIcon, null)
      ), React4.createElement(
        Button3,
        {
          variant: "ghost",
          padding: "small",
          onClick: handleManual,
          ariaLabel: "Rerun accessibility scan"
        },
        React4.createElement(SyncIcon, null)
      ))
    }
  ));
};

// src/components/TestDiscrepancyMessage.tsx
import React5, { useMemo as useMemo2 } from "react";
import { Link as Link2 } from "storybook/internal/components";
import { useStorybookApi as useStorybookApi2 } from "storybook/manager-api";
import { styled as styled4 } from "storybook/theming";
var Wrapper3 = styled4.div(({ theme: { color, typography, background } }) => ({
  textAlign: "start",
  padding: "11px 15px",
  fontSize: `${typography.size.s2}px`,
  fontWeight: typography.weight.regular,
  lineHeight: "1rem",
  background: background.app,
  borderBottom: `1px solid ${color.border}`,
  color: color.defaultText,
  backgroundClip: "padding-box",
  position: "relative",
  code: {
    fontSize: `${typography.size.s1 - 1}px`,
    color: "inherit",
    margin: "0 0.2em",
    padding: "0 0.2em",
    background: "rgba(255, 255, 255, 0.8)",
    borderRadius: "2px",
    boxShadow: "0 0 0 1px rgba(0, 0, 0, 0.1)"
  }
})), TestDiscrepancyMessage = ({ discrepancy }) => {
  let docsUrl = useStorybookApi2().getDocsUrl({
    subpath: DOCUMENTATION_DISCREPANCY_LINK,
    versioned: !0,
    renderer: !0
  }), message = useMemo2(() => {
    switch (discrepancy) {
      case "browserPassedCliFailed":
        return "Accessibility checks passed in this browser but failed in the CLI.";
      case "cliPassedBrowserFailed":
        return "Accessibility checks passed in the CLI but failed in this browser.";
      case "cliFailedButModeManual":
        return "Accessibility checks failed in the CLI. Run the tests manually to see the results.";
      default:
        return null;
    }
  }, [discrepancy]);
  return message ? React5.createElement(Wrapper3, null, message, " ", React5.createElement(Link2, { href: docsUrl, target: "_blank", withArrow: !0 }, "Learn what could cause this")) : null;
};

// src/components/A11YPanel.tsx
var RotatingIcon = styled5(SyncIcon2)(({ theme: theme2 }) => ({
  animation: `${theme2.animation.rotate360} 1s linear infinite;`,
  margin: 4
})), Tab = styled5.div({
  display: "flex",
  alignItems: "center",
  gap: 6
}), Centered = styled5.span(({ theme: theme2 }) => ({
  display: "flex",
  flexDirection: "column",
  alignItems: "center",
  justifyContent: "center",
  textAlign: "center",
  fontSize: theme2.typography.size.s2,
  height: "100%",
  gap: 24,
  div: {
    display: "flex",
    flexDirection: "column",
    alignItems: "center",
    gap: 8
  },
  p: {
    margin: 0,
    color: theme2.textMutedColor
  },
  code: {
    display: "inline-block",
    fontSize: theme2.typography.size.s2 - 1,
    backgroundColor: theme2.background.app,
    border: `1px solid ${theme2.color.border}`,
    borderRadius: 4,
    padding: "2px 3px"
  }
})), A11YPanel = () => {
  let {
    parameters,
    tab,
    results,
    status,
    handleManual,
    error,
    discrepancy,
    handleSelectionChange,
    selectedItems,
    toggleOpen
  } = useA11yContext(), tabs = useMemo3(() => {
    let { passes, incomplete, violations } = results ?? {
      passes: [],
      incomplete: [],
      violations: []
    };
    return [
      {
        label: React6.createElement(Tab, null, "Violations", React6.createElement(Badge2, { compact: !0, status: tab === "violations" ? "active" : "neutral" }, violations.length)),
        panel: React6.createElement(
          Report,
          {
            items: violations,
            type: RuleType.VIOLATION,
            empty: "No accessibility violations found.",
            handleSelectionChange,
            selectedItems,
            toggleOpen
          }
        ),
        items: violations,
        type: RuleType.VIOLATION
      },
      {
        label: React6.createElement(Tab, null, "Passes", React6.createElement(Badge2, { compact: !0, status: tab === "passes" ? "active" : "neutral" }, passes.length)),
        panel: React6.createElement(
          Report,
          {
            items: passes,
            type: RuleType.PASS,
            empty: "No passing accessibility checks found.",
            handleSelectionChange,
            selectedItems,
            toggleOpen
          }
        ),
        items: passes,
        type: RuleType.PASS
      },
      {
        label: React6.createElement(Tab, null, "Inconclusive", React6.createElement(Badge2, { compact: !0, status: tab === "incomplete" ? "active" : "neutral" }, incomplete.length)),
        panel: React6.createElement(
          Report,
          {
            items: incomplete,
            type: RuleType.INCOMPLETION,
            empty: "No inconclusive accessibility checks found.",
            handleSelectionChange,
            selectedItems,
            toggleOpen
          }
        ),
        items: incomplete,
        type: RuleType.INCOMPLETION
      }
    ];
  }, [tab, results, handleSelectionChange, selectedItems, toggleOpen]);
  return parameters.disable || parameters.test === "off" ? React6.createElement(Centered, null, React6.createElement("div", null, React6.createElement("strong", null, "Accessibility tests are disabled for this story"), React6.createElement("p", null, "Update", " ", React6.createElement("code", null, parameters.disable ? "parameters.a11y.disable" : "parameters.a11y.test"), " ", "to enable accessibility tests."))) : React6.createElement(React6.Fragment, null, discrepancy && React6.createElement(TestDiscrepancyMessage, { discrepancy }), status === "ready" || status === "ran" ? React6.createElement(Tabs, { key: "tabs", tabs }) : React6.createElement(Centered, { style: { marginTop: discrepancy ? "1em" : 0 } }, status === "initial" && React6.createElement("div", null, React6.createElement(RotatingIcon, { size: 12 }), React6.createElement("strong", null, "Preparing accessibility scan"), React6.createElement("p", null, "Please wait while the addon is initializing...")), status === "manual" && React6.createElement(React6.Fragment, null, React6.createElement("div", null, React6.createElement("strong", null, "Accessibility tests run manually for this story"), React6.createElement("p", null, "Results will not show when using the testing module. You can still run accessibility tests manually.")), React6.createElement(Button4, { ariaLabel: !1, size: "medium", onClick: handleManual }, "Run accessibility scan"), React6.createElement("p", null, "Update ", React6.createElement("code", null, "globals.a11y.manual"), " to disable manual mode.")), status === "running" && React6.createElement("div", null, React6.createElement(RotatingIcon, { size: 12 }), React6.createElement("strong", null, "Accessibility scan in progress"), React6.createElement("p", null, "Please wait while the accessibility scan is running...")), status === "error" && React6.createElement(React6.Fragment, null, React6.createElement("div", null, React6.createElement("strong", null, "The accessibility scan encountered an error"), React6.createElement("p", null, typeof error == "string" ? error : error instanceof Error ? error.toString() : JSON.stringify(error, null, 2))), React6.createElement(Button4, { ariaLabel: !1, size: "medium", onClick: handleManual }, "Rerun accessibility scan")), status === "component-test-error" && React6.createElement(React6.Fragment, null, React6.createElement("div", null, React6.createElement("strong", null, "This story's component tests failed"), React6.createElement("p", null, "Automated accessibility tests will not run until this is resolved. You can still test manually.")), React6.createElement(Button4, { ariaLabel: !1, size: "medium", onClick: handleManual }, "Run accessibility scan"))));
};

// src/components/VisionSimulator.tsx
import React7 from "react";
import { Select } from "storybook/internal/components";
import { AccessibilityIcon } from "@storybook/icons";
import { useGlobals as useGlobals2 } from "storybook/manager-api";
import { styled as styled6 } from "storybook/theming";
var Hidden = styled6.div({
  "&, & svg": {
    position: "absolute",
    width: 0,
    height: 0
  }
}), ColorIcon = styled6.span(
  {
    background: "linear-gradient(to right, #F44336, #FF9800, #FFEB3B, #8BC34A, #2196F3, #9C27B0)",
    borderRadius: 14,
    display: "block",
    flexShrink: 0,
    height: 14,
    width: 14
  },
  ({ $filter }) => ({
    filter: filters[$filter].filter || "none"
  }),
  ({ theme: theme2 }) => ({
    boxShadow: `${theme2.appBorderColor} 0 0 0 1px inset`
  })
), VisionSimulator = () => {
  let [globals, updateGlobals, storyGlobals] = useGlobals2(), value = globals[VISION_GLOBAL_KEY], isLocked = storyGlobals[VISION_GLOBAL_KEY] !== void 0, options = Object.entries(filters).map(([key, { label, percentage }]) => ({
    title: label,
    description: percentage ? `${percentage}% of users` : void 0,
    icon: React7.createElement(ColorIcon, { $filter: key }),
    value: key
  }));
  return React7.createElement(React7.Fragment, null, React7.createElement(
    Select,
    {
      resetLabel: "Reset color filter",
      onReset: () => updateGlobals({ [VISION_GLOBAL_KEY]: void 0 }),
      icon: React7.createElement(AccessibilityIcon, null),
      disabled: isLocked,
      ariaLabel: isLocked ? "Vision filter set by story globals" : "Vision filter",
      ariaDescription: "Select a vision filter among predefined options, or reset to remove the filter.",
      tooltip: isLocked ? "Vision filter set by story globals" : "Change vision filter",
      defaultOptions: value,
      options,
      onSelect: (selected) => updateGlobals({ [VISION_GLOBAL_KEY]: selected })
    }
  ), React7.createElement(Hidden, { dangerouslySetInnerHTML: { __html: filterDefs } }));
};

// src/manager.tsx
var Title2 = () => {
  let selectedPanel = useStorybookApi3().getSelectedPanel(), [{ results }] = useAddonState2(ADDON_ID, {
    ui: {
      highlighted: !1,
      tab: RuleType.VIOLATION
    },
    results: void 0,
    error: void 0,
    status: "initial"
  }), violationsNb = results?.violations?.length ?? 0, incompleteNb = results?.incomplete?.length ?? 0, count = violationsNb + incompleteNb, suffix = count === 0 ? null : React8.createElement(Badge3, { compact: !0, status: selectedPanel === PANEL_ID ? "active" : "neutral" }, count);
  return React8.createElement("div", { style: { display: "flex", alignItems: "center", gap: 6 } }, React8.createElement("span", null, "Accessibility"), suffix);
};
addons.register(ADDON_ID, (api) => {
  addons.add(PANEL_ID, {
    title: "",
    type: types.TOOL,
    match: ({ viewMode, tabId }) => viewMode === "story" && !tabId,
    render: () => React8.createElement(VisionSimulator, null)
  }), addons.add(PANEL_ID, {
    title: Title2,
    type: types.PANEL,
    render: ({ active = !0 }) => React8.createElement(A11yContextProvider, null, active ? React8.createElement(A11YPanel, null) : null),
    paramKey: PARAM_KEY
  });
});