storybook 10.0.0-beta.5 → 10.0.0-beta.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (88) hide show
  1. package/assets/server/openBrowser.applescript +94 -0
  2. package/dist/_browser-chunks/{WithTooltip-ERFLZL6W.js → WithTooltip-SK46ZJ2J.js} +1 -1
  3. package/dist/_browser-chunks/{chunk-EOILZP2R.js → chunk-BOOOPFZF.js} +7 -2
  4. package/dist/_browser-chunks/{chunk-YQV3EGQ5.js → chunk-OQ6NCFPL.js} +38 -15
  5. package/dist/_browser-chunks/{chunk-O5R5CGFA.js → chunk-TMDZCWME.js} +1 -2
  6. package/dist/_node-chunks/{builder-manager-ZTS4EIKQ.js → builder-manager-VFP7HSCF.js} +21 -151
  7. package/dist/_node-chunks/camelcase-ZLZNQMDD.js +18 -0
  8. package/dist/_node-chunks/{chunk-VQN4WAIA.js → chunk-2GCKJYK6.js} +7 -7
  9. package/dist/_node-chunks/{chunk-H52PBBSK.js → chunk-3NIQHNDU.js} +7 -7
  10. package/dist/_node-chunks/{chunk-3VVGIILJ.js → chunk-3QZ7KLON.js} +8 -8
  11. package/dist/_node-chunks/{chunk-VWSUFVUF.js → chunk-3XXQRL3A.js} +7 -7
  12. package/dist/_node-chunks/{chunk-OC3TVLYU.js → chunk-46BWYN3K.js} +7 -7
  13. package/dist/_node-chunks/{chunk-VX5P3IYA.js → chunk-4DIDWIST.js} +7 -7
  14. package/dist/_node-chunks/{chunk-TBWOUVTA.js → chunk-5YUTWYNI.js} +709 -935
  15. package/dist/_node-chunks/{chunk-4VDRH7SM.js → chunk-A2DKPKBY.js} +7 -7
  16. package/dist/_node-chunks/{chunk-KU3JBNPY.js → chunk-BC23FKU4.js} +8 -8
  17. package/dist/_node-chunks/{chunk-KZB7ELL6.js → chunk-BID2X7MU.js} +7 -7
  18. package/dist/_node-chunks/{chunk-PIKDGR3O.js → chunk-C4EOB63P.js} +7 -7
  19. package/dist/_node-chunks/{chunk-TVKUJ3SE.js → chunk-DH7BCQMG.js} +8 -8
  20. package/dist/_node-chunks/{chunk-J3DQMIO4.js → chunk-FCNWWJV7.js} +7 -7
  21. package/dist/_node-chunks/{chunk-EIHJ5J3O.js → chunk-GBZZSL2K.js} +264 -109
  22. package/dist/_node-chunks/{chunk-F7YW5W6B.js → chunk-GCWAGPDV.js} +12 -12
  23. package/dist/_node-chunks/{chunk-K4YETNYJ.js → chunk-I7SRMFT5.js} +7 -7
  24. package/dist/_node-chunks/{chunk-TKN5TEZV.js → chunk-IEFSRAX2.js} +13 -13
  25. package/dist/_node-chunks/{chunk-AK5PHLUA.js → chunk-IGWCAXA2.js} +7 -7
  26. package/dist/_node-chunks/chunk-IYOHZPPC.js +18 -0
  27. package/dist/_node-chunks/{chunk-F3WE3456.js → chunk-KVOP6ASA.js} +7 -7
  28. package/dist/_node-chunks/{chunk-DZJNLBBL.js → chunk-MHVF6Y35.js} +7 -7
  29. package/dist/_node-chunks/{chunk-UTCFHTQH.js → chunk-MRCMZPA2.js} +7 -7
  30. package/dist/_node-chunks/chunk-RNHUADRS.js +62 -0
  31. package/dist/_node-chunks/{chunk-4KRR46V2.js → chunk-RP3VMQPF.js} +15 -15
  32. package/dist/_node-chunks/{chunk-P7YMEOXF.js → chunk-TFIGR2HH.js} +7 -7
  33. package/dist/_node-chunks/{chunk-SW3VZAH7.js → chunk-TXDIOSHI.js} +9 -9
  34. package/dist/_node-chunks/{chunk-WCSHG2QT.js → chunk-U6MJQ7C6.js} +7 -7
  35. package/dist/_node-chunks/{chunk-ACUNHBEO.js → chunk-XXVKM2ZR.js} +26 -23
  36. package/dist/_node-chunks/{chunk-QHIU5I7C.js → chunk-YWU65VY4.js} +6 -6
  37. package/dist/_node-chunks/{chunk-P3TWEOO5.js → chunk-Z3PLI7S2.js} +7 -7
  38. package/dist/_node-chunks/{chunk-2VMDKLSW.js → chunk-ZM2HT2RW.js} +6 -6
  39. package/dist/_node-chunks/{chunk-D7SDB4XE.js → chunk-ZPNXCXIT.js} +8 -8
  40. package/dist/_node-chunks/{dist-OGRBL76N.js → dist-PG4I7ZDU.js} +9 -9
  41. package/dist/_node-chunks/{globby-65LOULA6.js → globby-HXB6X43W.js} +17 -13
  42. package/dist/_node-chunks/{lib-TF7JCT3A.js → lib-4JJTZC7T.js} +7 -7
  43. package/dist/_node-chunks/{mdx-N42X6CFJ-6ZJEUZMZ.js → mdx-N42X6CFJ-3JBJ7PQF.js} +8 -8
  44. package/dist/_node-chunks/{p-limit-PF7JSPDT.js → p-limit-WBBNX4KI.js} +7 -7
  45. package/dist/_node-chunks/{plugin-A6XAWMXN.js → plugin-SEQ2OPRK.js} +10 -10
  46. package/dist/_node-chunks/{plugin-LGHGAC6J.js → plugin-SG6I7RFC.js} +10 -10
  47. package/dist/_node-chunks/{webpack-inject-mocker-runtime-plugin-HDSEOU3Z.js → webpack-inject-mocker-runtime-plugin-5O25VYCQ.js} +10 -10
  48. package/dist/_node-chunks/{webpack-mock-plugin-ZJJVMJUS.js → webpack-mock-plugin-35I32SAF.js} +9 -9
  49. package/dist/babel/index.js +11 -11
  50. package/dist/bin/core.js +11 -11
  51. package/dist/bin/dispatcher.js +11 -11
  52. package/dist/bin/loader.js +8 -8
  53. package/dist/cli/index.js +27 -22
  54. package/dist/common/index.js +21 -21
  55. package/dist/components/index.js +8 -4
  56. package/dist/core-events/index.d.ts +18 -2
  57. package/dist/core-events/index.js +7 -1
  58. package/dist/core-server/index.js +1157 -1024
  59. package/dist/core-server/presets/common-manager.js +84 -39
  60. package/dist/core-server/presets/common-override-preset.js +9 -9
  61. package/dist/core-server/presets/common-preset.js +691 -29
  62. package/dist/core-server/presets/webpack/loaders/storybook-mock-transform-loader.js +9 -9
  63. package/dist/core-server/presets/webpack/loaders/webpack-automock-loader.js +10 -10
  64. package/dist/csf/index.d.ts +9 -4
  65. package/dist/csf/index.js +37 -8
  66. package/dist/csf-tools/index.d.ts +13 -6
  67. package/dist/csf-tools/index.js +9 -9
  68. package/dist/manager/globals-runtime.js +1318 -1001
  69. package/dist/manager/globals.d.ts +0 -4
  70. package/dist/manager/globals.js +1 -6
  71. package/dist/manager/runtime.js +2198 -721
  72. package/dist/manager-api/index.d.ts +12 -5
  73. package/dist/manager-api/index.js +347 -76
  74. package/dist/node-logger/index.js +14 -14
  75. package/dist/preview/runtime.js +103 -63
  76. package/dist/preview-api/index.d.ts +70 -71
  77. package/dist/preview-api/index.js +1 -1
  78. package/dist/server-errors.js +10 -10
  79. package/dist/telemetry/index.d.ts +1 -1
  80. package/dist/telemetry/index.js +24 -24
  81. package/dist/types/index.d.ts +28 -7
  82. package/dist/viewport/index.d.ts +36 -4
  83. package/dist/viewport/index.js +1 -1
  84. package/package.json +5 -4
  85. package/dist/_node-chunks/camelcase-K3BM7RII.js +0 -18
  86. package/dist/_node-chunks/chunk-7LG5CLCT.js +0 -18
  87. package/dist/_node-chunks/chunk-DWJ7TV2O.js +0 -62
  88. package/dist/_node-chunks/default-browser-id-4RZZMHJE.js +0 -1719
@@ -1589,7 +1589,7 @@ var require_copy_to_clipboard = __commonJS({
1589
1589
  return message.replace(/#{\s*key\s*}/g, copyKey);
1590
1590
  }
1591
1591
  __name(format, "format");
1592
- function copy2(text, options2) {
1592
+ function copy3(text, options2) {
1593
1593
  var debug, message, reselectPrevious, range3, selection, mark, success = false;
1594
1594
  if (!options2) {
1595
1595
  options2 = {};
@@ -1667,8 +1667,8 @@ var require_copy_to_clipboard = __commonJS({
1667
1667
  }
1668
1668
  return success;
1669
1669
  }
1670
- __name(copy2, "copy");
1671
- module.exports = copy2;
1670
+ __name(copy3, "copy");
1671
+ module.exports = copy3;
1672
1672
  }
1673
1673
  });
1674
1674
 
@@ -2455,7 +2455,7 @@ var { Channel, HEARTBEAT_INTERVAL, HEARTBEAT_MAX_LATENCY, PostMessageTransport,
2455
2455
 
2456
2456
  // global-externals:storybook/internal/core-events
2457
2457
  var core_events_default = __STORYBOOK_CORE_EVENTS__;
2458
- var { ARGTYPES_INFO_REQUEST, ARGTYPES_INFO_RESPONSE, CHANNEL_CREATED, CHANNEL_WS_DISCONNECT, CONFIG_ERROR, CREATE_NEW_STORYFILE_REQUEST, CREATE_NEW_STORYFILE_RESPONSE, CURRENT_STORY_WAS_SET, DOCS_PREPARED, DOCS_RENDERED, FILE_COMPONENT_SEARCH_REQUEST, FILE_COMPONENT_SEARCH_RESPONSE, FORCE_REMOUNT, FORCE_RE_RENDER, GLOBALS_UPDATED, NAVIGATE_URL, PLAY_FUNCTION_THREW_EXCEPTION, PRELOAD_ENTRIES, PREVIEW_BUILDER_PROGRESS, PREVIEW_KEYDOWN, REGISTER_SUBSCRIPTION, REQUEST_WHATS_NEW_DATA, RESET_STORY_ARGS, RESULT_WHATS_NEW_DATA, SAVE_STORY_REQUEST, SAVE_STORY_RESPONSE, SELECT_STORY, SET_CONFIG, SET_CURRENT_STORY, SET_FILTER, SET_GLOBALS, SET_INDEX, SET_STORIES, SET_WHATS_NEW_CACHE, SHARED_STATE_CHANGED, SHARED_STATE_SET, STORIES_COLLAPSE_ALL, STORIES_EXPAND_ALL, STORY_ARGS_UPDATED, STORY_CHANGED, STORY_ERRORED, STORY_FINISHED, STORY_HOT_UPDATED, STORY_INDEX_INVALIDATED, STORY_MISSING, STORY_PREPARED, STORY_RENDERED, STORY_RENDER_PHASE_CHANGED, STORY_SPECIFIED, STORY_THREW_EXCEPTION, STORY_UNCHANGED, TELEMETRY_ERROR, TOGGLE_WHATS_NEW_NOTIFICATIONS, UNHANDLED_ERRORS_WHILE_PLAYING, UPDATE_GLOBALS, UPDATE_QUERY_PARAMS, UPDATE_STORY_ARGS } = __STORYBOOK_CORE_EVENTS__;
2458
+ var { ARGTYPES_INFO_REQUEST, ARGTYPES_INFO_RESPONSE, CHANNEL_CREATED, CHANNEL_WS_DISCONNECT, CONFIG_ERROR, CREATE_NEW_STORYFILE_REQUEST, CREATE_NEW_STORYFILE_RESPONSE, CURRENT_STORY_WAS_SET, DOCS_PREPARED, DOCS_RENDERED, FILE_COMPONENT_SEARCH_REQUEST, FILE_COMPONENT_SEARCH_RESPONSE, FORCE_REMOUNT, FORCE_RE_RENDER, GLOBALS_UPDATED, NAVIGATE_URL, OPEN_IN_EDITOR_REQUEST, OPEN_IN_EDITOR_RESPONSE, PLAY_FUNCTION_THREW_EXCEPTION, PRELOAD_ENTRIES, PREVIEW_BUILDER_PROGRESS, PREVIEW_KEYDOWN, REGISTER_SUBSCRIPTION, REQUEST_WHATS_NEW_DATA, RESET_STORY_ARGS, RESULT_WHATS_NEW_DATA, SAVE_STORY_REQUEST, SAVE_STORY_RESPONSE, SELECT_STORY, SET_CONFIG, SET_CURRENT_STORY, SET_FILTER, SET_GLOBALS, SET_INDEX, SET_STORIES, SET_WHATS_NEW_CACHE, SHARED_STATE_CHANGED, SHARED_STATE_SET, STORIES_COLLAPSE_ALL, STORIES_EXPAND_ALL, STORY_ARGS_UPDATED, STORY_CHANGED, STORY_ERRORED, STORY_FINISHED, STORY_HOT_UPDATED, STORY_INDEX_INVALIDATED, STORY_MISSING, STORY_PREPARED, STORY_RENDERED, STORY_RENDER_PHASE_CHANGED, STORY_SPECIFIED, STORY_THREW_EXCEPTION, STORY_UNCHANGED, TELEMETRY_ERROR, TOGGLE_WHATS_NEW_NOTIFICATIONS, UNHANDLED_ERRORS_WHILE_PLAYING, UPDATE_GLOBALS, UPDATE_QUERY_PARAMS, UPDATE_STORY_ARGS } = __STORYBOOK_CORE_EVENTS__;
2459
2459
 
2460
2460
  // ../node_modules/@storybook/global/dist/index.mjs
2461
2461
  var scope = (() => {
@@ -2572,6 +2572,7 @@ __export(icons_exports, {
2572
2572
  DownloadIcon: () => DownloadIcon,
2573
2573
  DragIcon: () => DragIcon,
2574
2574
  EditIcon: () => EditIcon,
2575
+ EditorIcon: () => EditorIcon,
2575
2576
  EllipsisIcon: () => EllipsisIcon,
2576
2577
  EmailIcon: () => EmailIcon,
2577
2578
  ExpandAltIcon: () => ExpandAltIcon,
@@ -2731,7 +2732,7 @@ __export(icons_exports, {
2731
2732
  iconList: () => iconList
2732
2733
  });
2733
2734
  var icons_default = __STORYBOOK_ICONS__;
2734
- var { AccessibilityAltIcon, AccessibilityIcon, AccessibilityIgnoredIcon, AddIcon, AdminIcon, AlertAltIcon, AlertIcon, AlignLeftIcon, AlignRightIcon, AppleIcon, ArrowBottomLeftIcon, ArrowBottomRightIcon, ArrowDownIcon, ArrowLeftIcon, ArrowRightIcon, ArrowSolidDownIcon, ArrowSolidLeftIcon, ArrowSolidRightIcon, ArrowSolidUpIcon, ArrowTopLeftIcon, ArrowTopRightIcon, ArrowUpIcon, AzureDevOpsIcon, BackIcon, BasketIcon, BatchAcceptIcon, BatchDenyIcon, BeakerIcon, BellIcon, BitbucketIcon, BoldIcon, BookIcon, BookmarkHollowIcon, BookmarkIcon, BottomBarIcon, BottomBarToggleIcon, BoxIcon, BranchIcon, BrowserIcon, BugIcon, ButtonIcon, CPUIcon, CalendarIcon, CameraIcon, CameraStabilizeIcon, CategoryIcon, CertificateIcon, ChangedIcon, ChatIcon, CheckIcon, ChevronDownIcon, ChevronLeftIcon, ChevronRightIcon, ChevronSmallDownIcon, ChevronSmallLeftIcon, ChevronSmallRightIcon, ChevronSmallUpIcon, ChevronUpIcon, ChromaticIcon, ChromeIcon, CircleHollowIcon, CircleIcon, ClearIcon, CloseAltIcon, CloseIcon, CloudHollowIcon, CloudIcon, CogIcon, CollapseIcon, CommandIcon, CommentAddIcon, CommentIcon, CommentsIcon, CommitIcon, CompassIcon, ComponentDrivenIcon, ComponentIcon, ContrastIcon, ContrastIgnoredIcon, ControlsIcon, CopyIcon, CreditIcon, CrossIcon, DashboardIcon, DatabaseIcon, DeleteIcon, DiamondIcon, DirectionIcon, DiscordIcon, DocChartIcon, DocListIcon, DocumentIcon, DownloadIcon, DragIcon, EditIcon, EllipsisIcon, EmailIcon, ExpandAltIcon, ExpandIcon, EyeCloseIcon, EyeIcon, FaceHappyIcon, FaceNeutralIcon, FaceSadIcon, FacebookIcon, FailedIcon, FastForwardIcon, FigmaIcon, FilterIcon, FlagIcon, FolderIcon, FormIcon, GDriveIcon, GiftIcon, GithubIcon, GitlabIcon, GlobeIcon, GoogleIcon, GraphBarIcon, GraphLineIcon, GraphqlIcon, GridAltIcon, GridIcon, GrowIcon, HeartHollowIcon, HeartIcon, HomeIcon, HourglassIcon, InfoIcon, ItalicIcon, JumpToIcon, KeyIcon, LightningIcon, LightningOffIcon, LinkBrokenIcon, LinkIcon, LinkedinIcon, LinuxIcon, ListOrderedIcon, ListUnorderedIcon, LocationIcon, LockIcon, MarkdownIcon, MarkupIcon, MediumIcon, MemoryIcon, MenuIcon, MergeIcon, MirrorIcon, MobileIcon, MoonIcon, NutIcon, OutboxIcon, OutlineIcon, PaintBrushAltIcon, PaintBrushIcon, PaperClipIcon, ParagraphIcon, PassedIcon, PhoneIcon, PhotoDragIcon, PhotoIcon, PhotoStabilizeIcon, PinAltIcon, PinIcon, PlayAllHollowIcon, PlayBackIcon, PlayHollowIcon, PlayIcon, PlayNextIcon, PlusIcon, PointerDefaultIcon, PointerHandIcon, PowerIcon, PrintIcon, ProceedIcon, ProfileIcon, PullRequestIcon, QuestionIcon, RSSIcon, RedirectIcon, ReduxIcon, RefreshIcon, ReplyIcon, RepoIcon, RequestChangeIcon, RewindIcon, RulerIcon, SaveIcon, SearchIcon, ShareAltIcon, ShareIcon, ShieldIcon, SideBySideIcon, SidebarAltIcon, SidebarAltToggleIcon, SidebarIcon, SidebarToggleIcon, SortDownIcon, SortUpIcon, SpeakerIcon, StackedIcon, StarHollowIcon, StarIcon, StatusFailIcon, StatusIcon, StatusPassIcon, StatusWarnIcon, StickerIcon, StopAltHollowIcon, StopAltIcon, StopIcon, StorybookIcon, StructureIcon, SubtractIcon, SunIcon, SupportIcon, SweepIcon, SwitchAltIcon, SyncIcon, TabletIcon, ThumbsUpIcon, TimeIcon, TimerIcon, TransferIcon, TrashIcon, TwitterIcon, TypeIcon, UbuntuIcon, UndoIcon, UnfoldIcon, UnlockIcon, UnpinIcon, UploadIcon, UserAddIcon, UserAltIcon, UserIcon, UsersIcon, VSCodeIcon, VerifiedIcon, VideoIcon, WandIcon, WatchIcon, WindowsIcon, WrenchIcon, XIcon, YoutubeIcon, ZoomIcon, ZoomOutIcon, ZoomResetIcon, iconList } = __STORYBOOK_ICONS__;
2735
+ var { AccessibilityAltIcon, AccessibilityIcon, AccessibilityIgnoredIcon, AddIcon, AdminIcon, AlertAltIcon, AlertIcon, AlignLeftIcon, AlignRightIcon, AppleIcon, ArrowBottomLeftIcon, ArrowBottomRightIcon, ArrowDownIcon, ArrowLeftIcon, ArrowRightIcon, ArrowSolidDownIcon, ArrowSolidLeftIcon, ArrowSolidRightIcon, ArrowSolidUpIcon, ArrowTopLeftIcon, ArrowTopRightIcon, ArrowUpIcon, AzureDevOpsIcon, BackIcon, BasketIcon, BatchAcceptIcon, BatchDenyIcon, BeakerIcon, BellIcon, BitbucketIcon, BoldIcon, BookIcon, BookmarkHollowIcon, BookmarkIcon, BottomBarIcon, BottomBarToggleIcon, BoxIcon, BranchIcon, BrowserIcon, BugIcon, ButtonIcon, CPUIcon, CalendarIcon, CameraIcon, CameraStabilizeIcon, CategoryIcon, CertificateIcon, ChangedIcon, ChatIcon, CheckIcon, ChevronDownIcon, ChevronLeftIcon, ChevronRightIcon, ChevronSmallDownIcon, ChevronSmallLeftIcon, ChevronSmallRightIcon, ChevronSmallUpIcon, ChevronUpIcon, ChromaticIcon, ChromeIcon, CircleHollowIcon, CircleIcon, ClearIcon, CloseAltIcon, CloseIcon, CloudHollowIcon, CloudIcon, CogIcon, CollapseIcon, CommandIcon, CommentAddIcon, CommentIcon, CommentsIcon, CommitIcon, CompassIcon, ComponentDrivenIcon, ComponentIcon, ContrastIcon, ContrastIgnoredIcon, ControlsIcon, CopyIcon, CreditIcon, CrossIcon, DashboardIcon, DatabaseIcon, DeleteIcon, DiamondIcon, DirectionIcon, DiscordIcon, DocChartIcon, DocListIcon, DocumentIcon, DownloadIcon, DragIcon, EditIcon, EditorIcon, EllipsisIcon, EmailIcon, ExpandAltIcon, ExpandIcon, EyeCloseIcon, EyeIcon, FaceHappyIcon, FaceNeutralIcon, FaceSadIcon, FacebookIcon, FailedIcon, FastForwardIcon, FigmaIcon, FilterIcon, FlagIcon, FolderIcon, FormIcon, GDriveIcon, GiftIcon, GithubIcon, GitlabIcon, GlobeIcon, GoogleIcon, GraphBarIcon, GraphLineIcon, GraphqlIcon, GridAltIcon, GridIcon, GrowIcon, HeartHollowIcon, HeartIcon, HomeIcon, HourglassIcon, InfoIcon, ItalicIcon, JumpToIcon, KeyIcon, LightningIcon, LightningOffIcon, LinkBrokenIcon, LinkIcon, LinkedinIcon, LinuxIcon, ListOrderedIcon, ListUnorderedIcon, LocationIcon, LockIcon, MarkdownIcon, MarkupIcon, MediumIcon, MemoryIcon, MenuIcon, MergeIcon, MirrorIcon, MobileIcon, MoonIcon, NutIcon, OutboxIcon, OutlineIcon, PaintBrushAltIcon, PaintBrushIcon, PaperClipIcon, ParagraphIcon, PassedIcon, PhoneIcon, PhotoDragIcon, PhotoIcon, PhotoStabilizeIcon, PinAltIcon, PinIcon, PlayAllHollowIcon, PlayBackIcon, PlayHollowIcon, PlayIcon, PlayNextIcon, PlusIcon, PointerDefaultIcon, PointerHandIcon, PowerIcon, PrintIcon, ProceedIcon, ProfileIcon, PullRequestIcon, QuestionIcon, RSSIcon, RedirectIcon, ReduxIcon, RefreshIcon, ReplyIcon, RepoIcon, RequestChangeIcon, RewindIcon, RulerIcon, SaveIcon, SearchIcon, ShareAltIcon, ShareIcon, ShieldIcon, SideBySideIcon, SidebarAltIcon, SidebarAltToggleIcon, SidebarIcon, SidebarToggleIcon, SortDownIcon, SortUpIcon, SpeakerIcon, StackedIcon, StarHollowIcon, StarIcon, StatusFailIcon, StatusIcon, StatusPassIcon, StatusWarnIcon, StickerIcon, StopAltHollowIcon, StopAltIcon, StopIcon, StorybookIcon, StructureIcon, SubtractIcon, SunIcon, SupportIcon, SweepIcon, SwitchAltIcon, SyncIcon, TabletIcon, ThumbsUpIcon, TimeIcon, TimerIcon, TransferIcon, TrashIcon, TwitterIcon, TypeIcon, UbuntuIcon, UndoIcon, UnfoldIcon, UnlockIcon, UnpinIcon, UploadIcon, UserAddIcon, UserAltIcon, UserIcon, UsersIcon, VSCodeIcon, VerifiedIcon, VideoIcon, WandIcon, WatchIcon, WindowsIcon, WrenchIcon, XIcon, YoutubeIcon, ZoomIcon, ZoomOutIcon, ZoomResetIcon, iconList } = __STORYBOOK_ICONS__;
2735
2736
 
2736
2737
  // global-externals:storybook/manager-api
2737
2738
  var manager_api_default = __STORYBOOK_API__;
@@ -5473,14 +5474,14 @@ var import_prop_types5 = __toESM(require_prop_types());
5473
5474
 
5474
5475
  // ../node_modules/react-transition-group/esm/utils/ChildMapping.js
5475
5476
  function getChildMapping(children2, mapFn) {
5476
- var mapper3 = /* @__PURE__ */ __name(function mapper4(child) {
5477
+ var mapper5 = /* @__PURE__ */ __name(function mapper6(child) {
5477
5478
  return mapFn && isValidElement(child) ? mapFn(child) : child;
5478
5479
  }, "mapper");
5479
5480
  var result2 = /* @__PURE__ */ Object.create(null);
5480
5481
  if (children2) Children.map(children2, function(c2) {
5481
5482
  return c2;
5482
5483
  }).forEach(function(child) {
5483
- result2[child.key] = mapper3(child);
5484
+ result2[child.key] = mapper5(child);
5484
5485
  });
5485
5486
  return result2;
5486
5487
  }
@@ -6695,6 +6696,7 @@ var useLayoutSyncingState = /* @__PURE__ */ __name(({
6695
6696
  });
6696
6697
  const { navSize, rightPanelWidth, bottomPanelHeight } = internalDraggingSizeState.isDragging ? internalDraggingSizeState : managerLayoutState;
6697
6698
  const customisedNavSize = api.getNavSizeWithCustomisations?.(navSize) ?? navSize;
6699
+ const customisedShowPanel = api.getShowPanelWithCustomisations?.(isPanelShown) ?? isPanelShown;
6698
6700
  return {
6699
6701
  navSize: customisedNavSize,
6700
6702
  rightPanelWidth,
@@ -6703,7 +6705,7 @@ var useLayoutSyncingState = /* @__PURE__ */ __name(({
6703
6705
  panelResizerRef,
6704
6706
  sidebarResizerRef,
6705
6707
  showPages: isPagesShown,
6706
- showPanel: isPanelShown,
6708
+ showPanel: customisedShowPanel,
6707
6709
  isDragging: internalDraggingSizeState.isDragging
6708
6710
  };
6709
6711
  }, "useLayoutSyncingState");
@@ -6773,7 +6775,7 @@ var LayoutContainer = styled.div(
6773
6775
  gridTemplateColumns: `minmax(0, ${navSize}px) minmax(${MINIMUM_CONTENT_WIDTH_PX}px, 1fr) minmax(0, ${rightPanelWidth}px)`,
6774
6776
  gridTemplateRows: `1fr minmax(0, ${bottomPanelHeight}px)`,
6775
6777
  gridTemplateAreas: (() => {
6776
- if (viewMode === "docs" || !showPanel) {
6778
+ if (!showPanel) {
6777
6779
  return `"sidebar content content"
6778
6780
  "sidebar content content"`;
6779
6781
  }
@@ -6936,6 +6938,8 @@ var events = /* @__PURE__ */ ((events2) => {
6936
6938
  events2["ARGTYPES_INFO_RESPONSE"] = "argtypesInfoResponse";
6937
6939
  events2["CREATE_NEW_STORYFILE_REQUEST"] = "createNewStoryfileRequest";
6938
6940
  events2["CREATE_NEW_STORYFILE_RESPONSE"] = "createNewStoryfileResponse";
6941
+ events2["OPEN_IN_EDITOR_REQUEST"] = "openInEditorRequest";
6942
+ events2["OPEN_IN_EDITOR_RESPONSE"] = "openInEditorResponse";
6939
6943
  return events2;
6940
6944
  })(events || {});
6941
6945
  var {
@@ -6995,7 +6999,9 @@ var {
6995
6999
  SAVE_STORY_REQUEST: SAVE_STORY_REQUEST2,
6996
7000
  SAVE_STORY_RESPONSE: SAVE_STORY_RESPONSE2,
6997
7001
  ARGTYPES_INFO_REQUEST: ARGTYPES_INFO_REQUEST2,
6998
- ARGTYPES_INFO_RESPONSE: ARGTYPES_INFO_RESPONSE2
7002
+ ARGTYPES_INFO_RESPONSE: ARGTYPES_INFO_RESPONSE2,
7003
+ OPEN_IN_EDITOR_REQUEST: OPEN_IN_EDITOR_REQUEST2,
7004
+ OPEN_IN_EDITOR_RESPONSE: OPEN_IN_EDITOR_RESPONSE2
6999
7005
  } = events;
7000
7006
 
7001
7007
  // src/manager/components/panel/Panel.tsx
@@ -7272,194 +7278,6 @@ var FramesRenderer = /* @__PURE__ */ __name(({
7272
7278
  }));
7273
7279
  }, "FramesRenderer");
7274
7280
 
7275
- // src/manager/components/preview/tools/addons.tsx
7276
- var menuMapper = /* @__PURE__ */ __name(({ api, state }) => ({
7277
- isVisible: api.getIsPanelShown(),
7278
- singleStory: state.singleStory,
7279
- panelPosition: state.layout.panelPosition,
7280
- toggle: /* @__PURE__ */ __name(() => api.togglePanel(), "toggle")
7281
- }), "menuMapper");
7282
- var addonsTool = {
7283
- title: "addons",
7284
- id: "addons",
7285
- type: types.TOOL,
7286
- match: /* @__PURE__ */ __name(({ viewMode, tabId }) => viewMode === "story" && !tabId, "match"),
7287
- render: /* @__PURE__ */ __name(() => react_default.createElement(Consumer, { filter: menuMapper }, ({ isVisible, toggle, singleStory, panelPosition }) => !singleStory && !isVisible && react_default.createElement(react_default.Fragment, null, react_default.createElement(IconButton, { "aria-label": "Show addons", key: "addons", onClick: toggle, title: "Show addons" }, panelPosition === "bottom" ? react_default.createElement(BottomBarIcon, null) : react_default.createElement(SidebarAltIcon, null)))), "render")
7288
- };
7289
-
7290
- // src/manager/components/preview/tools/copy.tsx
7291
- var import_copy_to_clipboard = __toESM(require_copy_to_clipboard(), 1);
7292
- var { PREVIEW_URL, document: document2 } = scope;
7293
- var copyMapper = /* @__PURE__ */ __name(({ state }) => {
7294
- const { storyId, refId, refs } = state;
7295
- const { location } = document2;
7296
- const ref = refs[refId];
7297
- let baseUrl = `${location.origin}${location.pathname}`;
7298
- if (!baseUrl.endsWith("/")) {
7299
- baseUrl += "/";
7300
- }
7301
- return {
7302
- refId,
7303
- baseUrl: ref ? `${ref.url}/iframe.html` : PREVIEW_URL || `${baseUrl}iframe.html`,
7304
- storyId,
7305
- queryParams: state.customQueryParams
7306
- };
7307
- }, "copyMapper");
7308
- var copyTool = {
7309
- title: "copy",
7310
- id: "copy",
7311
- type: types.TOOL,
7312
- match: /* @__PURE__ */ __name(({ viewMode, tabId }) => viewMode === "story" && !tabId, "match"),
7313
- render: /* @__PURE__ */ __name(() => react_default.createElement(Consumer, { filter: copyMapper }, ({ baseUrl, storyId, queryParams }) => storyId ? react_default.createElement(
7314
- IconButton,
7315
- {
7316
- key: "copy",
7317
- onClick: () => (0, import_copy_to_clipboard.default)(getStoryHref(baseUrl, storyId, queryParams)),
7318
- title: "Copy canvas link"
7319
- },
7320
- react_default.createElement(LinkIcon, null)
7321
- ) : null), "render")
7322
- };
7323
-
7324
- // src/manager/components/preview/tools/eject.tsx
7325
- var { PREVIEW_URL: PREVIEW_URL2 } = scope;
7326
- var ejectMapper = /* @__PURE__ */ __name(({ state }) => {
7327
- const { storyId, refId, refs } = state;
7328
- const ref = refs[refId];
7329
- return {
7330
- refId,
7331
- baseUrl: ref ? `${ref.url}/iframe.html` : PREVIEW_URL2 || "iframe.html",
7332
- storyId,
7333
- queryParams: state.customQueryParams
7334
- };
7335
- }, "ejectMapper");
7336
- var ejectTool = {
7337
- title: "eject",
7338
- id: "eject",
7339
- type: types.TOOL,
7340
- match: /* @__PURE__ */ __name(({ viewMode, tabId }) => viewMode === "story" && !tabId, "match"),
7341
- render: /* @__PURE__ */ __name(() => react_default.createElement(Consumer, { filter: ejectMapper }, ({ baseUrl, storyId, queryParams }) => storyId ? react_default.createElement(IconButton, { key: "opener", asChild: true }, react_default.createElement(
7342
- "a",
7343
- {
7344
- href: getStoryHref(baseUrl, storyId, queryParams),
7345
- target: "_blank",
7346
- rel: "noopener noreferrer",
7347
- title: "Open canvas in new tab"
7348
- },
7349
- react_default.createElement(ShareAltIcon, null)
7350
- )) : null), "render")
7351
- };
7352
-
7353
- // src/manager/components/preview/tools/remount.tsx
7354
- var StyledAnimatedIconButton = styled(IconButton)(({ theme, animating, disabled }) => ({
7355
- opacity: disabled ? 0.5 : 1,
7356
- svg: {
7357
- animation: animating ? `${theme.animation.rotate360} 1000ms ease-out` : void 0
7358
- }
7359
- }));
7360
- var menuMapper2 = /* @__PURE__ */ __name(({ api, state }) => {
7361
- const { storyId } = state;
7362
- return {
7363
- storyId,
7364
- remount: /* @__PURE__ */ __name(() => api.emit(FORCE_REMOUNT, { storyId: state.storyId }), "remount"),
7365
- api
7366
- };
7367
- }, "menuMapper");
7368
- var remountTool = {
7369
- title: "remount",
7370
- id: "remount",
7371
- type: types.TOOL,
7372
- match: /* @__PURE__ */ __name(({ viewMode, tabId }) => viewMode === "story" && !tabId, "match"),
7373
- render: /* @__PURE__ */ __name(() => react_default.createElement(Consumer, { filter: menuMapper2 }, ({ remount, storyId, api }) => {
7374
- const [isAnimating, setIsAnimating] = useState(false);
7375
- const remountComponent = /* @__PURE__ */ __name(() => {
7376
- if (!storyId) {
7377
- return;
7378
- }
7379
- remount();
7380
- }, "remountComponent");
7381
- api.on(FORCE_REMOUNT, () => {
7382
- setIsAnimating(true);
7383
- });
7384
- return react_default.createElement(
7385
- StyledAnimatedIconButton,
7386
- {
7387
- key: "remount",
7388
- title: "Remount component",
7389
- onClick: remountComponent,
7390
- onAnimationEnd: () => setIsAnimating(false),
7391
- animating: isAnimating,
7392
- disabled: !storyId
7393
- },
7394
- react_default.createElement(SyncIcon, null)
7395
- );
7396
- }), "render")
7397
- };
7398
-
7399
- // src/manager/components/preview/tools/zoom.tsx
7400
- var initialZoom = 1;
7401
- var Context = createContext({ value: initialZoom, set: /* @__PURE__ */ __name((v2) => {
7402
- }, "set") });
7403
- var _ZoomProvider = class _ZoomProvider extends Component {
7404
- constructor() {
7405
- super(...arguments);
7406
- this.state = {
7407
- value: initialZoom
7408
- };
7409
- this.set = /* @__PURE__ */ __name((value) => this.setState({ value }), "set");
7410
- }
7411
- render() {
7412
- const { children: children2, shouldScale } = this.props;
7413
- const { set: set2 } = this;
7414
- const { value } = this.state;
7415
- return react_default.createElement(Context.Provider, { value: { value: shouldScale ? value : initialZoom, set: set2 } }, children2);
7416
- }
7417
- };
7418
- __name(_ZoomProvider, "ZoomProvider");
7419
- var ZoomProvider = _ZoomProvider;
7420
- var { Consumer: ZoomConsumer } = Context;
7421
- var Zoom2 = memo(/* @__PURE__ */ __name(function Zoom3({ zoomIn, zoomOut, reset }) {
7422
- return react_default.createElement(react_default.Fragment, null, react_default.createElement(IconButton, { key: "zoomin", onClick: zoomIn, title: "Zoom in" }, react_default.createElement(ZoomIcon, null)), react_default.createElement(IconButton, { key: "zoomout", onClick: zoomOut, title: "Zoom out" }, react_default.createElement(ZoomOutIcon, null)), react_default.createElement(IconButton, { key: "zoomreset", onClick: reset, title: "Reset zoom" }, react_default.createElement(ZoomResetIcon, null)));
7423
- }, "Zoom"));
7424
- var ZoomWrapper = memo(/* @__PURE__ */ __name(function ZoomWrapper2({
7425
- set: set2,
7426
- value
7427
- }) {
7428
- const zoomIn = useCallback(
7429
- (e2) => {
7430
- e2.preventDefault();
7431
- set2(0.8 * value);
7432
- },
7433
- [set2, value]
7434
- );
7435
- const zoomOut = useCallback(
7436
- (e2) => {
7437
- e2.preventDefault();
7438
- set2(1.25 * value);
7439
- },
7440
- [set2, value]
7441
- );
7442
- const reset = useCallback(
7443
- (e2) => {
7444
- e2.preventDefault();
7445
- set2(initialZoom);
7446
- },
7447
- [set2, initialZoom]
7448
- );
7449
- return react_default.createElement(Zoom2, { key: "zoom", ...{ zoomIn, zoomOut, reset } });
7450
- }, "ZoomWrapper"));
7451
- function ZoomToolRenderer() {
7452
- return react_default.createElement(react_default.Fragment, null, react_default.createElement(ZoomConsumer, null, ({ set: set2, value }) => react_default.createElement(ZoomWrapper, { ...{ set: set2, value } })), react_default.createElement(Separator, null));
7453
- }
7454
- __name(ZoomToolRenderer, "ZoomToolRenderer");
7455
- var zoomTool = {
7456
- title: "zoom",
7457
- id: "zoom",
7458
- type: types.TOOL,
7459
- match: /* @__PURE__ */ __name(({ viewMode, tabId }) => viewMode === "story" && !tabId, "match"),
7460
- render: ZoomToolRenderer
7461
- };
7462
-
7463
7281
  // src/manager/components/preview/Toolbar.tsx
7464
7282
  var fullScreenMapper = /* @__PURE__ */ __name(({ api, state }) => {
7465
7283
  return {
@@ -7676,6 +7494,70 @@ var defaultWrappers = [
7676
7494
  }
7677
7495
  ];
7678
7496
 
7497
+ // src/manager/components/preview/tools/zoom.tsx
7498
+ var initialZoom = 1;
7499
+ var Context = createContext({ value: initialZoom, set: /* @__PURE__ */ __name((v2) => {
7500
+ }, "set") });
7501
+ var _ZoomProvider = class _ZoomProvider extends Component {
7502
+ constructor() {
7503
+ super(...arguments);
7504
+ this.state = {
7505
+ value: initialZoom
7506
+ };
7507
+ this.set = /* @__PURE__ */ __name((value) => this.setState({ value }), "set");
7508
+ }
7509
+ render() {
7510
+ const { children: children2, shouldScale } = this.props;
7511
+ const { set: set2 } = this;
7512
+ const { value } = this.state;
7513
+ return react_default.createElement(Context.Provider, { value: { value: shouldScale ? value : initialZoom, set: set2 } }, children2);
7514
+ }
7515
+ };
7516
+ __name(_ZoomProvider, "ZoomProvider");
7517
+ var ZoomProvider = _ZoomProvider;
7518
+ var { Consumer: ZoomConsumer } = Context;
7519
+ var Zoom2 = memo(/* @__PURE__ */ __name(function Zoom3({ zoomIn, zoomOut, reset }) {
7520
+ return react_default.createElement(react_default.Fragment, null, react_default.createElement(IconButton, { key: "zoomin", onClick: zoomIn, title: "Zoom in" }, react_default.createElement(ZoomIcon, null)), react_default.createElement(IconButton, { key: "zoomout", onClick: zoomOut, title: "Zoom out" }, react_default.createElement(ZoomOutIcon, null)), react_default.createElement(IconButton, { key: "zoomreset", onClick: reset, title: "Reset zoom" }, react_default.createElement(ZoomResetIcon, null)));
7521
+ }, "Zoom"));
7522
+ var ZoomWrapper = memo(/* @__PURE__ */ __name(function ZoomWrapper2({
7523
+ set: set2,
7524
+ value
7525
+ }) {
7526
+ const zoomIn = useCallback(
7527
+ (e2) => {
7528
+ e2.preventDefault();
7529
+ set2(0.8 * value);
7530
+ },
7531
+ [set2, value]
7532
+ );
7533
+ const zoomOut = useCallback(
7534
+ (e2) => {
7535
+ e2.preventDefault();
7536
+ set2(1.25 * value);
7537
+ },
7538
+ [set2, value]
7539
+ );
7540
+ const reset = useCallback(
7541
+ (e2) => {
7542
+ e2.preventDefault();
7543
+ set2(initialZoom);
7544
+ },
7545
+ [set2, initialZoom]
7546
+ );
7547
+ return react_default.createElement(Zoom2, { key: "zoom", ...{ zoomIn, zoomOut, reset } });
7548
+ }, "ZoomWrapper"));
7549
+ function ZoomToolRenderer() {
7550
+ return react_default.createElement(react_default.Fragment, null, react_default.createElement(ZoomConsumer, null, ({ set: set2, value }) => react_default.createElement(ZoomWrapper, { ...{ set: set2, value } })), react_default.createElement(Separator, null));
7551
+ }
7552
+ __name(ZoomToolRenderer, "ZoomToolRenderer");
7553
+ var zoomTool = {
7554
+ title: "zoom",
7555
+ id: "zoom",
7556
+ type: types.TOOL,
7557
+ match: /* @__PURE__ */ __name(({ viewMode, tabId }) => viewMode === "story" && !tabId, "match"),
7558
+ render: ZoomToolRenderer
7559
+ };
7560
+
7679
7561
  // src/manager/components/preview/Preview.tsx
7680
7562
  var canvasMapper = /* @__PURE__ */ __name(({ state, api }) => ({
7681
7563
  storyId: state.storyId,
@@ -7821,32 +7703,1591 @@ function filterTabs(panels, parameters) {
7821
7703
  hidden: t2.hidden
7822
7704
  };
7823
7705
  }
7824
- return panel;
7825
- });
7826
- }
7827
- return panels;
7828
- }
7829
- __name(filterTabs, "filterTabs");
7830
-
7831
- // src/manager/components/preview/tools/menu.tsx
7832
- var menuMapper3 = /* @__PURE__ */ __name(({ api, state }) => ({
7833
- isVisible: api.getIsNavShown(),
7834
- singleStory: state.singleStory,
7835
- toggle: /* @__PURE__ */ __name(() => api.toggleNav(), "toggle")
7836
- }), "menuMapper");
7837
- var menuTool = {
7838
- title: "menu",
7839
- id: "menu",
7706
+ return panel;
7707
+ });
7708
+ }
7709
+ return panels;
7710
+ }
7711
+ __name(filterTabs, "filterTabs");
7712
+
7713
+ // src/manager/components/preview/tools/addons.tsx
7714
+ var menuMapper = /* @__PURE__ */ __name(({ api, state }) => ({
7715
+ isVisible: api.getIsPanelShown(),
7716
+ singleStory: state.singleStory,
7717
+ panelPosition: state.layout.panelPosition,
7718
+ toggle: /* @__PURE__ */ __name(() => api.togglePanel(), "toggle")
7719
+ }), "menuMapper");
7720
+ var addonsTool = {
7721
+ title: "addons",
7722
+ id: "addons",
7723
+ type: types.TOOL,
7724
+ match: /* @__PURE__ */ __name(({ viewMode, tabId }) => viewMode === "story" && !tabId, "match"),
7725
+ render: /* @__PURE__ */ __name(() => react_default.createElement(Consumer, { filter: menuMapper }, ({ isVisible, toggle, singleStory, panelPosition }) => !singleStory && !isVisible && react_default.createElement(react_default.Fragment, null, react_default.createElement(IconButton, { "aria-label": "Show addons", key: "addons", onClick: toggle, title: "Show addons" }, panelPosition === "bottom" ? react_default.createElement(BottomBarIcon, null) : react_default.createElement(SidebarAltIcon, null)))), "render")
7726
+ };
7727
+
7728
+ // src/manager/components/preview/tools/menu.tsx
7729
+ var menuMapper2 = /* @__PURE__ */ __name(({ api, state }) => ({
7730
+ isVisible: api.getIsNavShown(),
7731
+ singleStory: state.singleStory,
7732
+ toggle: /* @__PURE__ */ __name(() => api.toggleNav(), "toggle")
7733
+ }), "menuMapper");
7734
+ var menuTool = {
7735
+ title: "menu",
7736
+ id: "menu",
7737
+ type: types.TOOL,
7738
+ // @ts-expect-error (non strict)
7739
+ match: /* @__PURE__ */ __name(({ viewMode }) => ["story", "docs"].includes(viewMode), "match"),
7740
+ render: /* @__PURE__ */ __name(() => react_default.createElement(Consumer, { filter: menuMapper2 }, ({ isVisible, toggle, singleStory }) => !singleStory && !isVisible && react_default.createElement(react_default.Fragment, null, react_default.createElement(IconButton, { "aria-label": "Show sidebar", key: "menu", onClick: toggle, title: "Show sidebar" }, react_default.createElement(MenuIcon, null)), react_default.createElement(Separator, null))), "render")
7741
+ };
7742
+
7743
+ // src/manager/components/preview/tools/open-in-editor.tsx
7744
+ var mapper2 = /* @__PURE__ */ __name(({ state, api }) => {
7745
+ const { storyId, refId } = state;
7746
+ const entry = api.getData(storyId, refId);
7747
+ const isCompositionStory = !!refId;
7748
+ return {
7749
+ storyId,
7750
+ isCompositionStory,
7751
+ importPath: entry?.importPath
7752
+ };
7753
+ }, "mapper");
7754
+ var openInEditorTool = {
7755
+ title: "open-in-editor",
7756
+ id: "open-in-editor",
7757
+ type: types.TOOL,
7758
+ match: /* @__PURE__ */ __name(({ viewMode, tabId }) => scope.CONFIG_TYPE === "DEVELOPMENT" && (viewMode === "story" || viewMode === "docs") && !tabId, "match"),
7759
+ render: /* @__PURE__ */ __name(() => react_default.createElement(Consumer, { filter: mapper2 }, ({ importPath, isCompositionStory }) => {
7760
+ const api = useStorybookApi();
7761
+ if (isCompositionStory || !importPath) {
7762
+ return null;
7763
+ }
7764
+ return react_default.createElement(
7765
+ IconButton,
7766
+ {
7767
+ key: "open-in-editor",
7768
+ onClick: () => api.openInEditor({
7769
+ file: importPath
7770
+ }),
7771
+ title: "Open in editor",
7772
+ "aria-label": "Open in editor"
7773
+ },
7774
+ react_default.createElement(EditorIcon, null)
7775
+ );
7776
+ }), "render")
7777
+ };
7778
+
7779
+ // src/manager/components/preview/tools/remount.tsx
7780
+ var StyledAnimatedIconButton = styled(IconButton)(({ theme, animating, disabled }) => ({
7781
+ opacity: disabled ? 0.5 : 1,
7782
+ svg: {
7783
+ animation: animating ? `${theme.animation.rotate360} 1000ms ease-out` : void 0
7784
+ }
7785
+ }));
7786
+ var menuMapper3 = /* @__PURE__ */ __name(({ api, state }) => {
7787
+ const { storyId } = state;
7788
+ return {
7789
+ storyId,
7790
+ remount: /* @__PURE__ */ __name(() => api.emit(FORCE_REMOUNT, { storyId: state.storyId }), "remount"),
7791
+ api
7792
+ };
7793
+ }, "menuMapper");
7794
+ var remountTool = {
7795
+ title: "remount",
7796
+ id: "remount",
7797
+ type: types.TOOL,
7798
+ match: /* @__PURE__ */ __name(({ viewMode, tabId }) => viewMode === "story" && !tabId, "match"),
7799
+ render: /* @__PURE__ */ __name(() => react_default.createElement(Consumer, { filter: menuMapper3 }, ({ remount, storyId, api }) => {
7800
+ const [isAnimating, setIsAnimating] = useState(false);
7801
+ const remountComponent = /* @__PURE__ */ __name(() => {
7802
+ if (!storyId) {
7803
+ return;
7804
+ }
7805
+ remount();
7806
+ }, "remountComponent");
7807
+ api.on(FORCE_REMOUNT, () => {
7808
+ setIsAnimating(true);
7809
+ });
7810
+ return react_default.createElement(
7811
+ StyledAnimatedIconButton,
7812
+ {
7813
+ key: "remount",
7814
+ title: "Remount component",
7815
+ onClick: remountComponent,
7816
+ onAnimationEnd: () => setIsAnimating(false),
7817
+ animating: isAnimating,
7818
+ disabled: !storyId
7819
+ },
7820
+ react_default.createElement(SyncIcon, null)
7821
+ );
7822
+ }), "render")
7823
+ };
7824
+
7825
+ // src/manager/components/preview/tools/share.tsx
7826
+ var import_copy_to_clipboard = __toESM(require_copy_to_clipboard(), 1);
7827
+
7828
+ // ../node_modules/qrcode.react/lib/esm/index.js
7829
+ var __defProp2 = Object.defineProperty;
7830
+ var __getOwnPropSymbols = Object.getOwnPropertySymbols;
7831
+ var __hasOwnProp2 = Object.prototype.hasOwnProperty;
7832
+ var __propIsEnum = Object.prototype.propertyIsEnumerable;
7833
+ var __defNormalProp = /* @__PURE__ */ __name((obj, key, value) => key in obj ? __defProp2(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value, "__defNormalProp");
7834
+ var __spreadValues = /* @__PURE__ */ __name((a2, b2) => {
7835
+ for (var prop in b2 || (b2 = {}))
7836
+ if (__hasOwnProp2.call(b2, prop))
7837
+ __defNormalProp(a2, prop, b2[prop]);
7838
+ if (__getOwnPropSymbols)
7839
+ for (var prop of __getOwnPropSymbols(b2)) {
7840
+ if (__propIsEnum.call(b2, prop))
7841
+ __defNormalProp(a2, prop, b2[prop]);
7842
+ }
7843
+ return a2;
7844
+ }, "__spreadValues");
7845
+ var __objRest = /* @__PURE__ */ __name((source, exclude) => {
7846
+ var target = {};
7847
+ for (var prop in source)
7848
+ if (__hasOwnProp2.call(source, prop) && exclude.indexOf(prop) < 0)
7849
+ target[prop] = source[prop];
7850
+ if (source != null && __getOwnPropSymbols)
7851
+ for (var prop of __getOwnPropSymbols(source)) {
7852
+ if (exclude.indexOf(prop) < 0 && __propIsEnum.call(source, prop))
7853
+ target[prop] = source[prop];
7854
+ }
7855
+ return target;
7856
+ }, "__objRest");
7857
+ var qrcodegen;
7858
+ ((qrcodegen2) => {
7859
+ var _a, _b;
7860
+ const _QrCode = (_a = class {
7861
+ /*-- Constructor (low level) and fields --*/
7862
+ // Creates a new QR Code with the given version number,
7863
+ // error correction level, data codeword bytes, and mask number.
7864
+ // This is a low-level API that most users should not use directly.
7865
+ // A mid-level API is the encodeSegments() function.
7866
+ constructor(version3, errorCorrectionLevel, dataCodewords, msk) {
7867
+ this.version = version3;
7868
+ this.errorCorrectionLevel = errorCorrectionLevel;
7869
+ this.modules = [];
7870
+ this.isFunction = [];
7871
+ if (version3 < _a.MIN_VERSION || version3 > _a.MAX_VERSION)
7872
+ throw new RangeError("Version value out of range");
7873
+ if (msk < -1 || msk > 7)
7874
+ throw new RangeError("Mask value out of range");
7875
+ this.size = version3 * 4 + 17;
7876
+ let row = [];
7877
+ for (let i2 = 0; i2 < this.size; i2++)
7878
+ row.push(false);
7879
+ for (let i2 = 0; i2 < this.size; i2++) {
7880
+ this.modules.push(row.slice());
7881
+ this.isFunction.push(row.slice());
7882
+ }
7883
+ this.drawFunctionPatterns();
7884
+ const allCodewords = this.addEccAndInterleave(dataCodewords);
7885
+ this.drawCodewords(allCodewords);
7886
+ if (msk == -1) {
7887
+ let minPenalty = 1e9;
7888
+ for (let i2 = 0; i2 < 8; i2++) {
7889
+ this.applyMask(i2);
7890
+ this.drawFormatBits(i2);
7891
+ const penalty = this.getPenaltyScore();
7892
+ if (penalty < minPenalty) {
7893
+ msk = i2;
7894
+ minPenalty = penalty;
7895
+ }
7896
+ this.applyMask(i2);
7897
+ }
7898
+ }
7899
+ assert(0 <= msk && msk <= 7);
7900
+ this.mask = msk;
7901
+ this.applyMask(msk);
7902
+ this.drawFormatBits(msk);
7903
+ this.isFunction = [];
7904
+ }
7905
+ /*-- Static factory functions (high level) --*/
7906
+ // Returns a QR Code representing the given Unicode text string at the given error correction level.
7907
+ // As a conservative upper bound, this function is guaranteed to succeed for strings that have 738 or fewer
7908
+ // Unicode code points (not UTF-16 code units) if the low error correction level is used. The smallest possible
7909
+ // QR Code version is automatically chosen for the output. The ECC level of the result may be higher than the
7910
+ // ecl argument if it can be done without increasing the version.
7911
+ static encodeText(text, ecl) {
7912
+ const segs = qrcodegen2.QrSegment.makeSegments(text);
7913
+ return _a.encodeSegments(segs, ecl);
7914
+ }
7915
+ // Returns a QR Code representing the given binary data at the given error correction level.
7916
+ // This function always encodes using the binary segment mode, not any text mode. The maximum number of
7917
+ // bytes allowed is 2953. The smallest possible QR Code version is automatically chosen for the output.
7918
+ // The ECC level of the result may be higher than the ecl argument if it can be done without increasing the version.
7919
+ static encodeBinary(data, ecl) {
7920
+ const seg = qrcodegen2.QrSegment.makeBytes(data);
7921
+ return _a.encodeSegments([seg], ecl);
7922
+ }
7923
+ /*-- Static factory functions (mid level) --*/
7924
+ // Returns a QR Code representing the given segments with the given encoding parameters.
7925
+ // The smallest possible QR Code version within the given range is automatically
7926
+ // chosen for the output. Iff boostEcl is true, then the ECC level of the result
7927
+ // may be higher than the ecl argument if it can be done without increasing the
7928
+ // version. The mask number is either between 0 to 7 (inclusive) to force that
7929
+ // mask, or -1 to automatically choose an appropriate mask (which may be slow).
7930
+ // This function allows the user to create a custom sequence of segments that switches
7931
+ // between modes (such as alphanumeric and byte) to encode text in less space.
7932
+ // This is a mid-level API; the high-level API is encodeText() and encodeBinary().
7933
+ static encodeSegments(segs, ecl, minVersion = 1, maxVersion = 40, mask = -1, boostEcl = true) {
7934
+ if (!(_a.MIN_VERSION <= minVersion && minVersion <= maxVersion && maxVersion <= _a.MAX_VERSION) || mask < -1 || mask > 7)
7935
+ throw new RangeError("Invalid value");
7936
+ let version3;
7937
+ let dataUsedBits;
7938
+ for (version3 = minVersion; ; version3++) {
7939
+ const dataCapacityBits2 = _a.getNumDataCodewords(version3, ecl) * 8;
7940
+ const usedBits = QrSegment.getTotalBits(segs, version3);
7941
+ if (usedBits <= dataCapacityBits2) {
7942
+ dataUsedBits = usedBits;
7943
+ break;
7944
+ }
7945
+ if (version3 >= maxVersion)
7946
+ throw new RangeError("Data too long");
7947
+ }
7948
+ for (const newEcl of [_a.Ecc.MEDIUM, _a.Ecc.QUARTILE, _a.Ecc.HIGH]) {
7949
+ if (boostEcl && dataUsedBits <= _a.getNumDataCodewords(version3, newEcl) * 8)
7950
+ ecl = newEcl;
7951
+ }
7952
+ let bb = [];
7953
+ for (const seg of segs) {
7954
+ appendBits(seg.mode.modeBits, 4, bb);
7955
+ appendBits(seg.numChars, seg.mode.numCharCountBits(version3), bb);
7956
+ for (const b2 of seg.getData())
7957
+ bb.push(b2);
7958
+ }
7959
+ assert(bb.length == dataUsedBits);
7960
+ const dataCapacityBits = _a.getNumDataCodewords(version3, ecl) * 8;
7961
+ assert(bb.length <= dataCapacityBits);
7962
+ appendBits(0, Math.min(4, dataCapacityBits - bb.length), bb);
7963
+ appendBits(0, (8 - bb.length % 8) % 8, bb);
7964
+ assert(bb.length % 8 == 0);
7965
+ for (let padByte = 236; bb.length < dataCapacityBits; padByte ^= 236 ^ 17)
7966
+ appendBits(padByte, 8, bb);
7967
+ let dataCodewords = [];
7968
+ while (dataCodewords.length * 8 < bb.length)
7969
+ dataCodewords.push(0);
7970
+ bb.forEach((b2, i2) => dataCodewords[i2 >>> 3] |= b2 << 7 - (i2 & 7));
7971
+ return new _a(version3, ecl, dataCodewords, mask);
7972
+ }
7973
+ /*-- Accessor methods --*/
7974
+ // Returns the color of the module (pixel) at the given coordinates, which is false
7975
+ // for light or true for dark. The top left corner has the coordinates (x=0, y=0).
7976
+ // If the given coordinates are out of bounds, then false (light) is returned.
7977
+ getModule(x2, y2) {
7978
+ return 0 <= x2 && x2 < this.size && 0 <= y2 && y2 < this.size && this.modules[y2][x2];
7979
+ }
7980
+ // Modified to expose modules for easy access
7981
+ getModules() {
7982
+ return this.modules;
7983
+ }
7984
+ /*-- Private helper methods for constructor: Drawing function modules --*/
7985
+ // Reads this object's version field, and draws and marks all function modules.
7986
+ drawFunctionPatterns() {
7987
+ for (let i2 = 0; i2 < this.size; i2++) {
7988
+ this.setFunctionModule(6, i2, i2 % 2 == 0);
7989
+ this.setFunctionModule(i2, 6, i2 % 2 == 0);
7990
+ }
7991
+ this.drawFinderPattern(3, 3);
7992
+ this.drawFinderPattern(this.size - 4, 3);
7993
+ this.drawFinderPattern(3, this.size - 4);
7994
+ const alignPatPos = this.getAlignmentPatternPositions();
7995
+ const numAlign = alignPatPos.length;
7996
+ for (let i2 = 0; i2 < numAlign; i2++) {
7997
+ for (let j2 = 0; j2 < numAlign; j2++) {
7998
+ if (!(i2 == 0 && j2 == 0 || i2 == 0 && j2 == numAlign - 1 || i2 == numAlign - 1 && j2 == 0))
7999
+ this.drawAlignmentPattern(alignPatPos[i2], alignPatPos[j2]);
8000
+ }
8001
+ }
8002
+ this.drawFormatBits(0);
8003
+ this.drawVersion();
8004
+ }
8005
+ // Draws two copies of the format bits (with its own error correction code)
8006
+ // based on the given mask and this object's error correction level field.
8007
+ drawFormatBits(mask) {
8008
+ const data = this.errorCorrectionLevel.formatBits << 3 | mask;
8009
+ let rem2 = data;
8010
+ for (let i2 = 0; i2 < 10; i2++)
8011
+ rem2 = rem2 << 1 ^ (rem2 >>> 9) * 1335;
8012
+ const bits = (data << 10 | rem2) ^ 21522;
8013
+ assert(bits >>> 15 == 0);
8014
+ for (let i2 = 0; i2 <= 5; i2++)
8015
+ this.setFunctionModule(8, i2, getBit(bits, i2));
8016
+ this.setFunctionModule(8, 7, getBit(bits, 6));
8017
+ this.setFunctionModule(8, 8, getBit(bits, 7));
8018
+ this.setFunctionModule(7, 8, getBit(bits, 8));
8019
+ for (let i2 = 9; i2 < 15; i2++)
8020
+ this.setFunctionModule(14 - i2, 8, getBit(bits, i2));
8021
+ for (let i2 = 0; i2 < 8; i2++)
8022
+ this.setFunctionModule(this.size - 1 - i2, 8, getBit(bits, i2));
8023
+ for (let i2 = 8; i2 < 15; i2++)
8024
+ this.setFunctionModule(8, this.size - 15 + i2, getBit(bits, i2));
8025
+ this.setFunctionModule(8, this.size - 8, true);
8026
+ }
8027
+ // Draws two copies of the version bits (with its own error correction code),
8028
+ // based on this object's version field, iff 7 <= version <= 40.
8029
+ drawVersion() {
8030
+ if (this.version < 7)
8031
+ return;
8032
+ let rem2 = this.version;
8033
+ for (let i2 = 0; i2 < 12; i2++)
8034
+ rem2 = rem2 << 1 ^ (rem2 >>> 11) * 7973;
8035
+ const bits = this.version << 12 | rem2;
8036
+ assert(bits >>> 18 == 0);
8037
+ for (let i2 = 0; i2 < 18; i2++) {
8038
+ const color2 = getBit(bits, i2);
8039
+ const a2 = this.size - 11 + i2 % 3;
8040
+ const b2 = Math.floor(i2 / 3);
8041
+ this.setFunctionModule(a2, b2, color2);
8042
+ this.setFunctionModule(b2, a2, color2);
8043
+ }
8044
+ }
8045
+ // Draws a 9*9 finder pattern including the border separator,
8046
+ // with the center module at (x, y). Modules can be out of bounds.
8047
+ drawFinderPattern(x2, y2) {
8048
+ for (let dy = -4; dy <= 4; dy++) {
8049
+ for (let dx = -4; dx <= 4; dx++) {
8050
+ const dist = Math.max(Math.abs(dx), Math.abs(dy));
8051
+ const xx = x2 + dx;
8052
+ const yy = y2 + dy;
8053
+ if (0 <= xx && xx < this.size && 0 <= yy && yy < this.size)
8054
+ this.setFunctionModule(xx, yy, dist != 2 && dist != 4);
8055
+ }
8056
+ }
8057
+ }
8058
+ // Draws a 5*5 alignment pattern, with the center module
8059
+ // at (x, y). All modules must be in bounds.
8060
+ drawAlignmentPattern(x2, y2) {
8061
+ for (let dy = -2; dy <= 2; dy++) {
8062
+ for (let dx = -2; dx <= 2; dx++)
8063
+ this.setFunctionModule(x2 + dx, y2 + dy, Math.max(Math.abs(dx), Math.abs(dy)) != 1);
8064
+ }
8065
+ }
8066
+ // Sets the color of a module and marks it as a function module.
8067
+ // Only used by the constructor. Coordinates must be in bounds.
8068
+ setFunctionModule(x2, y2, isDark) {
8069
+ this.modules[y2][x2] = isDark;
8070
+ this.isFunction[y2][x2] = true;
8071
+ }
8072
+ /*-- Private helper methods for constructor: Codewords and masking --*/
8073
+ // Returns a new byte string representing the given data with the appropriate error correction
8074
+ // codewords appended to it, based on this object's version and error correction level.
8075
+ addEccAndInterleave(data) {
8076
+ const ver = this.version;
8077
+ const ecl = this.errorCorrectionLevel;
8078
+ if (data.length != _a.getNumDataCodewords(ver, ecl))
8079
+ throw new RangeError("Invalid argument");
8080
+ const numBlocks = _a.NUM_ERROR_CORRECTION_BLOCKS[ecl.ordinal][ver];
8081
+ const blockEccLen = _a.ECC_CODEWORDS_PER_BLOCK[ecl.ordinal][ver];
8082
+ const rawCodewords = Math.floor(_a.getNumRawDataModules(ver) / 8);
8083
+ const numShortBlocks = numBlocks - rawCodewords % numBlocks;
8084
+ const shortBlockLen = Math.floor(rawCodewords / numBlocks);
8085
+ let blocks = [];
8086
+ const rsDiv = _a.reedSolomonComputeDivisor(blockEccLen);
8087
+ for (let i2 = 0, k2 = 0; i2 < numBlocks; i2++) {
8088
+ let dat = data.slice(k2, k2 + shortBlockLen - blockEccLen + (i2 < numShortBlocks ? 0 : 1));
8089
+ k2 += dat.length;
8090
+ const ecc = _a.reedSolomonComputeRemainder(dat, rsDiv);
8091
+ if (i2 < numShortBlocks)
8092
+ dat.push(0);
8093
+ blocks.push(dat.concat(ecc));
8094
+ }
8095
+ let result2 = [];
8096
+ for (let i2 = 0; i2 < blocks[0].length; i2++) {
8097
+ blocks.forEach((block, j2) => {
8098
+ if (i2 != shortBlockLen - blockEccLen || j2 >= numShortBlocks)
8099
+ result2.push(block[i2]);
8100
+ });
8101
+ }
8102
+ assert(result2.length == rawCodewords);
8103
+ return result2;
8104
+ }
8105
+ // Draws the given sequence of 8-bit codewords (data and error correction) onto the entire
8106
+ // data area of this QR Code. Function modules need to be marked off before this is called.
8107
+ drawCodewords(data) {
8108
+ if (data.length != Math.floor(_a.getNumRawDataModules(this.version) / 8))
8109
+ throw new RangeError("Invalid argument");
8110
+ let i2 = 0;
8111
+ for (let right = this.size - 1; right >= 1; right -= 2) {
8112
+ if (right == 6)
8113
+ right = 5;
8114
+ for (let vert = 0; vert < this.size; vert++) {
8115
+ for (let j2 = 0; j2 < 2; j2++) {
8116
+ const x2 = right - j2;
8117
+ const upward = (right + 1 & 2) == 0;
8118
+ const y2 = upward ? this.size - 1 - vert : vert;
8119
+ if (!this.isFunction[y2][x2] && i2 < data.length * 8) {
8120
+ this.modules[y2][x2] = getBit(data[i2 >>> 3], 7 - (i2 & 7));
8121
+ i2++;
8122
+ }
8123
+ }
8124
+ }
8125
+ }
8126
+ assert(i2 == data.length * 8);
8127
+ }
8128
+ // XORs the codeword modules in this QR Code with the given mask pattern.
8129
+ // The function modules must be marked and the codeword bits must be drawn
8130
+ // before masking. Due to the arithmetic of XOR, calling applyMask() with
8131
+ // the same mask value a second time will undo the mask. A final well-formed
8132
+ // QR Code needs exactly one (not zero, two, etc.) mask applied.
8133
+ applyMask(mask) {
8134
+ if (mask < 0 || mask > 7)
8135
+ throw new RangeError("Mask value out of range");
8136
+ for (let y2 = 0; y2 < this.size; y2++) {
8137
+ for (let x2 = 0; x2 < this.size; x2++) {
8138
+ let invert3;
8139
+ switch (mask) {
8140
+ case 0:
8141
+ invert3 = (x2 + y2) % 2 == 0;
8142
+ break;
8143
+ case 1:
8144
+ invert3 = y2 % 2 == 0;
8145
+ break;
8146
+ case 2:
8147
+ invert3 = x2 % 3 == 0;
8148
+ break;
8149
+ case 3:
8150
+ invert3 = (x2 + y2) % 3 == 0;
8151
+ break;
8152
+ case 4:
8153
+ invert3 = (Math.floor(x2 / 3) + Math.floor(y2 / 2)) % 2 == 0;
8154
+ break;
8155
+ case 5:
8156
+ invert3 = x2 * y2 % 2 + x2 * y2 % 3 == 0;
8157
+ break;
8158
+ case 6:
8159
+ invert3 = (x2 * y2 % 2 + x2 * y2 % 3) % 2 == 0;
8160
+ break;
8161
+ case 7:
8162
+ invert3 = ((x2 + y2) % 2 + x2 * y2 % 3) % 2 == 0;
8163
+ break;
8164
+ default:
8165
+ throw new Error("Unreachable");
8166
+ }
8167
+ if (!this.isFunction[y2][x2] && invert3)
8168
+ this.modules[y2][x2] = !this.modules[y2][x2];
8169
+ }
8170
+ }
8171
+ }
8172
+ // Calculates and returns the penalty score based on state of this QR Code's current modules.
8173
+ // This is used by the automatic mask choice algorithm to find the mask pattern that yields the lowest score.
8174
+ getPenaltyScore() {
8175
+ let result2 = 0;
8176
+ for (let y2 = 0; y2 < this.size; y2++) {
8177
+ let runColor = false;
8178
+ let runX = 0;
8179
+ let runHistory = [0, 0, 0, 0, 0, 0, 0];
8180
+ for (let x2 = 0; x2 < this.size; x2++) {
8181
+ if (this.modules[y2][x2] == runColor) {
8182
+ runX++;
8183
+ if (runX == 5)
8184
+ result2 += _a.PENALTY_N1;
8185
+ else if (runX > 5)
8186
+ result2++;
8187
+ } else {
8188
+ this.finderPenaltyAddHistory(runX, runHistory);
8189
+ if (!runColor)
8190
+ result2 += this.finderPenaltyCountPatterns(runHistory) * _a.PENALTY_N3;
8191
+ runColor = this.modules[y2][x2];
8192
+ runX = 1;
8193
+ }
8194
+ }
8195
+ result2 += this.finderPenaltyTerminateAndCount(runColor, runX, runHistory) * _a.PENALTY_N3;
8196
+ }
8197
+ for (let x2 = 0; x2 < this.size; x2++) {
8198
+ let runColor = false;
8199
+ let runY = 0;
8200
+ let runHistory = [0, 0, 0, 0, 0, 0, 0];
8201
+ for (let y2 = 0; y2 < this.size; y2++) {
8202
+ if (this.modules[y2][x2] == runColor) {
8203
+ runY++;
8204
+ if (runY == 5)
8205
+ result2 += _a.PENALTY_N1;
8206
+ else if (runY > 5)
8207
+ result2++;
8208
+ } else {
8209
+ this.finderPenaltyAddHistory(runY, runHistory);
8210
+ if (!runColor)
8211
+ result2 += this.finderPenaltyCountPatterns(runHistory) * _a.PENALTY_N3;
8212
+ runColor = this.modules[y2][x2];
8213
+ runY = 1;
8214
+ }
8215
+ }
8216
+ result2 += this.finderPenaltyTerminateAndCount(runColor, runY, runHistory) * _a.PENALTY_N3;
8217
+ }
8218
+ for (let y2 = 0; y2 < this.size - 1; y2++) {
8219
+ for (let x2 = 0; x2 < this.size - 1; x2++) {
8220
+ const color2 = this.modules[y2][x2];
8221
+ if (color2 == this.modules[y2][x2 + 1] && color2 == this.modules[y2 + 1][x2] && color2 == this.modules[y2 + 1][x2 + 1])
8222
+ result2 += _a.PENALTY_N2;
8223
+ }
8224
+ }
8225
+ let dark = 0;
8226
+ for (const row of this.modules)
8227
+ dark = row.reduce((sum3, color2) => sum3 + (color2 ? 1 : 0), dark);
8228
+ const total = this.size * this.size;
8229
+ const k2 = Math.ceil(Math.abs(dark * 20 - total * 10) / total) - 1;
8230
+ assert(0 <= k2 && k2 <= 9);
8231
+ result2 += k2 * _a.PENALTY_N4;
8232
+ assert(0 <= result2 && result2 <= 2568888);
8233
+ return result2;
8234
+ }
8235
+ /*-- Private helper functions --*/
8236
+ // Returns an ascending list of positions of alignment patterns for this version number.
8237
+ // Each position is in the range [0,177), and are used on both the x and y axes.
8238
+ // This could be implemented as lookup table of 40 variable-length lists of integers.
8239
+ getAlignmentPatternPositions() {
8240
+ if (this.version == 1)
8241
+ return [];
8242
+ else {
8243
+ const numAlign = Math.floor(this.version / 7) + 2;
8244
+ const step = this.version == 32 ? 26 : Math.ceil((this.version * 4 + 4) / (numAlign * 2 - 2)) * 2;
8245
+ let result2 = [6];
8246
+ for (let pos = this.size - 7; result2.length < numAlign; pos -= step)
8247
+ result2.splice(1, 0, pos);
8248
+ return result2;
8249
+ }
8250
+ }
8251
+ // Returns the number of data bits that can be stored in a QR Code of the given version number, after
8252
+ // all function modules are excluded. This includes remainder bits, so it might not be a multiple of 8.
8253
+ // The result is in the range [208, 29648]. This could be implemented as a 40-entry lookup table.
8254
+ static getNumRawDataModules(ver) {
8255
+ if (ver < _a.MIN_VERSION || ver > _a.MAX_VERSION)
8256
+ throw new RangeError("Version number out of range");
8257
+ let result2 = (16 * ver + 128) * ver + 64;
8258
+ if (ver >= 2) {
8259
+ const numAlign = Math.floor(ver / 7) + 2;
8260
+ result2 -= (25 * numAlign - 10) * numAlign - 55;
8261
+ if (ver >= 7)
8262
+ result2 -= 36;
8263
+ }
8264
+ assert(208 <= result2 && result2 <= 29648);
8265
+ return result2;
8266
+ }
8267
+ // Returns the number of 8-bit data (i.e. not error correction) codewords contained in any
8268
+ // QR Code of the given version number and error correction level, with remainder bits discarded.
8269
+ // This stateless pure function could be implemented as a (40*4)-cell lookup table.
8270
+ static getNumDataCodewords(ver, ecl) {
8271
+ return Math.floor(_a.getNumRawDataModules(ver) / 8) - _a.ECC_CODEWORDS_PER_BLOCK[ecl.ordinal][ver] * _a.NUM_ERROR_CORRECTION_BLOCKS[ecl.ordinal][ver];
8272
+ }
8273
+ // Returns a Reed-Solomon ECC generator polynomial for the given degree. This could be
8274
+ // implemented as a lookup table over all possible parameter values, instead of as an algorithm.
8275
+ static reedSolomonComputeDivisor(degree) {
8276
+ if (degree < 1 || degree > 255)
8277
+ throw new RangeError("Degree out of range");
8278
+ let result2 = [];
8279
+ for (let i2 = 0; i2 < degree - 1; i2++)
8280
+ result2.push(0);
8281
+ result2.push(1);
8282
+ let root = 1;
8283
+ for (let i2 = 0; i2 < degree; i2++) {
8284
+ for (let j2 = 0; j2 < result2.length; j2++) {
8285
+ result2[j2] = _a.reedSolomonMultiply(result2[j2], root);
8286
+ if (j2 + 1 < result2.length)
8287
+ result2[j2] ^= result2[j2 + 1];
8288
+ }
8289
+ root = _a.reedSolomonMultiply(root, 2);
8290
+ }
8291
+ return result2;
8292
+ }
8293
+ // Returns the Reed-Solomon error correction codeword for the given data and divisor polynomials.
8294
+ static reedSolomonComputeRemainder(data, divisor) {
8295
+ let result2 = divisor.map((_2) => 0);
8296
+ for (const b2 of data) {
8297
+ const factor = b2 ^ result2.shift();
8298
+ result2.push(0);
8299
+ divisor.forEach((coef, i2) => result2[i2] ^= _a.reedSolomonMultiply(coef, factor));
8300
+ }
8301
+ return result2;
8302
+ }
8303
+ // Returns the product of the two given field elements modulo GF(2^8/0x11D). The arguments and result
8304
+ // are unsigned 8-bit integers. This could be implemented as a lookup table of 256*256 entries of uint8.
8305
+ static reedSolomonMultiply(x2, y2) {
8306
+ if (x2 >>> 8 != 0 || y2 >>> 8 != 0)
8307
+ throw new RangeError("Byte out of range");
8308
+ let z2 = 0;
8309
+ for (let i2 = 7; i2 >= 0; i2--) {
8310
+ z2 = z2 << 1 ^ (z2 >>> 7) * 285;
8311
+ z2 ^= (y2 >>> i2 & 1) * x2;
8312
+ }
8313
+ assert(z2 >>> 8 == 0);
8314
+ return z2;
8315
+ }
8316
+ // Can only be called immediately after a light run is added, and
8317
+ // returns either 0, 1, or 2. A helper function for getPenaltyScore().
8318
+ finderPenaltyCountPatterns(runHistory) {
8319
+ const n3 = runHistory[1];
8320
+ assert(n3 <= this.size * 3);
8321
+ const core = n3 > 0 && runHistory[2] == n3 && runHistory[3] == n3 * 3 && runHistory[4] == n3 && runHistory[5] == n3;
8322
+ return (core && runHistory[0] >= n3 * 4 && runHistory[6] >= n3 ? 1 : 0) + (core && runHistory[6] >= n3 * 4 && runHistory[0] >= n3 ? 1 : 0);
8323
+ }
8324
+ // Must be called at the end of a line (row or column) of modules. A helper function for getPenaltyScore().
8325
+ finderPenaltyTerminateAndCount(currentRunColor, currentRunLength, runHistory) {
8326
+ if (currentRunColor) {
8327
+ this.finderPenaltyAddHistory(currentRunLength, runHistory);
8328
+ currentRunLength = 0;
8329
+ }
8330
+ currentRunLength += this.size;
8331
+ this.finderPenaltyAddHistory(currentRunLength, runHistory);
8332
+ return this.finderPenaltyCountPatterns(runHistory);
8333
+ }
8334
+ // Pushes the given value to the front and drops the last value. A helper function for getPenaltyScore().
8335
+ finderPenaltyAddHistory(currentRunLength, runHistory) {
8336
+ if (runHistory[0] == 0)
8337
+ currentRunLength += this.size;
8338
+ runHistory.pop();
8339
+ runHistory.unshift(currentRunLength);
8340
+ }
8341
+ }, __name(_a, "_QrCode"), _a);
8342
+ _QrCode.MIN_VERSION = 1;
8343
+ _QrCode.MAX_VERSION = 40;
8344
+ _QrCode.PENALTY_N1 = 3;
8345
+ _QrCode.PENALTY_N2 = 3;
8346
+ _QrCode.PENALTY_N3 = 40;
8347
+ _QrCode.PENALTY_N4 = 10;
8348
+ _QrCode.ECC_CODEWORDS_PER_BLOCK = [
8349
+ // Version: (note that index 0 is for padding, and is set to an illegal value)
8350
+ //0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40 Error correction level
8351
+ [-1, 7, 10, 15, 20, 26, 18, 20, 24, 30, 18, 20, 24, 26, 30, 22, 24, 28, 30, 28, 28, 28, 28, 30, 30, 26, 28, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30],
8352
+ // Low
8353
+ [-1, 10, 16, 26, 18, 24, 16, 18, 22, 22, 26, 30, 22, 22, 24, 24, 28, 28, 26, 26, 26, 26, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28],
8354
+ // Medium
8355
+ [-1, 13, 22, 18, 26, 18, 24, 18, 22, 20, 24, 28, 26, 24, 20, 30, 24, 28, 28, 26, 30, 28, 30, 30, 30, 30, 28, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30],
8356
+ // Quartile
8357
+ [-1, 17, 28, 22, 16, 22, 28, 26, 26, 24, 28, 24, 28, 22, 24, 24, 30, 28, 28, 26, 28, 30, 24, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30]
8358
+ // High
8359
+ ];
8360
+ _QrCode.NUM_ERROR_CORRECTION_BLOCKS = [
8361
+ // Version: (note that index 0 is for padding, and is set to an illegal value)
8362
+ //0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40 Error correction level
8363
+ [-1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 4, 4, 4, 4, 4, 6, 6, 6, 6, 7, 8, 8, 9, 9, 10, 12, 12, 12, 13, 14, 15, 16, 17, 18, 19, 19, 20, 21, 22, 24, 25],
8364
+ // Low
8365
+ [-1, 1, 1, 1, 2, 2, 4, 4, 4, 5, 5, 5, 8, 9, 9, 10, 10, 11, 13, 14, 16, 17, 17, 18, 20, 21, 23, 25, 26, 28, 29, 31, 33, 35, 37, 38, 40, 43, 45, 47, 49],
8366
+ // Medium
8367
+ [-1, 1, 1, 2, 2, 4, 4, 6, 6, 8, 8, 8, 10, 12, 16, 12, 17, 16, 18, 21, 20, 23, 23, 25, 27, 29, 34, 34, 35, 38, 40, 43, 45, 48, 51, 53, 56, 59, 62, 65, 68],
8368
+ // Quartile
8369
+ [-1, 1, 1, 2, 4, 4, 4, 5, 6, 8, 8, 11, 11, 16, 16, 18, 16, 19, 21, 25, 25, 25, 34, 30, 32, 35, 37, 40, 42, 45, 48, 51, 54, 57, 60, 63, 66, 70, 74, 77, 81]
8370
+ // High
8371
+ ];
8372
+ let QrCode = _QrCode;
8373
+ qrcodegen2.QrCode = _QrCode;
8374
+ function appendBits(val, len, bb) {
8375
+ if (len < 0 || len > 31 || val >>> len != 0)
8376
+ throw new RangeError("Value out of range");
8377
+ for (let i2 = len - 1; i2 >= 0; i2--)
8378
+ bb.push(val >>> i2 & 1);
8379
+ }
8380
+ __name(appendBits, "appendBits");
8381
+ function getBit(x2, i2) {
8382
+ return (x2 >>> i2 & 1) != 0;
8383
+ }
8384
+ __name(getBit, "getBit");
8385
+ function assert(cond2) {
8386
+ if (!cond2)
8387
+ throw new Error("Assertion error");
8388
+ }
8389
+ __name(assert, "assert");
8390
+ const _QrSegment = (_b = class {
8391
+ /*-- Constructor (low level) and fields --*/
8392
+ // Creates a new QR Code segment with the given attributes and data.
8393
+ // The character count (numChars) must agree with the mode and the bit buffer length,
8394
+ // but the constraint isn't checked. The given bit buffer is cloned and stored.
8395
+ constructor(mode, numChars, bitData) {
8396
+ this.mode = mode;
8397
+ this.numChars = numChars;
8398
+ this.bitData = bitData;
8399
+ if (numChars < 0)
8400
+ throw new RangeError("Invalid argument");
8401
+ this.bitData = bitData.slice();
8402
+ }
8403
+ /*-- Static factory functions (mid level) --*/
8404
+ // Returns a segment representing the given binary data encoded in
8405
+ // byte mode. All input byte arrays are acceptable. Any text string
8406
+ // can be converted to UTF-8 bytes and encoded as a byte mode segment.
8407
+ static makeBytes(data) {
8408
+ let bb = [];
8409
+ for (const b2 of data)
8410
+ appendBits(b2, 8, bb);
8411
+ return new _b(_b.Mode.BYTE, data.length, bb);
8412
+ }
8413
+ // Returns a segment representing the given string of decimal digits encoded in numeric mode.
8414
+ static makeNumeric(digits) {
8415
+ if (!_b.isNumeric(digits))
8416
+ throw new RangeError("String contains non-numeric characters");
8417
+ let bb = [];
8418
+ for (let i2 = 0; i2 < digits.length; ) {
8419
+ const n3 = Math.min(digits.length - i2, 3);
8420
+ appendBits(parseInt(digits.substring(i2, i2 + n3), 10), n3 * 3 + 1, bb);
8421
+ i2 += n3;
8422
+ }
8423
+ return new _b(_b.Mode.NUMERIC, digits.length, bb);
8424
+ }
8425
+ // Returns a segment representing the given text string encoded in alphanumeric mode.
8426
+ // The characters allowed are: 0 to 9, A to Z (uppercase only), space,
8427
+ // dollar, percent, asterisk, plus, hyphen, period, slash, colon.
8428
+ static makeAlphanumeric(text) {
8429
+ if (!_b.isAlphanumeric(text))
8430
+ throw new RangeError("String contains unencodable characters in alphanumeric mode");
8431
+ let bb = [];
8432
+ let i2;
8433
+ for (i2 = 0; i2 + 2 <= text.length; i2 += 2) {
8434
+ let temp = _b.ALPHANUMERIC_CHARSET.indexOf(text.charAt(i2)) * 45;
8435
+ temp += _b.ALPHANUMERIC_CHARSET.indexOf(text.charAt(i2 + 1));
8436
+ appendBits(temp, 11, bb);
8437
+ }
8438
+ if (i2 < text.length)
8439
+ appendBits(_b.ALPHANUMERIC_CHARSET.indexOf(text.charAt(i2)), 6, bb);
8440
+ return new _b(_b.Mode.ALPHANUMERIC, text.length, bb);
8441
+ }
8442
+ // Returns a new mutable list of zero or more segments to represent the given Unicode text string.
8443
+ // The result may use various segment modes and switch modes to optimize the length of the bit stream.
8444
+ static makeSegments(text) {
8445
+ if (text == "")
8446
+ return [];
8447
+ else if (_b.isNumeric(text))
8448
+ return [_b.makeNumeric(text)];
8449
+ else if (_b.isAlphanumeric(text))
8450
+ return [_b.makeAlphanumeric(text)];
8451
+ else
8452
+ return [_b.makeBytes(_b.toUtf8ByteArray(text))];
8453
+ }
8454
+ // Returns a segment representing an Extended Channel Interpretation
8455
+ // (ECI) designator with the given assignment value.
8456
+ static makeEci(assignVal) {
8457
+ let bb = [];
8458
+ if (assignVal < 0)
8459
+ throw new RangeError("ECI assignment value out of range");
8460
+ else if (assignVal < 1 << 7)
8461
+ appendBits(assignVal, 8, bb);
8462
+ else if (assignVal < 1 << 14) {
8463
+ appendBits(2, 2, bb);
8464
+ appendBits(assignVal, 14, bb);
8465
+ } else if (assignVal < 1e6) {
8466
+ appendBits(6, 3, bb);
8467
+ appendBits(assignVal, 21, bb);
8468
+ } else
8469
+ throw new RangeError("ECI assignment value out of range");
8470
+ return new _b(_b.Mode.ECI, 0, bb);
8471
+ }
8472
+ // Tests whether the given string can be encoded as a segment in numeric mode.
8473
+ // A string is encodable iff each character is in the range 0 to 9.
8474
+ static isNumeric(text) {
8475
+ return _b.NUMERIC_REGEX.test(text);
8476
+ }
8477
+ // Tests whether the given string can be encoded as a segment in alphanumeric mode.
8478
+ // A string is encodable iff each character is in the following set: 0 to 9, A to Z
8479
+ // (uppercase only), space, dollar, percent, asterisk, plus, hyphen, period, slash, colon.
8480
+ static isAlphanumeric(text) {
8481
+ return _b.ALPHANUMERIC_REGEX.test(text);
8482
+ }
8483
+ /*-- Methods --*/
8484
+ // Returns a new copy of the data bits of this segment.
8485
+ getData() {
8486
+ return this.bitData.slice();
8487
+ }
8488
+ // (Package-private) Calculates and returns the number of bits needed to encode the given segments at
8489
+ // the given version. The result is infinity if a segment has too many characters to fit its length field.
8490
+ static getTotalBits(segs, version3) {
8491
+ let result2 = 0;
8492
+ for (const seg of segs) {
8493
+ const ccbits = seg.mode.numCharCountBits(version3);
8494
+ if (seg.numChars >= 1 << ccbits)
8495
+ return Infinity;
8496
+ result2 += 4 + ccbits + seg.bitData.length;
8497
+ }
8498
+ return result2;
8499
+ }
8500
+ // Returns a new array of bytes representing the given string encoded in UTF-8.
8501
+ static toUtf8ByteArray(str) {
8502
+ str = encodeURI(str);
8503
+ let result2 = [];
8504
+ for (let i2 = 0; i2 < str.length; i2++) {
8505
+ if (str.charAt(i2) != "%")
8506
+ result2.push(str.charCodeAt(i2));
8507
+ else {
8508
+ result2.push(parseInt(str.substring(i2 + 1, i2 + 3), 16));
8509
+ i2 += 2;
8510
+ }
8511
+ }
8512
+ return result2;
8513
+ }
8514
+ }, __name(_b, "_QrSegment"), _b);
8515
+ _QrSegment.NUMERIC_REGEX = /^[0-9]*$/;
8516
+ _QrSegment.ALPHANUMERIC_REGEX = /^[A-Z0-9 $%*+.\/:-]*$/;
8517
+ _QrSegment.ALPHANUMERIC_CHARSET = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ $%*+-./:";
8518
+ let QrSegment = _QrSegment;
8519
+ qrcodegen2.QrSegment = _QrSegment;
8520
+ })(qrcodegen || (qrcodegen = {}));
8521
+ ((qrcodegen2) => {
8522
+ let QrCode;
8523
+ ((QrCode2) => {
8524
+ var _a;
8525
+ const _Ecc = (_a = class {
8526
+ // The QR Code can tolerate about 30% erroneous codewords
8527
+ /*-- Constructor and fields --*/
8528
+ constructor(ordinal, formatBits) {
8529
+ this.ordinal = ordinal;
8530
+ this.formatBits = formatBits;
8531
+ }
8532
+ }, __name(_a, "_Ecc"), _a);
8533
+ _Ecc.LOW = new _Ecc(0, 1);
8534
+ _Ecc.MEDIUM = new _Ecc(1, 0);
8535
+ _Ecc.QUARTILE = new _Ecc(2, 3);
8536
+ _Ecc.HIGH = new _Ecc(3, 2);
8537
+ let Ecc = _Ecc;
8538
+ QrCode2.Ecc = _Ecc;
8539
+ })(QrCode = qrcodegen2.QrCode || (qrcodegen2.QrCode = {}));
8540
+ })(qrcodegen || (qrcodegen = {}));
8541
+ ((qrcodegen2) => {
8542
+ let QrSegment;
8543
+ ((QrSegment2) => {
8544
+ var _a;
8545
+ const _Mode = (_a = class {
8546
+ /*-- Constructor and fields --*/
8547
+ constructor(modeBits, numBitsCharCount) {
8548
+ this.modeBits = modeBits;
8549
+ this.numBitsCharCount = numBitsCharCount;
8550
+ }
8551
+ /*-- Method --*/
8552
+ // (Package-private) Returns the bit width of the character count field for a segment in
8553
+ // this mode in a QR Code at the given version number. The result is in the range [0, 16].
8554
+ numCharCountBits(ver) {
8555
+ return this.numBitsCharCount[Math.floor((ver + 7) / 17)];
8556
+ }
8557
+ }, __name(_a, "_Mode"), _a);
8558
+ _Mode.NUMERIC = new _Mode(1, [10, 12, 14]);
8559
+ _Mode.ALPHANUMERIC = new _Mode(2, [9, 11, 13]);
8560
+ _Mode.BYTE = new _Mode(4, [8, 16, 16]);
8561
+ _Mode.KANJI = new _Mode(8, [8, 10, 12]);
8562
+ _Mode.ECI = new _Mode(7, [0, 0, 0]);
8563
+ let Mode = _Mode;
8564
+ QrSegment2.Mode = _Mode;
8565
+ })(QrSegment = qrcodegen2.QrSegment || (qrcodegen2.QrSegment = {}));
8566
+ })(qrcodegen || (qrcodegen = {}));
8567
+ var qrcodegen_default = qrcodegen;
8568
+ var ERROR_LEVEL_MAP = {
8569
+ L: qrcodegen_default.QrCode.Ecc.LOW,
8570
+ M: qrcodegen_default.QrCode.Ecc.MEDIUM,
8571
+ Q: qrcodegen_default.QrCode.Ecc.QUARTILE,
8572
+ H: qrcodegen_default.QrCode.Ecc.HIGH
8573
+ };
8574
+ var DEFAULT_SIZE = 128;
8575
+ var DEFAULT_LEVEL = "L";
8576
+ var DEFAULT_BGCOLOR = "#FFFFFF";
8577
+ var DEFAULT_FGCOLOR = "#000000";
8578
+ var DEFAULT_INCLUDEMARGIN = false;
8579
+ var DEFAULT_MINVERSION = 1;
8580
+ var SPEC_MARGIN_SIZE = 4;
8581
+ var DEFAULT_MARGIN_SIZE = 0;
8582
+ var DEFAULT_IMG_SCALE = 0.1;
8583
+ function generatePath(modules, margin = 0) {
8584
+ const ops = [];
8585
+ modules.forEach(function(row, y2) {
8586
+ let start = null;
8587
+ row.forEach(function(cell, x2) {
8588
+ if (!cell && start !== null) {
8589
+ ops.push(
8590
+ `M${start + margin} ${y2 + margin}h${x2 - start}v1H${start + margin}z`
8591
+ );
8592
+ start = null;
8593
+ return;
8594
+ }
8595
+ if (x2 === row.length - 1) {
8596
+ if (!cell) {
8597
+ return;
8598
+ }
8599
+ if (start === null) {
8600
+ ops.push(`M${x2 + margin},${y2 + margin} h1v1H${x2 + margin}z`);
8601
+ } else {
8602
+ ops.push(
8603
+ `M${start + margin},${y2 + margin} h${x2 + 1 - start}v1H${start + margin}z`
8604
+ );
8605
+ }
8606
+ return;
8607
+ }
8608
+ if (cell && start === null) {
8609
+ start = x2;
8610
+ }
8611
+ });
8612
+ });
8613
+ return ops.join("");
8614
+ }
8615
+ __name(generatePath, "generatePath");
8616
+ function excavateModules(modules, excavation) {
8617
+ return modules.slice().map((row, y2) => {
8618
+ if (y2 < excavation.y || y2 >= excavation.y + excavation.h) {
8619
+ return row;
8620
+ }
8621
+ return row.map((cell, x2) => {
8622
+ if (x2 < excavation.x || x2 >= excavation.x + excavation.w) {
8623
+ return cell;
8624
+ }
8625
+ return false;
8626
+ });
8627
+ });
8628
+ }
8629
+ __name(excavateModules, "excavateModules");
8630
+ function getImageSettings(cells, size2, margin, imageSettings) {
8631
+ if (imageSettings == null) {
8632
+ return null;
8633
+ }
8634
+ const numCells = cells.length + margin * 2;
8635
+ const defaultSize = Math.floor(size2 * DEFAULT_IMG_SCALE);
8636
+ const scale = numCells / size2;
8637
+ const w2 = (imageSettings.width || defaultSize) * scale;
8638
+ const h2 = (imageSettings.height || defaultSize) * scale;
8639
+ const x2 = imageSettings.x == null ? cells.length / 2 - w2 / 2 : imageSettings.x * scale;
8640
+ const y2 = imageSettings.y == null ? cells.length / 2 - h2 / 2 : imageSettings.y * scale;
8641
+ const opacity = imageSettings.opacity == null ? 1 : imageSettings.opacity;
8642
+ let excavation = null;
8643
+ if (imageSettings.excavate) {
8644
+ let floorX = Math.floor(x2);
8645
+ let floorY = Math.floor(y2);
8646
+ let ceilW = Math.ceil(w2 + x2 - floorX);
8647
+ let ceilH = Math.ceil(h2 + y2 - floorY);
8648
+ excavation = { x: floorX, y: floorY, w: ceilW, h: ceilH };
8649
+ }
8650
+ const crossOrigin = imageSettings.crossOrigin;
8651
+ return { x: x2, y: y2, h: h2, w: w2, excavation, opacity, crossOrigin };
8652
+ }
8653
+ __name(getImageSettings, "getImageSettings");
8654
+ function getMarginSize(includeMargin, marginSize) {
8655
+ if (marginSize != null) {
8656
+ return Math.max(Math.floor(marginSize), 0);
8657
+ }
8658
+ return includeMargin ? SPEC_MARGIN_SIZE : DEFAULT_MARGIN_SIZE;
8659
+ }
8660
+ __name(getMarginSize, "getMarginSize");
8661
+ function useQRCode({
8662
+ value,
8663
+ level,
8664
+ minVersion,
8665
+ includeMargin,
8666
+ marginSize,
8667
+ imageSettings,
8668
+ size: size2,
8669
+ boostLevel
8670
+ }) {
8671
+ let qrcode = react_default.useMemo(() => {
8672
+ const values3 = Array.isArray(value) ? value : [value];
8673
+ const segments = values3.reduce((accum, v2) => {
8674
+ accum.push(...qrcodegen_default.QrSegment.makeSegments(v2));
8675
+ return accum;
8676
+ }, []);
8677
+ return qrcodegen_default.QrCode.encodeSegments(
8678
+ segments,
8679
+ ERROR_LEVEL_MAP[level],
8680
+ minVersion,
8681
+ void 0,
8682
+ void 0,
8683
+ boostLevel
8684
+ );
8685
+ }, [value, level, minVersion, boostLevel]);
8686
+ const { cells, margin, numCells, calculatedImageSettings } = react_default.useMemo(() => {
8687
+ let cells2 = qrcode.getModules();
8688
+ const margin2 = getMarginSize(includeMargin, marginSize);
8689
+ const numCells2 = cells2.length + margin2 * 2;
8690
+ const calculatedImageSettings2 = getImageSettings(
8691
+ cells2,
8692
+ size2,
8693
+ margin2,
8694
+ imageSettings
8695
+ );
8696
+ return {
8697
+ cells: cells2,
8698
+ margin: margin2,
8699
+ numCells: numCells2,
8700
+ calculatedImageSettings: calculatedImageSettings2
8701
+ };
8702
+ }, [qrcode, size2, imageSettings, includeMargin, marginSize]);
8703
+ return {
8704
+ qrcode,
8705
+ margin,
8706
+ cells,
8707
+ numCells,
8708
+ calculatedImageSettings
8709
+ };
8710
+ }
8711
+ __name(useQRCode, "useQRCode");
8712
+ var SUPPORTS_PATH2D = function() {
8713
+ try {
8714
+ new Path2D().addPath(new Path2D());
8715
+ } catch (e2) {
8716
+ return false;
8717
+ }
8718
+ return true;
8719
+ }();
8720
+ var QRCodeCanvas = react_default.forwardRef(
8721
+ /* @__PURE__ */ __name(function QRCodeCanvas2(props, forwardedRef) {
8722
+ const _a = props, {
8723
+ value,
8724
+ size: size2 = DEFAULT_SIZE,
8725
+ level = DEFAULT_LEVEL,
8726
+ bgColor = DEFAULT_BGCOLOR,
8727
+ fgColor = DEFAULT_FGCOLOR,
8728
+ includeMargin = DEFAULT_INCLUDEMARGIN,
8729
+ minVersion = DEFAULT_MINVERSION,
8730
+ boostLevel,
8731
+ marginSize,
8732
+ imageSettings
8733
+ } = _a, extraProps = __objRest(_a, [
8734
+ "value",
8735
+ "size",
8736
+ "level",
8737
+ "bgColor",
8738
+ "fgColor",
8739
+ "includeMargin",
8740
+ "minVersion",
8741
+ "boostLevel",
8742
+ "marginSize",
8743
+ "imageSettings"
8744
+ ]);
8745
+ const _b = extraProps, { style } = _b, otherProps = __objRest(_b, ["style"]);
8746
+ const imgSrc = imageSettings == null ? void 0 : imageSettings.src;
8747
+ const _canvas = react_default.useRef(null);
8748
+ const _image = react_default.useRef(null);
8749
+ const setCanvasRef = react_default.useCallback(
8750
+ (node) => {
8751
+ _canvas.current = node;
8752
+ if (typeof forwardedRef === "function") {
8753
+ forwardedRef(node);
8754
+ } else if (forwardedRef) {
8755
+ forwardedRef.current = node;
8756
+ }
8757
+ },
8758
+ [forwardedRef]
8759
+ );
8760
+ const [isImgLoaded, setIsImageLoaded] = react_default.useState(false);
8761
+ const { margin, cells, numCells, calculatedImageSettings } = useQRCode({
8762
+ value,
8763
+ level,
8764
+ minVersion,
8765
+ boostLevel,
8766
+ includeMargin,
8767
+ marginSize,
8768
+ imageSettings,
8769
+ size: size2
8770
+ });
8771
+ react_default.useEffect(() => {
8772
+ if (_canvas.current != null) {
8773
+ const canvas = _canvas.current;
8774
+ const ctx = canvas.getContext("2d");
8775
+ if (!ctx) {
8776
+ return;
8777
+ }
8778
+ let cellsToDraw = cells;
8779
+ const image = _image.current;
8780
+ const haveImageToRender = calculatedImageSettings != null && image !== null && image.complete && image.naturalHeight !== 0 && image.naturalWidth !== 0;
8781
+ if (haveImageToRender) {
8782
+ if (calculatedImageSettings.excavation != null) {
8783
+ cellsToDraw = excavateModules(
8784
+ cells,
8785
+ calculatedImageSettings.excavation
8786
+ );
8787
+ }
8788
+ }
8789
+ const pixelRatio = window.devicePixelRatio || 1;
8790
+ canvas.height = canvas.width = size2 * pixelRatio;
8791
+ const scale = size2 / numCells * pixelRatio;
8792
+ ctx.scale(scale, scale);
8793
+ ctx.fillStyle = bgColor;
8794
+ ctx.fillRect(0, 0, numCells, numCells);
8795
+ ctx.fillStyle = fgColor;
8796
+ if (SUPPORTS_PATH2D) {
8797
+ ctx.fill(new Path2D(generatePath(cellsToDraw, margin)));
8798
+ } else {
8799
+ cells.forEach(function(row, rdx) {
8800
+ row.forEach(function(cell, cdx) {
8801
+ if (cell) {
8802
+ ctx.fillRect(cdx + margin, rdx + margin, 1, 1);
8803
+ }
8804
+ });
8805
+ });
8806
+ }
8807
+ if (calculatedImageSettings) {
8808
+ ctx.globalAlpha = calculatedImageSettings.opacity;
8809
+ }
8810
+ if (haveImageToRender) {
8811
+ ctx.drawImage(
8812
+ image,
8813
+ calculatedImageSettings.x + margin,
8814
+ calculatedImageSettings.y + margin,
8815
+ calculatedImageSettings.w,
8816
+ calculatedImageSettings.h
8817
+ );
8818
+ }
8819
+ }
8820
+ });
8821
+ react_default.useEffect(() => {
8822
+ setIsImageLoaded(false);
8823
+ }, [imgSrc]);
8824
+ const canvasStyle = __spreadValues({ height: size2, width: size2 }, style);
8825
+ let img = null;
8826
+ if (imgSrc != null) {
8827
+ img = react_default.createElement(
8828
+ "img",
8829
+ {
8830
+ src: imgSrc,
8831
+ key: imgSrc,
8832
+ style: { display: "none" },
8833
+ onLoad: /* @__PURE__ */ __name(() => {
8834
+ setIsImageLoaded(true);
8835
+ }, "onLoad"),
8836
+ ref: _image,
8837
+ crossOrigin: calculatedImageSettings == null ? void 0 : calculatedImageSettings.crossOrigin
8838
+ }
8839
+ );
8840
+ }
8841
+ return react_default.createElement(react_default.Fragment, null, react_default.createElement(
8842
+ "canvas",
8843
+ __spreadValues({
8844
+ style: canvasStyle,
8845
+ height: size2,
8846
+ width: size2,
8847
+ ref: setCanvasRef,
8848
+ role: "img"
8849
+ }, otherProps)
8850
+ ), img);
8851
+ }, "QRCodeCanvas2")
8852
+ );
8853
+ QRCodeCanvas.displayName = "QRCodeCanvas";
8854
+ var QRCodeSVG = react_default.forwardRef(
8855
+ /* @__PURE__ */ __name(function QRCodeSVG2(props, forwardedRef) {
8856
+ const _a = props, {
8857
+ value,
8858
+ size: size2 = DEFAULT_SIZE,
8859
+ level = DEFAULT_LEVEL,
8860
+ bgColor = DEFAULT_BGCOLOR,
8861
+ fgColor = DEFAULT_FGCOLOR,
8862
+ includeMargin = DEFAULT_INCLUDEMARGIN,
8863
+ minVersion = DEFAULT_MINVERSION,
8864
+ boostLevel,
8865
+ title,
8866
+ marginSize,
8867
+ imageSettings
8868
+ } = _a, otherProps = __objRest(_a, [
8869
+ "value",
8870
+ "size",
8871
+ "level",
8872
+ "bgColor",
8873
+ "fgColor",
8874
+ "includeMargin",
8875
+ "minVersion",
8876
+ "boostLevel",
8877
+ "title",
8878
+ "marginSize",
8879
+ "imageSettings"
8880
+ ]);
8881
+ const { margin, cells, numCells, calculatedImageSettings } = useQRCode({
8882
+ value,
8883
+ level,
8884
+ minVersion,
8885
+ boostLevel,
8886
+ includeMargin,
8887
+ marginSize,
8888
+ imageSettings,
8889
+ size: size2
8890
+ });
8891
+ let cellsToDraw = cells;
8892
+ let image = null;
8893
+ if (imageSettings != null && calculatedImageSettings != null) {
8894
+ if (calculatedImageSettings.excavation != null) {
8895
+ cellsToDraw = excavateModules(
8896
+ cells,
8897
+ calculatedImageSettings.excavation
8898
+ );
8899
+ }
8900
+ image = react_default.createElement(
8901
+ "image",
8902
+ {
8903
+ href: imageSettings.src,
8904
+ height: calculatedImageSettings.h,
8905
+ width: calculatedImageSettings.w,
8906
+ x: calculatedImageSettings.x + margin,
8907
+ y: calculatedImageSettings.y + margin,
8908
+ preserveAspectRatio: "none",
8909
+ opacity: calculatedImageSettings.opacity,
8910
+ crossOrigin: calculatedImageSettings.crossOrigin
8911
+ }
8912
+ );
8913
+ }
8914
+ const fgPath = generatePath(cellsToDraw, margin);
8915
+ return react_default.createElement(
8916
+ "svg",
8917
+ __spreadValues({
8918
+ height: size2,
8919
+ width: size2,
8920
+ viewBox: `0 0 ${numCells} ${numCells}`,
8921
+ ref: forwardedRef,
8922
+ role: "img"
8923
+ }, otherProps),
8924
+ !!title && react_default.createElement("title", null, title),
8925
+ react_default.createElement(
8926
+ "path",
8927
+ {
8928
+ fill: bgColor,
8929
+ d: `M0,0 h${numCells}v${numCells}H0z`,
8930
+ shapeRendering: "crispEdges"
8931
+ }
8932
+ ),
8933
+ react_default.createElement("path", { fill: fgColor, d: fgPath, shapeRendering: "crispEdges" }),
8934
+ image
8935
+ );
8936
+ }, "QRCodeSVG2")
8937
+ );
8938
+ QRCodeSVG.displayName = "QRCodeSVG";
8939
+
8940
+ // src/manager/container/Menu.tsx
8941
+ var focusableUIElements = {
8942
+ storySearchField: "storybook-explorer-searchfield",
8943
+ storyListMenu: "storybook-explorer-menu",
8944
+ storyPanelRoot: "storybook-panel-root"
8945
+ };
8946
+ var Key = styled.span(({ theme }) => ({
8947
+ display: "inline-block",
8948
+ height: 16,
8949
+ lineHeight: "16px",
8950
+ textAlign: "center",
8951
+ fontSize: "11px",
8952
+ background: theme.base === "light" ? "rgba(0,0,0,0.05)" : "rgba(255,255,255,0.05)",
8953
+ color: theme.base === "light" ? theme.color.dark : theme.textMutedColor,
8954
+ borderRadius: 2,
8955
+ userSelect: "none",
8956
+ pointerEvents: "none",
8957
+ padding: "0 6px"
8958
+ }));
8959
+ var KeyChild = styled.code(({ theme }) => ({
8960
+ padding: 0,
8961
+ fontFamily: theme.typography.fonts.base,
8962
+ verticalAlign: "middle",
8963
+ "& + &": {
8964
+ marginLeft: 6
8965
+ }
8966
+ }));
8967
+ var Shortcut = /* @__PURE__ */ __name(({ keys: keys2 }) => react_default.createElement(Key, null, keys2.map((key) => react_default.createElement(KeyChild, { key }, shortcutToHumanString([key])))), "Shortcut");
8968
+ var useMenu = /* @__PURE__ */ __name((state, api, showToolbar, isFullscreen, isPanelShown, isNavShown, enableShortcuts) => {
8969
+ const shortcutKeys = api.getShortcutKeys();
8970
+ const about = useMemo(
8971
+ () => ({
8972
+ id: "about",
8973
+ title: "About your Storybook",
8974
+ onClick: /* @__PURE__ */ __name(() => api.changeSettingsTab("about"), "onClick"),
8975
+ icon: react_default.createElement(InfoIcon, null)
8976
+ }),
8977
+ [api]
8978
+ );
8979
+ const documentation = useMemo(() => {
8980
+ const docsUrl = api.getDocsUrl({ versioned: true, renderer: true });
8981
+ return {
8982
+ id: "documentation",
8983
+ title: "Documentation",
8984
+ href: docsUrl,
8985
+ icon: react_default.createElement(ShareAltIcon, null)
8986
+ };
8987
+ }, [api]);
8988
+ const whatsNewNotificationsEnabled = state.whatsNewData?.status === "SUCCESS" && !state.disableWhatsNewNotifications;
8989
+ const isWhatsNewUnread = api.isWhatsNewUnread();
8990
+ const whatsNew = useMemo(
8991
+ () => ({
8992
+ id: "whats-new",
8993
+ title: "What's new?",
8994
+ onClick: /* @__PURE__ */ __name(() => api.changeSettingsTab("whats-new"), "onClick"),
8995
+ right: whatsNewNotificationsEnabled && isWhatsNewUnread && react_default.createElement(Badge, { status: "positive" }, "Check it out"),
8996
+ icon: react_default.createElement(WandIcon, null)
8997
+ }),
8998
+ [api, whatsNewNotificationsEnabled, isWhatsNewUnread]
8999
+ );
9000
+ const shortcuts = useMemo(
9001
+ () => ({
9002
+ id: "shortcuts",
9003
+ title: "Keyboard shortcuts",
9004
+ onClick: /* @__PURE__ */ __name(() => api.changeSettingsTab("shortcuts"), "onClick"),
9005
+ right: enableShortcuts ? react_default.createElement(Shortcut, { keys: shortcutKeys.shortcutsPage }) : null,
9006
+ icon: react_default.createElement(CommandIcon, null)
9007
+ }),
9008
+ [api, enableShortcuts, shortcutKeys.shortcutsPage]
9009
+ );
9010
+ const sidebarToggle = useMemo(
9011
+ () => ({
9012
+ id: "S",
9013
+ title: "Show sidebar",
9014
+ onClick: /* @__PURE__ */ __name(() => api.toggleNav(), "onClick"),
9015
+ active: isNavShown,
9016
+ right: enableShortcuts ? react_default.createElement(Shortcut, { keys: shortcutKeys.toggleNav }) : null,
9017
+ icon: isNavShown ? react_default.createElement(CheckIcon, null) : null
9018
+ }),
9019
+ [api, enableShortcuts, shortcutKeys, isNavShown]
9020
+ );
9021
+ const toolbarToogle = useMemo(
9022
+ () => ({
9023
+ id: "T",
9024
+ title: "Show toolbar",
9025
+ onClick: /* @__PURE__ */ __name(() => api.toggleToolbar(), "onClick"),
9026
+ active: showToolbar,
9027
+ right: enableShortcuts ? react_default.createElement(Shortcut, { keys: shortcutKeys.toolbar }) : null,
9028
+ icon: showToolbar ? react_default.createElement(CheckIcon, null) : null
9029
+ }),
9030
+ [api, enableShortcuts, shortcutKeys, showToolbar]
9031
+ );
9032
+ const addonsToggle = useMemo(
9033
+ () => ({
9034
+ id: "A",
9035
+ title: "Show addons panel",
9036
+ onClick: /* @__PURE__ */ __name(() => api.togglePanel(), "onClick"),
9037
+ active: isPanelShown,
9038
+ right: enableShortcuts ? react_default.createElement(Shortcut, { keys: shortcutKeys.togglePanel }) : null,
9039
+ icon: isPanelShown ? react_default.createElement(CheckIcon, null) : null
9040
+ }),
9041
+ [api, enableShortcuts, shortcutKeys, isPanelShown]
9042
+ );
9043
+ const addonsOrientationToggle = useMemo(
9044
+ () => ({
9045
+ id: "D",
9046
+ title: "Change addons orientation",
9047
+ onClick: /* @__PURE__ */ __name(() => api.togglePanelPosition(), "onClick"),
9048
+ right: enableShortcuts ? react_default.createElement(Shortcut, { keys: shortcutKeys.panelPosition }) : null
9049
+ }),
9050
+ [api, enableShortcuts, shortcutKeys]
9051
+ );
9052
+ const fullscreenToggle = useMemo(
9053
+ () => ({
9054
+ id: "F",
9055
+ title: "Go full screen",
9056
+ onClick: /* @__PURE__ */ __name(() => api.toggleFullscreen(), "onClick"),
9057
+ active: isFullscreen,
9058
+ right: enableShortcuts ? react_default.createElement(Shortcut, { keys: shortcutKeys.fullScreen }) : null,
9059
+ icon: isFullscreen ? react_default.createElement(CheckIcon, null) : null
9060
+ }),
9061
+ [api, enableShortcuts, shortcutKeys, isFullscreen]
9062
+ );
9063
+ const searchToggle = useMemo(
9064
+ () => ({
9065
+ id: "/",
9066
+ title: "Search",
9067
+ onClick: /* @__PURE__ */ __name(() => api.focusOnUIElement(focusableUIElements.storySearchField), "onClick"),
9068
+ right: enableShortcuts ? react_default.createElement(Shortcut, { keys: shortcutKeys.search }) : null
9069
+ }),
9070
+ [api, enableShortcuts, shortcutKeys]
9071
+ );
9072
+ const up = useMemo(
9073
+ () => ({
9074
+ id: "up",
9075
+ title: "Previous component",
9076
+ onClick: /* @__PURE__ */ __name(() => api.jumpToComponent(-1), "onClick"),
9077
+ right: enableShortcuts ? react_default.createElement(Shortcut, { keys: shortcutKeys.prevComponent }) : null
9078
+ }),
9079
+ [api, enableShortcuts, shortcutKeys]
9080
+ );
9081
+ const down = useMemo(
9082
+ () => ({
9083
+ id: "down",
9084
+ title: "Next component",
9085
+ onClick: /* @__PURE__ */ __name(() => api.jumpToComponent(1), "onClick"),
9086
+ right: enableShortcuts ? react_default.createElement(Shortcut, { keys: shortcutKeys.nextComponent }) : null
9087
+ }),
9088
+ [api, enableShortcuts, shortcutKeys]
9089
+ );
9090
+ const prev = useMemo(
9091
+ () => ({
9092
+ id: "prev",
9093
+ title: "Previous story",
9094
+ onClick: /* @__PURE__ */ __name(() => api.jumpToStory(-1), "onClick"),
9095
+ right: enableShortcuts ? react_default.createElement(Shortcut, { keys: shortcutKeys.prevStory }) : null
9096
+ }),
9097
+ [api, enableShortcuts, shortcutKeys]
9098
+ );
9099
+ const next = useMemo(
9100
+ () => ({
9101
+ id: "next",
9102
+ title: "Next story",
9103
+ onClick: /* @__PURE__ */ __name(() => api.jumpToStory(1), "onClick"),
9104
+ right: enableShortcuts ? react_default.createElement(Shortcut, { keys: shortcutKeys.nextStory }) : null
9105
+ }),
9106
+ [api, enableShortcuts, shortcutKeys]
9107
+ );
9108
+ const collapse = useMemo(
9109
+ () => ({
9110
+ id: "collapse",
9111
+ title: "Collapse all",
9112
+ onClick: /* @__PURE__ */ __name(() => api.emit(STORIES_COLLAPSE_ALL), "onClick"),
9113
+ right: enableShortcuts ? react_default.createElement(Shortcut, { keys: shortcutKeys.collapseAll }) : null
9114
+ }),
9115
+ [api, enableShortcuts, shortcutKeys]
9116
+ );
9117
+ const getAddonsShortcuts = useCallback(() => {
9118
+ const addonsShortcuts = api.getAddonsShortcuts();
9119
+ const keys2 = shortcutKeys;
9120
+ return Object.entries(addonsShortcuts).filter(([_2, { showInMenu }]) => showInMenu).map(([actionName, { label, action }]) => ({
9121
+ id: actionName,
9122
+ title: label,
9123
+ onClick: /* @__PURE__ */ __name(() => action(), "onClick"),
9124
+ right: enableShortcuts ? react_default.createElement(Shortcut, { keys: keys2[actionName] }) : null
9125
+ }));
9126
+ }, [api, enableShortcuts, shortcutKeys]);
9127
+ return useMemo(
9128
+ () => [
9129
+ [
9130
+ about,
9131
+ ...state.whatsNewData?.status === "SUCCESS" ? [whatsNew] : [],
9132
+ documentation,
9133
+ ...enableShortcuts ? [shortcuts] : []
9134
+ ],
9135
+ [
9136
+ sidebarToggle,
9137
+ toolbarToogle,
9138
+ addonsToggle,
9139
+ addonsOrientationToggle,
9140
+ fullscreenToggle,
9141
+ searchToggle,
9142
+ up,
9143
+ down,
9144
+ prev,
9145
+ next,
9146
+ collapse
9147
+ ],
9148
+ getAddonsShortcuts()
9149
+ ],
9150
+ [
9151
+ about,
9152
+ state,
9153
+ whatsNew,
9154
+ documentation,
9155
+ shortcuts,
9156
+ sidebarToggle,
9157
+ toolbarToogle,
9158
+ addonsToggle,
9159
+ addonsOrientationToggle,
9160
+ fullscreenToggle,
9161
+ searchToggle,
9162
+ up,
9163
+ down,
9164
+ prev,
9165
+ next,
9166
+ collapse,
9167
+ getAddonsShortcuts,
9168
+ enableShortcuts
9169
+ ]
9170
+ );
9171
+ }, "useMenu");
9172
+
9173
+ // src/manager/components/preview/tools/share.tsx
9174
+ var { PREVIEW_URL, document: document2 } = scope;
9175
+ var mapper3 = /* @__PURE__ */ __name(({ state }) => {
9176
+ const { storyId, refId, refs } = state;
9177
+ const { location } = document2;
9178
+ const ref = refs[refId];
9179
+ let baseUrl = `${location.origin}${location.pathname}`;
9180
+ if (!baseUrl.endsWith("/")) {
9181
+ baseUrl += "/";
9182
+ }
9183
+ return {
9184
+ refId,
9185
+ baseUrl: ref ? `${ref.url}/iframe.html` : PREVIEW_URL || `${baseUrl}iframe.html`,
9186
+ storyId,
9187
+ queryParams: state.customQueryParams
9188
+ };
9189
+ }, "mapper");
9190
+ var QRContainer = styled.div(() => ({
9191
+ display: "flex",
9192
+ alignItems: "center",
9193
+ padding: 8,
9194
+ maxWidth: 200
9195
+ }));
9196
+ var QRImageContainer = styled.div(() => ({
9197
+ width: 64,
9198
+ height: 64,
9199
+ marginRight: 12,
9200
+ backgroundColor: "white",
9201
+ padding: 2
9202
+ }));
9203
+ var QRImage = /* @__PURE__ */ __name(({ value }) => {
9204
+ const theme = useTheme();
9205
+ return react_default.createElement(QRImageContainer, null, react_default.createElement(QRCodeSVG, { value, marginSize: 0, size: 60, fgColor: theme.color.darkest }));
9206
+ }, "QRImage");
9207
+ var QRContent = styled.div(() => ({}));
9208
+ var QRTitle = styled.div(({ theme }) => ({
9209
+ fontWeight: theme.typography.weight.bold,
9210
+ fontSize: theme.typography.size.s1,
9211
+ marginBottom: 4
9212
+ }));
9213
+ var QRDescription = styled.div(({ theme }) => ({
9214
+ fontSize: theme.typography.size.s1,
9215
+ color: theme.textMutedColor
9216
+ }));
9217
+ function ShareMenu({
9218
+ baseUrl,
9219
+ storyId,
9220
+ queryParams,
9221
+ qrUrl
9222
+ }) {
9223
+ const api = useStorybookApi();
9224
+ const shortcutKeys = api.getShortcutKeys();
9225
+ const enableShortcuts = !!shortcutKeys;
9226
+ const [copied, setCopied] = useState(false);
9227
+ const copyStoryLink = shortcutKeys?.copyStoryLink;
9228
+ const links = useMemo(() => {
9229
+ const copyTitle = copied ? "Copied!" : "Copy story link";
9230
+ const baseLinks = [
9231
+ [
9232
+ {
9233
+ id: "copy-link",
9234
+ title: copyTitle,
9235
+ icon: react_default.createElement(LinkIcon, null),
9236
+ right: enableShortcuts ? react_default.createElement(Shortcut, { keys: copyStoryLink }) : null,
9237
+ onClick: /* @__PURE__ */ __name(() => {
9238
+ (0, import_copy_to_clipboard.default)(window.location.href);
9239
+ setCopied(true);
9240
+ setTimeout(() => setCopied(false), 2e3);
9241
+ }, "onClick")
9242
+ },
9243
+ {
9244
+ id: "open-new-tab",
9245
+ title: "Open in isolation mode",
9246
+ icon: react_default.createElement(BugIcon, null),
9247
+ onClick: /* @__PURE__ */ __name(() => {
9248
+ const href = getStoryHref(baseUrl, storyId, queryParams);
9249
+ window.open(href, "_blank", "noopener,noreferrer");
9250
+ }, "onClick")
9251
+ }
9252
+ ]
9253
+ ];
9254
+ baseLinks.push([
9255
+ {
9256
+ id: "qr-section",
9257
+ // @ts-expect-error (non strict)
9258
+ content: react_default.createElement(QRContainer, null, react_default.createElement(QRImage, { value: qrUrl }), react_default.createElement(QRContent, null, react_default.createElement(QRTitle, null, "Scan me"), react_default.createElement(QRDescription, null, "Must be on the same network as this device.")))
9259
+ }
9260
+ ]);
9261
+ return baseLinks;
9262
+ }, [baseUrl, storyId, queryParams, copied, qrUrl, enableShortcuts, copyStoryLink]);
9263
+ return react_default.createElement(TooltipLinkList, { links });
9264
+ }
9265
+ __name(ShareMenu, "ShareMenu");
9266
+ var shareTool = {
9267
+ title: "share",
9268
+ id: "share",
7840
9269
  type: types.TOOL,
7841
- // @ts-expect-error (non strict)
7842
- match: /* @__PURE__ */ __name(({ viewMode }) => ["story", "docs"].includes(viewMode), "match"),
7843
- render: /* @__PURE__ */ __name(() => react_default.createElement(Consumer, { filter: menuMapper3 }, ({ isVisible, toggle, singleStory }) => !singleStory && !isVisible && react_default.createElement(react_default.Fragment, null, react_default.createElement(IconButton, { "aria-label": "Show sidebar", key: "menu", onClick: toggle, title: "Show sidebar" }, react_default.createElement(MenuIcon, null)), react_default.createElement(Separator, null))), "render")
9270
+ match: /* @__PURE__ */ __name(({ viewMode, tabId }) => viewMode === "story" && !tabId, "match"),
9271
+ render: /* @__PURE__ */ __name(() => {
9272
+ return react_default.createElement(Consumer, { filter: mapper3 }, ({ baseUrl, storyId, queryParams }) => {
9273
+ const storyUrl = scope.STORYBOOK_NETWORK_ADDRESS ? `${scope.STORYBOOK_NETWORK_ADDRESS}${window.location.search}` : window.location.href;
9274
+ return storyId ? react_default.createElement(
9275
+ WithTooltip,
9276
+ {
9277
+ hasChrome: true,
9278
+ placement: "bottom",
9279
+ tooltip: react_default.createElement(ShareMenu, { ...{ baseUrl, storyId, queryParams, qrUrl: storyUrl } })
9280
+ },
9281
+ react_default.createElement(IconButton, { title: "Share" }, react_default.createElement(ShareIcon, null))
9282
+ ) : null;
9283
+ });
9284
+ }, "render")
7844
9285
  };
7845
9286
 
7846
9287
  // src/manager/container/Preview.tsx
7847
9288
  var defaultTabs = [createCanvasTab()];
7848
9289
  var defaultTools = [menuTool, remountTool, zoomTool];
7849
- var defaultToolsExtra = [addonsTool, fullScreenTool, ejectTool, copyTool];
9290
+ var defaultToolsExtra = [addonsTool, fullScreenTool, shareTool, openInEditorTool];
7850
9291
  var emptyTabsList = [];
7851
9292
  var memoizedTabs = (0, import_memoizerific.default)(1)(
7852
9293
  (_2, tabElements, parameters, showTabs) => showTabs ? filterTabs([...defaultTabs, ...Object.values(tabElements)], parameters) : emptyTabsList
@@ -7861,7 +9302,7 @@ var memoizedWrapper = (0, import_memoizerific.default)(1)((_2, previewElements)
7861
9302
  ...defaultWrappers,
7862
9303
  ...Object.values(previewElements)
7863
9304
  ]);
7864
- var { PREVIEW_URL: PREVIEW_URL3 } = scope;
9305
+ var { PREVIEW_URL: PREVIEW_URL2 } = scope;
7865
9306
  var splitTitleAddExtraSpace = /* @__PURE__ */ __name((input) => input.split("/").join(" / ").replace(/\s\s/, " "), "splitTitleAddExtraSpace");
7866
9307
  var getDescription = /* @__PURE__ */ __name((item) => {
7867
9308
  if (item?.type === "story" || item?.type === "docs") {
@@ -7870,7 +9311,7 @@ var getDescription = /* @__PURE__ */ __name((item) => {
7870
9311
  }
7871
9312
  return item?.name ? `${item.name} \u22C5 Storybook` : "Storybook";
7872
9313
  }, "getDescription");
7873
- var mapper2 = /* @__PURE__ */ __name(({
9314
+ var mapper4 = /* @__PURE__ */ __name(({
7874
9315
  api,
7875
9316
  state
7876
9317
  // @ts-expect-error (non strict)
@@ -7904,7 +9345,7 @@ var mapper2 = /* @__PURE__ */ __name(({
7904
9345
  viewMode,
7905
9346
  refs,
7906
9347
  storyId,
7907
- baseUrl: PREVIEW_URL3 || "iframe.html",
9348
+ baseUrl: PREVIEW_URL2 || "iframe.html",
7908
9349
  queryParams: customQueryParams,
7909
9350
  tools,
7910
9351
  toolsExtra,
@@ -7922,7 +9363,7 @@ var mapper2 = /* @__PURE__ */ __name(({
7922
9363
  };
7923
9364
  }, "mapper");
7924
9365
  var PreviewConnected = react_default.memo(/* @__PURE__ */ __name(function PreviewConnected2(props) {
7925
- return react_default.createElement(Consumer, { filter: mapper2 }, (fromState) => react_default.createElement(Preview, { ...props, ...fromState }));
9366
+ return react_default.createElement(Consumer, { filter: mapper4 }, (fromState) => react_default.createElement(Preview, { ...props, ...fromState }));
7926
9367
  }, "PreviewConnected"));
7927
9368
  var Preview_default = PreviewConnected;
7928
9369
 
@@ -9780,7 +11221,7 @@ var HighlightStyles = /* @__PURE__ */ __name(({ refId, itemId }) => react_defaul
9780
11221
  background: background2,
9781
11222
  "&:hover, &:focus": { background: background2 }
9782
11223
  },
9783
- [`&[data-nodetype="story"], &[data-nodetype="document"]`]: {
11224
+ [`&[data-nodetype="story"], &[data-nodetype="document"], &[data-nodetype="test"]`]: {
9784
11225
  color: color2.defaultText,
9785
11226
  background: background2,
9786
11227
  "&:hover, &:focus": { background: background2 }
@@ -9812,7 +11253,7 @@ var getAncestorIds = (0, import_memoizerific2.default)(1e3)(
9812
11253
  );
9813
11254
  var getDescendantIds = (0, import_memoizerific2.default)(1e3)((data, id, skipLeafs) => {
9814
11255
  const entry = data[id];
9815
- if (!entry || entry.type === "story" || entry.type === "docs" || !entry.children) {
11256
+ if (!entry || !("children" in entry) || !entry.children) {
9816
11257
  return [];
9817
11258
  }
9818
11259
  return entry.children.reduce((acc, childId) => {
@@ -10209,6 +11650,7 @@ var GROUP_ID = "icon--group";
10209
11650
  var COMPONENT_ID = "icon--component";
10210
11651
  var DOCUMENT_ID = "icon--document";
10211
11652
  var STORY_ID = "icon--story";
11653
+ var TEST_ID = "icon--test";
10212
11654
  var SUCCESS_ID = "icon--success";
10213
11655
  var ERROR_ID = "icon--error";
10214
11656
  var WARNING_ID = "icon--warning";
@@ -10252,6 +11694,14 @@ var IconSymbols = /* @__PURE__ */ __name(() => {
10252
11694
  d: "M3.5 0h7a.5.5 0 01.5.5v13a.5.5 0 01-.454.498.462.462 0 01-.371-.118L7 11.159l-3.175 2.72a.46.46 0 01-.379.118A.5.5 0 013 13.5V.5a.5.5 0 01.5-.5zM4 12.413l2.664-2.284a.454.454 0 01.377-.128.498.498 0 01.284.12L10 12.412V1H4v11.413z",
10253
11695
  fill: "currentColor"
10254
11696
  }
11697
+ )), react_default.createElement("symbol", { id: TEST_ID }, react_default.createElement(
11698
+ "path",
11699
+ {
11700
+ fillRule: "evenodd",
11701
+ clipRule: "evenodd",
11702
+ d: "M4.5 2h.75v3.866l-3.034 5.26A1.25 1.25 0 003.299 13H10.7a1.25 1.25 0 001.083-1.875L8.75 5.866V2h.75a.5.5 0 100-1h-5a.5.5 0 000 1zm1.75 4V2h1.5v4.134l.067.116L8.827 8H5.173l1.01-1.75.067-.116V6zM4.597 9l-1.515 2.625A.25.25 0 003.3 12H10.7a.25.25 0 00.217-.375L9.404 9H4.597z",
11703
+ fill: "currentColor"
11704
+ }
10255
11705
  )), react_default.createElement("symbol", { id: SUCCESS_ID }, react_default.createElement(
10256
11706
  "path",
10257
11707
  {
@@ -10291,6 +11741,9 @@ var UseSymbol = /* @__PURE__ */ __name(({ type }) => {
10291
11741
  if (type === "story") {
10292
11742
  return react_default.createElement("use", { xlinkHref: `#${STORY_ID}` });
10293
11743
  }
11744
+ if (type === "test") {
11745
+ return react_default.createElement("use", { xlinkHref: `#${TEST_ID}` });
11746
+ }
10294
11747
  if (type === "success") {
10295
11748
  return react_default.createElement("use", { xlinkHref: `#${SUCCESS_ID}` });
10296
11749
  }
@@ -10350,7 +11803,7 @@ var getMostCriticalStatusValue = /* @__PURE__ */ __name((statusValues) => {
10350
11803
  }, "getMostCriticalStatusValue");
10351
11804
  function getGroupStatus(collapsedData, allStatuses) {
10352
11805
  return Object.values(collapsedData).reduce((acc, item) => {
10353
- if (item.type === "group" || item.type === "component") {
11806
+ if (item.type === "group" || item.type === "component" || item.type === "story") {
10354
11807
  const leafs = getDescendantIds(collapsedData, item.id, false).map((id) => collapsedData[id]).filter((i2) => i2.type === "story");
10355
11808
  const combinedStatus = getMostCriticalStatusValue(
10356
11809
  // @ts-expect-error (non strict)
@@ -10365,6 +11818,9 @@ function getGroupStatus(collapsedData, allStatuses) {
10365
11818
  }
10366
11819
  __name(getGroupStatus, "getGroupStatus");
10367
11820
 
11821
+ // src/manager/components/sidebar/ContextMenu.tsx
11822
+ var import_copy_to_clipboard2 = __toESM(require_copy_to_clipboard(), 1);
11823
+
10368
11824
  // src/manager/components/sidebar/StatusButton.tsx
10369
11825
  var withStatusColor = /* @__PURE__ */ __name(({ theme, status }) => {
10370
11826
  const defaultColor = theme.base === "light" ? curriedTransparentize$1(0.3, theme.color.defaultText) : curriedTransparentize$1(0.6, theme.color.defaultText);
@@ -10435,6 +11891,47 @@ var FloatingStatusButton = styled(StatusButton)({
10435
11891
  var useContextMenu = /* @__PURE__ */ __name((context, links, api) => {
10436
11892
  const [hoverCount, setHoverCount] = useState(0);
10437
11893
  const [isOpen, setIsOpen] = useState(false);
11894
+ const [copyText, setCopyText] = react_default.useState("Copy story name");
11895
+ const shortcutKeys = api.getShortcutKeys();
11896
+ const enableShortcuts = !!shortcutKeys;
11897
+ const topLinks = useMemo(() => {
11898
+ const defaultLinks = [];
11899
+ if (context && "importPath" in context) {
11900
+ defaultLinks.push({
11901
+ id: "open-in-editor",
11902
+ title: "Open in editor",
11903
+ icon: react_default.createElement(EditorIcon, null),
11904
+ right: enableShortcuts ? react_default.createElement(Shortcut, { keys: shortcutKeys.openInEditor }) : null,
11905
+ onClick: /* @__PURE__ */ __name((e2) => {
11906
+ e2.preventDefault();
11907
+ api.openInEditor({
11908
+ file: context.importPath
11909
+ });
11910
+ }, "onClick")
11911
+ });
11912
+ }
11913
+ if (context.type === "story") {
11914
+ defaultLinks.push({
11915
+ id: "copy-story-name",
11916
+ title: copyText,
11917
+ icon: react_default.createElement(CopyIcon, null),
11918
+ // TODO: bring this back once we want to add shortcuts for this
11919
+ // right:
11920
+ // enableShortcuts && shortcutKeys.copyStoryName ? (
11921
+ // <Shortcut keys={shortcutKeys.copyStoryName} />
11922
+ // ) : null,
11923
+ onClick: /* @__PURE__ */ __name((e2) => {
11924
+ e2.preventDefault();
11925
+ (0, import_copy_to_clipboard2.default)(context.exportName);
11926
+ setCopyText("Copied!");
11927
+ setTimeout(() => {
11928
+ setCopyText("Copy story name");
11929
+ }, 2e3);
11930
+ }, "onClick")
11931
+ });
11932
+ }
11933
+ return defaultLinks;
11934
+ }, [context, copyText, enableShortcuts, shortcutKeys]);
10438
11935
  const handlers = useMemo(() => {
10439
11936
  return {
10440
11937
  onMouseEnter: /* @__PURE__ */ __name(() => {
@@ -10456,14 +11953,14 @@ var useContextMenu = /* @__PURE__ */ __name((context, links, api) => {
10456
11953
  }
10457
11954
  return [];
10458
11955
  }, [api, context, hoverCount]);
10459
- const isRendered = providerLinks.length > 0 || links.length > 0;
11956
+ const shouldRender = !context.refId && (providerLinks.length > 0 || links.length > 0 || topLinks.length > 0);
10460
11957
  return useMemo(() => {
10461
11958
  if (globalThis.CONFIG_TYPE !== "DEVELOPMENT") {
10462
11959
  return empty;
10463
11960
  }
10464
11961
  return {
10465
11962
  onMouseEnter: handlers.onMouseEnter,
10466
- node: isRendered ? react_default.createElement(
11963
+ node: shouldRender ? react_default.createElement(
10467
11964
  PositionedWithTooltip,
10468
11965
  {
10469
11966
  "data-displayed": isOpen ? "on" : "off",
@@ -10477,12 +11974,12 @@ var useContextMenu = /* @__PURE__ */ __name((context, links, api) => {
10477
11974
  setIsOpen(true);
10478
11975
  }
10479
11976
  },
10480
- tooltip: react_default.createElement(LiveContextMenu, { context, links })
11977
+ tooltip: react_default.createElement(LiveContextMenu, { context, links: [...topLinks, ...links] })
10481
11978
  },
10482
11979
  react_default.createElement(FloatingStatusButton, { type: "button", status: "status-value:pending" }, react_default.createElement(EllipsisIcon, null))
10483
11980
  ) : null
10484
11981
  };
10485
- }, [context, handlers, isOpen, isRendered, links]);
11982
+ }, [context, handlers, isOpen, shouldRender, links, topLinks]);
10486
11983
  }, "useContextMenu");
10487
11984
  var LiveContextMenu = /* @__PURE__ */ __name(({
10488
11985
  context,
@@ -10493,7 +11990,7 @@ var LiveContextMenu = /* @__PURE__ */ __name(({
10493
11990
  Addon_TypesEnum.experimental_TEST_PROVIDER
10494
11991
  );
10495
11992
  const providerLinks = generateTestProviderLinks(registeredTestProviders, context);
10496
- const groups = Array.isArray(links[0]) ? links : [links];
11993
+ const groups = Array.isArray(links[0]) || links.length === 0 ? links : [links];
10497
11994
  const all = groups.concat([providerLinks]);
10498
11995
  return react_default.createElement(TooltipLinkList, { ...rest3, links: all });
10499
11996
  }, "LiveContextMenu");
@@ -10549,23 +12046,22 @@ var useStatusSummary = /* @__PURE__ */ __name((item) => {
10549
12046
  }, "useStatusSummary");
10550
12047
 
10551
12048
  // src/manager/components/sidebar/components/CollapseIcon.tsx
10552
- var CollapseIconWrapper = styled.div(({ theme, isExpanded }) => ({
12049
+ var CollapseIconWrapper = styled.div(({ isExpanded }) => ({
10553
12050
  width: 8,
10554
12051
  height: 8,
10555
12052
  display: "flex",
10556
12053
  justifyContent: "center",
10557
12054
  alignItems: "center",
10558
- color: curriedTransparentize$1(0.4, theme.textMutedColor),
10559
12055
  transform: isExpanded ? "rotateZ(90deg)" : "none",
10560
12056
  transition: "transform .1s ease-out"
10561
12057
  }));
10562
- var CollapseIcon2 = /* @__PURE__ */ __name(({ isExpanded }) => react_default.createElement(CollapseIconWrapper, { isExpanded }, react_default.createElement("svg", { xmlns: "http://www.w3.org/2000/svg", width: "8", height: "8", fill: "none" }, react_default.createElement(
12058
+ var CollapseIcon2 = /* @__PURE__ */ __name((props) => react_default.createElement(CollapseIconWrapper, { ...props }, react_default.createElement("svg", { xmlns: "http://www.w3.org/2000/svg", width: "8", height: "8", fill: "none" }, react_default.createElement(
10563
12059
  "path",
10564
12060
  {
10565
- fill: "#73828C",
12061
+ fill: "currentColor",
10566
12062
  fillRule: "evenodd",
10567
- d: "M1.896 7.146a.5.5 0 1 0 .708.708l3.5-3.5a.5.5 0 0 0 0-.708l-3.5-3.5a.5.5 0 1 0-.708.708L5.043 4 1.896 7.146Z",
10568
- clipRule: "evenodd"
12063
+ clipRule: "evenodd",
12064
+ d: "M1.896 7.146a.5.5 0 1 0 .708.708l3.5-3.5a.5.5 0 0 0 0-.708l-3.5-3.5a.5.5 0 1 0-.708.708L5.043 4 1.896 7.146Z"
10569
12065
  }
10570
12066
  ))), "CollapseIcon");
10571
12067
 
@@ -10588,44 +12084,42 @@ var TypeIcon2 = styled.svg(
10588
12084
  if (type === "story") {
10589
12085
  return theme.color.seafoam;
10590
12086
  }
12087
+ if (type === "test") {
12088
+ return theme.color.green;
12089
+ }
10591
12090
  return "currentColor";
10592
12091
  })()
10593
12092
  })
10594
12093
  );
10595
- var BranchNode = styled.button(({ theme, depth = 0, isExpandable = false }) => ({
12094
+ var commonNodeStyles = /* @__PURE__ */ __name(({
12095
+ theme,
12096
+ depth = 0,
12097
+ isExpandable = false
12098
+ }) => ({
12099
+ flex: 1,
10596
12100
  width: "100%",
10597
- border: "none",
10598
12101
  cursor: "pointer",
10599
12102
  display: "flex",
10600
12103
  alignItems: "start",
10601
12104
  textAlign: "left",
10602
- paddingLeft: `${(isExpandable ? 8 : 22) + depth * 18}px`,
12105
+ textDecoration: "none",
12106
+ border: "none",
10603
12107
  color: "inherit",
10604
12108
  fontSize: `${theme.typography.size.s2}px`,
12109
+ fontWeight: "inherit",
10605
12110
  background: "transparent",
10606
12111
  minHeight: 28,
10607
12112
  borderRadius: 4,
10608
12113
  gap: 6,
10609
- paddingTop: 5,
10610
- paddingBottom: 4
10611
- }));
10612
- var LeafNode = styled.a(({ theme, depth = 0 }) => ({
10613
- width: "100%",
10614
- cursor: "pointer",
10615
- color: "inherit",
10616
- display: "flex",
10617
- gap: 6,
10618
- flex: 1,
10619
- alignItems: "start",
10620
- paddingLeft: `${22 + depth * 18}px`,
12114
+ paddingLeft: `${(isExpandable ? 8 : 22) + depth * 18}px`,
10621
12115
  paddingTop: 5,
10622
12116
  paddingBottom: 4,
10623
- fontSize: `${theme.typography.size.s2}px`,
10624
- textDecoration: "none",
10625
12117
  overflowWrap: "break-word",
10626
12118
  wordWrap: "break-word",
10627
12119
  wordBreak: "break-word"
10628
- }));
12120
+ }), "commonNodeStyles");
12121
+ var BranchNode = styled.button(commonNodeStyles);
12122
+ var LeafNode = styled.a(commonNodeStyles);
10629
12123
  var RootNode = styled.div(({ theme }) => ({
10630
12124
  display: "flex",
10631
12125
  alignItems: "center",
@@ -10655,22 +12149,37 @@ var GroupNode = react_default.memo(/* @__PURE__ */ __name(function GroupNode2({
10655
12149
  return react_default.createElement(BranchNode, { isExpandable, tabIndex: -1, ...props }, react_default.createElement(Wrapper, null, isExpandable && react_default.createElement(CollapseIcon2, { isExpanded }), react_default.createElement(TypeIcon2, { viewBox: "0 0 14 14", width: "14", height: "14", type: "group" }, react_default.createElement(UseSymbol, { type: "group" }))), children2);
10656
12150
  }, "GroupNode"));
10657
12151
  var ComponentNode = react_default.memo(
10658
- /* @__PURE__ */ __name(function ComponentNode2({ theme, children: children2, isExpanded, isExpandable, isSelected, ...props }) {
12152
+ /* @__PURE__ */ __name(function ComponentNode2({
12153
+ theme,
12154
+ children: children2,
12155
+ isExpanded = false,
12156
+ isExpandable = false,
12157
+ isSelected,
12158
+ ...props
12159
+ }) {
10659
12160
  return react_default.createElement(BranchNode, { isExpandable, tabIndex: -1, ...props }, react_default.createElement(Wrapper, null, isExpandable && react_default.createElement(CollapseIcon2, { isExpanded }), react_default.createElement(TypeIcon2, { viewBox: "0 0 14 14", width: "12", height: "12", type: "component" }, react_default.createElement(UseSymbol, { type: "component" }))), children2);
10660
12161
  }, "ComponentNode")
10661
12162
  );
10662
- var DocumentNode = react_default.memo(
10663
- /* @__PURE__ */ __name(function DocumentNode2({ theme, children: children2, docsMode, ...props }) {
10664
- return react_default.createElement(LeafNode, { tabIndex: -1, ...props }, react_default.createElement(Wrapper, null, react_default.createElement(TypeIcon2, { viewBox: "0 0 14 14", width: "12", height: "12", type: "document" }, react_default.createElement(UseSymbol, { type: "document" }))), children2);
10665
- }, "DocumentNode")
10666
- );
12163
+ var DocumentNode = react_default.memo(/* @__PURE__ */ __name(function DocumentNode2({ theme, children: children2, docsMode, ...props }) {
12164
+ return react_default.createElement(LeafNode, { tabIndex: -1, ...props }, react_default.createElement(Wrapper, null, react_default.createElement(TypeIcon2, { viewBox: "0 0 14 14", width: "12", height: "12", type: "document" }, react_default.createElement(UseSymbol, { type: "document" }))), children2);
12165
+ }, "DocumentNode"));
10667
12166
  var StoryNode = react_default.memo(/* @__PURE__ */ __name(function StoryNode2({
10668
12167
  theme,
10669
12168
  children: children2,
12169
+ isExpandable = false,
12170
+ isExpanded = false,
12171
+ isSelected,
10670
12172
  ...props
10671
12173
  }) {
10672
- return react_default.createElement(LeafNode, { tabIndex: -1, ...props }, react_default.createElement(Wrapper, null, react_default.createElement(TypeIcon2, { viewBox: "0 0 14 14", width: "12", height: "12", type: "story" }, react_default.createElement(UseSymbol, { type: "story" }))), children2);
12174
+ return react_default.createElement(BranchNode, { isExpandable, tabIndex: -1, ...props }, react_default.createElement(Wrapper, null, isExpandable && react_default.createElement(CollapseIcon2, { isExpanded }), react_default.createElement(TypeIcon2, { viewBox: "0 0 14 14", width: "12", height: "12", type: "story" }, react_default.createElement(UseSymbol, { type: "story" }))), children2);
10673
12175
  }, "StoryNode"));
12176
+ var TestNode = react_default.memo(/* @__PURE__ */ __name(function TestNode2({
12177
+ theme,
12178
+ children: children2,
12179
+ ...props
12180
+ }) {
12181
+ return react_default.createElement(LeafNode, { tabIndex: -1, ...props }, react_default.createElement(Wrapper, null, react_default.createElement(TypeIcon2, { viewBox: "0 0 14 14", width: "12", height: "12", type: "test" }, react_default.createElement(UseSymbol, { type: "test" }))), children2);
12182
+ }, "TestNode"));
10674
12183
 
10675
12184
  // ../node_modules/es-toolkit/dist/function/after.mjs
10676
12185
  function after(n3, func) {
@@ -11036,7 +12545,7 @@ var useExpanded = /* @__PURE__ */ __name(({
11036
12545
  target.blur();
11037
12546
  }
11038
12547
  const type = highlightedElement.getAttribute("data-nodetype");
11039
- if ((isEnter || isSpace) && ["component", "story", "document"].includes(type)) {
12548
+ if (type && (isEnter || isSpace) && ["component", "story", "document", "test"].includes(type)) {
11040
12549
  onSelectStoryId(highlightedItemId);
11041
12550
  }
11042
12551
  const isExpanded = highlightedElement.getAttribute("aria-expanded");
@@ -11081,7 +12590,7 @@ var Container6 = styled.div((props) => ({
11081
12590
  marginTop: props.hasOrphans ? 20 : 0,
11082
12591
  marginBottom: 20
11083
12592
  }));
11084
- var CollapseButton = styled.button(({ theme }) => ({
12593
+ var CollapseButton = styled.button({
11085
12594
  all: "unset",
11086
12595
  display: "flex",
11087
12596
  padding: "0px 8px",
@@ -11095,7 +12604,7 @@ var CollapseButton = styled.button(({ theme }) => ({
11095
12604
  outline: "none",
11096
12605
  background: "var(--tree-node-background-hover)"
11097
12606
  }
11098
- }));
12607
+ });
11099
12608
  var LeafNodeStyleWrapper = styled.div(({ theme }) => ({
11100
12609
  position: "relative",
11101
12610
  display: "flex",
@@ -11189,22 +12698,23 @@ var statusOrder = [
11189
12698
  "status-value:pending",
11190
12699
  "status-value:unknown"
11191
12700
  ];
11192
- var Node2 = react_default.memo(/* @__PURE__ */ __name(function Node3({
11193
- item,
11194
- statuses,
11195
- groupStatus,
11196
- refId,
11197
- docsMode,
11198
- isOrphan,
11199
- isDisplayed,
11200
- isSelected,
11201
- isFullyExpanded,
11202
- setFullyExpanded,
11203
- isExpanded,
11204
- setExpanded,
11205
- onSelectStoryId,
11206
- api
11207
- }) {
12701
+ var Node2 = react_default.memo(/* @__PURE__ */ __name(function Node3(props) {
12702
+ const {
12703
+ item,
12704
+ statuses,
12705
+ groupStatus,
12706
+ refId,
12707
+ docsMode,
12708
+ isOrphan,
12709
+ isDisplayed,
12710
+ isSelected,
12711
+ isFullyExpanded,
12712
+ setFullyExpanded,
12713
+ isExpanded,
12714
+ setExpanded,
12715
+ onSelectStoryId,
12716
+ api
12717
+ } = props;
11208
12718
  const { isDesktop, isMobile, setMobileMenuOpen } = useLayout();
11209
12719
  const { counts, statusesByValue } = useStatusSummary(item);
11210
12720
  if (!isDisplayed) {
@@ -11261,58 +12771,6 @@ var Node2 = react_default.memo(/* @__PURE__ */ __name(function Node3({
11261
12771
  const id = createId(item.id, refId);
11262
12772
  const contextMenu = refId === "storybook_internal" ? useContextMenu(item, statusLinks, api) : { node: null, onMouseEnter: /* @__PURE__ */ __name(() => {
11263
12773
  }, "onMouseEnter") };
11264
- if (item.type === "story" || item.type === "docs") {
11265
- const LeafNode2 = item.type === "docs" ? DocumentNode : StoryNode;
11266
- const statusValue = getMostCriticalStatusValue(
11267
- Object.values(statuses || {}).map((s2) => s2.value)
11268
- );
11269
- const [icon, textColor] = statusMapping[statusValue];
11270
- return react_default.createElement(
11271
- LeafNodeStyleWrapper,
11272
- {
11273
- key: id,
11274
- className: "sidebar-item",
11275
- "data-selected": isSelected,
11276
- "data-ref-id": refId,
11277
- "data-item-id": item.id,
11278
- "data-parent-id": item.parent,
11279
- "data-nodetype": item.type === "docs" ? "document" : "story",
11280
- "data-highlightable": isDisplayed,
11281
- onMouseEnter: contextMenu.onMouseEnter
11282
- },
11283
- react_default.createElement(
11284
- LeafNode2,
11285
- {
11286
- style: isSelected ? {} : { color: textColor },
11287
- href: getLink(item, refId),
11288
- id,
11289
- depth: isOrphan ? item.depth : item.depth - 1,
11290
- onClick: (event) => {
11291
- event.preventDefault();
11292
- onSelectStoryId(item.id);
11293
- if (isMobile) {
11294
- setMobileMenuOpen(false);
11295
- }
11296
- },
11297
- ...item.type === "docs" && { docsMode }
11298
- },
11299
- item.renderLabel?.(item, api) || item.name
11300
- ),
11301
- isSelected && react_default.createElement(SkipToContentLink, { asChild: true }, react_default.createElement("a", { href: "#storybook-preview-wrapper" }, "Skip to canvas")),
11302
- contextMenu.node,
11303
- icon ? react_default.createElement(
11304
- StatusButton,
11305
- {
11306
- "aria-label": `Test status: ${statusValue.replace("status-value:", "")}`,
11307
- role: "status",
11308
- type: "button",
11309
- status: statusValue,
11310
- selectedItem: isSelected
11311
- },
11312
- icon
11313
- ) : null
11314
- );
11315
- }
11316
12774
  if (item.type === "root") {
11317
12775
  return react_default.createElement(
11318
12776
  RootNode,
@@ -11354,15 +12812,31 @@ var Node2 = react_default.memo(/* @__PURE__ */ __name(function Node3({
11354
12812
  )
11355
12813
  );
11356
12814
  }
11357
- if (item.type === "component" || item.type === "group") {
11358
- const itemStatus = groupStatus?.[item.id];
11359
- const color2 = itemStatus ? statusMapping[itemStatus][1] : null;
11360
- const BranchNode2 = item.type === "component" ? ComponentNode : GroupNode;
12815
+ const itemStatus = getMostCriticalStatusValue(Object.values(statuses || {}).map((s2) => s2.value));
12816
+ const [itemIcon, itemColor] = statusMapping[itemStatus];
12817
+ const itemStatusButton = itemIcon ? react_default.createElement(
12818
+ StatusButton,
12819
+ {
12820
+ "aria-label": `Test status: ${itemStatus.replace("status-value:", "")}`,
12821
+ role: "status",
12822
+ type: "button",
12823
+ status: itemStatus,
12824
+ selectedItem: isSelected
12825
+ },
12826
+ itemIcon
12827
+ ) : null;
12828
+ if (item.type === "component" || item.type === "group" || item.type === "story" && "children" in item && item.children) {
12829
+ const { children: children2 = [] } = item;
12830
+ const BranchNode2 = { component: ComponentNode, group: GroupNode, story: StoryNode }[item.type];
12831
+ const status = getMostCriticalStatusValue([itemStatus, groupStatus?.[item.id]]);
12832
+ const color2 = status ? statusMapping[status][1] : null;
12833
+ const showBranchStatus = status === "status-value:error" || status === "status-value:warning";
11361
12834
  return react_default.createElement(
11362
12835
  LeafNodeStyleWrapper,
11363
12836
  {
11364
12837
  key: id,
11365
12838
  className: "sidebar-item",
12839
+ "data-selected": isSelected,
11366
12840
  "data-ref-id": refId,
11367
12841
  "data-item-id": item.id,
11368
12842
  "data-parent-id": item.parent,
@@ -11374,24 +12848,32 @@ var Node2 = react_default.memo(/* @__PURE__ */ __name(function Node3({
11374
12848
  BranchNode2,
11375
12849
  {
11376
12850
  id,
11377
- style: color2 ? { color: color2 } : {},
11378
- "aria-controls": item.children && item.children.join(" "),
12851
+ style: color2 && !isSelected ? { color: color2 } : {},
12852
+ "aria-controls": children2.join(" "),
11379
12853
  "aria-expanded": isExpanded,
11380
12854
  depth: isOrphan ? item.depth : item.depth - 1,
11381
- isComponent: item.type === "component",
11382
- isExpandable: item.children && item.children.length > 0,
12855
+ isExpandable: children2.length > 0,
11383
12856
  isExpanded,
11384
12857
  onClick: (event) => {
11385
12858
  event.preventDefault();
11386
- setExpanded({ ids: [item.id], value: !isExpanded });
11387
- if (item.type === "component" && !isExpanded && isDesktop) {
12859
+ if (item.type === "story") {
11388
12860
  onSelectStoryId(item.id);
12861
+ if (!isExpanded || isSelected) {
12862
+ setExpanded({ ids: [item.id], value: !isExpanded });
12863
+ }
12864
+ } else if (item.type === "component") {
12865
+ if (!isExpanded && isDesktop) {
12866
+ onSelectStoryId(item.id);
12867
+ }
12868
+ setExpanded({ ids: [item.id], value: !isExpanded });
12869
+ } else {
12870
+ setExpanded({ ids: [item.id], value: !isExpanded });
11389
12871
  }
11390
12872
  },
11391
12873
  onMouseEnter: () => {
11392
- if (item.type === "component") {
12874
+ if (item.type === "component" || item.type === "story") {
11393
12875
  api.emit(PRELOAD_ENTRIES, {
11394
- ids: [item.children[0]],
12876
+ ids: [children2[0]],
11395
12877
  options: { target: refId }
11396
12878
  });
11397
12879
  }
@@ -11399,11 +12881,49 @@ var Node2 = react_default.memo(/* @__PURE__ */ __name(function Node3({
11399
12881
  },
11400
12882
  item.renderLabel?.(item, api) || item.name
11401
12883
  ),
12884
+ isSelected && react_default.createElement(SkipToContentLink, { asChild: true }, react_default.createElement("a", { href: "#storybook-preview-wrapper" }, "Skip to canvas")),
11402
12885
  contextMenu.node,
11403
- ["status-value:error", "status-value:warning"].includes(itemStatus) && react_default.createElement(StatusButton, { type: "button", status: itemStatus }, react_default.createElement("svg", { key: "icon", viewBox: "0 0 6 6", width: "6", height: "6", type: "dot" }, react_default.createElement(UseSymbol, { type: "dot" })))
12886
+ showBranchStatus ? react_default.createElement(StatusButton, { type: "button", status, selectedItem: isSelected }, react_default.createElement("svg", { key: "icon", viewBox: "0 0 6 6", width: "6", height: "6", type: "dot" }, react_default.createElement(UseSymbol, { type: "dot" }))) : itemStatusButton
11404
12887
  );
11405
12888
  }
11406
- return null;
12889
+ const isTest = item.type === "story" && item.subtype === "test";
12890
+ const LeafNode2 = isTest ? TestNode : { docs: DocumentNode, story: StoryNode }[item.type];
12891
+ const nodeType = isTest ? "test" : { docs: "document", story: "story" }[item.type];
12892
+ return react_default.createElement(
12893
+ LeafNodeStyleWrapper,
12894
+ {
12895
+ key: id,
12896
+ className: "sidebar-item",
12897
+ "data-selected": isSelected,
12898
+ "data-ref-id": refId,
12899
+ "data-item-id": item.id,
12900
+ "data-parent-id": item.parent,
12901
+ "data-nodetype": nodeType,
12902
+ "data-highlightable": isDisplayed,
12903
+ onMouseEnter: contextMenu.onMouseEnter
12904
+ },
12905
+ react_default.createElement(
12906
+ LeafNode2,
12907
+ {
12908
+ style: itemColor && !isSelected ? { color: itemColor } : {},
12909
+ href: getLink(item, refId),
12910
+ id,
12911
+ depth: isOrphan ? item.depth : item.depth - 1,
12912
+ onClick: (event) => {
12913
+ event.preventDefault();
12914
+ onSelectStoryId(item.id);
12915
+ if (isMobile) {
12916
+ setMobileMenuOpen(false);
12917
+ }
12918
+ },
12919
+ ...item.type === "docs" && { docsMode }
12920
+ },
12921
+ item.renderLabel?.(item, api) || item.name
12922
+ ),
12923
+ isSelected && react_default.createElement(SkipToContentLink, { asChild: true }, react_default.createElement("a", { href: "#storybook-preview-wrapper" }, "Skip to canvas")),
12924
+ contextMenu.node,
12925
+ itemStatusButton
12926
+ );
11407
12927
  }, "Node"));
11408
12928
  var Root = react_default.memo(/* @__PURE__ */ __name(function Root2({
11409
12929
  setExpanded,
@@ -11482,7 +13002,7 @@ var Tree = react_default.memo(/* @__PURE__ */ __name(function Tree2({
11482
13002
  if (onlyChild.type === "docs") {
11483
13003
  return true;
11484
13004
  }
11485
- if (onlyChild.type === "story") {
13005
+ if (onlyChild.type === "story" && onlyChild.subtype === "story") {
11486
13006
  return isStoryHoistable(onlyChild.name, name);
11487
13007
  }
11488
13008
  return false;
@@ -11490,7 +13010,7 @@ var Tree = react_default.memo(/* @__PURE__ */ __name(function Tree2({
11490
13010
  }, [data]);
11491
13011
  const collapsedItems = useMemo(
11492
13012
  () => Object.keys(data).filter((id) => !singleStoryComponentIds.includes(id)),
11493
- [singleStoryComponentIds]
13013
+ [data, singleStoryComponentIds]
11494
13014
  );
11495
13015
  const collapsedData = useMemo(() => {
11496
13016
  return singleStoryComponentIds.reduce(
@@ -11512,7 +13032,7 @@ var Tree = react_default.memo(/* @__PURE__ */ __name(function Tree2({
11512
13032
  },
11513
13033
  { ...data }
11514
13034
  );
11515
- }, [data]);
13035
+ }, [data, singleStoryComponentIds]);
11516
13036
  const ancestry = useMemo(() => {
11517
13037
  return collapsedItems.reduce(
11518
13038
  (acc, id) => Object.assign(acc, { [id]: getAncestorIds(collapsedData, id) }),
@@ -11689,11 +13209,10 @@ var Ref = react_default.memo(/* @__PURE__ */ __name(function Ref2(props) {
11689
13209
  const handleClick = useCallback(() => setExpanded((value) => !value), [setExpanded]);
11690
13210
  const setHighlightedItemId = useCallback(
11691
13211
  (itemId) => setHighlighted({ itemId, refId }),
11692
- [setHighlighted]
13212
+ [setHighlighted, refId]
11693
13213
  );
11694
13214
  const onSelectStoryId = useCallback(
11695
- // @ts-expect-error (non strict)
11696
- (storyId) => api && api.selectStory(storyId, void 0, { ref: !isMain && refId }),
13215
+ (storyId) => api?.selectStory(storyId, void 0, { ref: isMain ? void 0 : refId }),
11697
13216
  [api, isMain, refId]
11698
13217
  );
11699
13218
  return react_default.createElement(react_default.Fragment, null, isMain || react_default.createElement(
@@ -11809,9 +13328,8 @@ var useHighlighted = /* @__PURE__ */ __name(({
11809
13328
  if (highlightable[nextIndex].getAttribute("data-nodetype") === "component") {
11810
13329
  const { itemId, refId } = highlightedRef.current;
11811
13330
  const item = api.resolveStory(itemId, refId === "storybook_internal" ? void 0 : refId);
11812
- if (item.type === "component") {
13331
+ if (item?.type === "component") {
11813
13332
  api.emit(PRELOAD_ENTRIES, {
11814
- // @ts-expect-error (non strict)
11815
13333
  ids: [item.children[0]],
11816
13334
  options: { target: refId }
11817
13335
  });
@@ -11821,7 +13339,7 @@ var useHighlighted = /* @__PURE__ */ __name(({
11821
13339
  }, "navigateTree");
11822
13340
  document6.addEventListener("keydown", navigateTree);
11823
13341
  return () => document6.removeEventListener("keydown", navigateTree);
11824
- }, [isLoading, isBrowsing, highlightedRef, highlightElement]);
13342
+ }, [api, containerRef, isLoading, isBrowsing, highlightedRef, highlightElement]);
11825
13343
  return [highlighted, updateHighlighted, highlightedRef];
11826
13344
  }, "useHighlighted");
11827
13345
 
@@ -11988,8 +13506,8 @@ var SidebarMenu = /* @__PURE__ */ __name(({ menu, isHighlighted, onClick }) => {
11988
13506
  react_default.createElement(
11989
13507
  SidebarIconButton,
11990
13508
  {
11991
- title: "Shortcuts",
11992
- "aria-label": "Shortcuts",
13509
+ title: "Settings",
13510
+ "aria-label": "Settings",
11993
13511
  highlighted: !!isHighlighted,
11994
13512
  active: isTooltipVisible,
11995
13513
  size: "medium",
@@ -15288,6 +16806,7 @@ var FocusKey = styled.code(({ theme }) => ({
15288
16806
  margin: 5,
15289
16807
  marginTop: 6,
15290
16808
  height: 16,
16809
+ fontFamily: theme.typography.fonts.base,
15291
16810
  lineHeight: "16px",
15292
16811
  textAlign: "center",
15293
16812
  fontSize: "11px",
@@ -15659,7 +17178,7 @@ var Result = react_default.memo(/* @__PURE__ */ __name(function Result2({ item,
15659
17178
  const nameMatch = matches2.find((match) => match.key === "name");
15660
17179
  const pathMatches = matches2.filter((match) => match.key === "path");
15661
17180
  const [icon] = item.status ? statusMapping[item.status] : [];
15662
- return react_default.createElement(ResultRow, { ...props, onClick: click }, react_default.createElement(IconWrapper2, null, item.type === "component" && react_default.createElement(TypeIcon2, { viewBox: "0 0 14 14", width: "14", height: "14", type: "component" }, react_default.createElement(UseSymbol, { type: "component" })), item.type === "story" && react_default.createElement(TypeIcon2, { viewBox: "0 0 14 14", width: "14", height: "14", type: "story" }, react_default.createElement(UseSymbol, { type: "story" })), !(item.type === "component" || item.type === "story") && react_default.createElement(TypeIcon2, { viewBox: "0 0 14 14", width: "14", height: "14", type: "document" }, react_default.createElement(UseSymbol, { type: "document" }))), react_default.createElement(ResultRowContent, { className: "search-result-item--label" }, react_default.createElement(Title, null, react_default.createElement(Highlight, { match: nameMatch }, item.name)), react_default.createElement(Path, null, item.path.map((group, index) => react_default.createElement("span", { key: index }, react_default.createElement(Highlight, { match: pathMatches.find((match) => match.arrayIndex === index) }, group))))), item.status ? react_default.createElement(StatusLabel, { status: item.status }, icon) : null);
17181
+ return react_default.createElement(ResultRow, { ...props, onClick: click }, react_default.createElement(IconWrapper2, null, item.type === "component" && react_default.createElement(TypeIcon2, { viewBox: "0 0 14 14", width: "14", height: "14", type: "component" }, react_default.createElement(UseSymbol, { type: "component" })), item.type === "story" && react_default.createElement(TypeIcon2, { viewBox: "0 0 14 14", width: "14", height: "14", type: item.subtype }, react_default.createElement(UseSymbol, { type: item.subtype })), !(item.type === "component" || item.type === "story") && react_default.createElement(TypeIcon2, { viewBox: "0 0 14 14", width: "14", height: "14", type: "document" }, react_default.createElement(UseSymbol, { type: "document" }))), react_default.createElement(ResultRowContent, { className: "search-result-item--label" }, react_default.createElement(Title, null, react_default.createElement(Highlight, { match: nameMatch }, item.name)), react_default.createElement(Path, null, item.path.map((group, index) => react_default.createElement("span", { key: index }, react_default.createElement(Highlight, { match: pathMatches.find((match) => match.arrayIndex === index) }, group))))), item.status ? react_default.createElement(StatusLabel, { status: item.status }, icon) : null);
15663
17182
  }, "Result"));
15664
17183
  var SearchResults = react_default.memo(/* @__PURE__ */ __name(function SearchResults2({
15665
17184
  query,
@@ -16306,19 +17825,14 @@ var SidebarBottom = /* @__PURE__ */ __name(({ isDevelopment }) => {
16306
17825
  }, "SidebarBottom");
16307
17826
 
16308
17827
  // src/manager/components/sidebar/TagsFilterPanel.tsx
16309
- var BUILT_IN_TAGS = /* @__PURE__ */ new Set([
16310
- "dev",
16311
- "test",
16312
- "autodocs",
16313
- "attached-mdx",
16314
- "unattached-mdx",
16315
- "play-fn",
16316
- "test-fn",
16317
- "vitest",
16318
- "svelte-csf",
16319
- "svelte-csf-v4",
16320
- "svelte-csf-v5"
16321
- ]);
17828
+ var groupByType = /* @__PURE__ */ __name((filters) => filters.reduce(
17829
+ (acc, filter2) => {
17830
+ acc[filter2.type] = acc[filter2.type] || [];
17831
+ acc[filter2.type].push(filter2);
17832
+ return acc;
17833
+ },
17834
+ {}
17835
+ ), "groupByType");
16322
17836
  var Wrapper3 = styled.div({
16323
17837
  minWidth: 240,
16324
17838
  maxWidth: 300
@@ -16330,79 +17844,183 @@ var Actions3 = styled.div(({ theme }) => ({
16330
17844
  padding: 4,
16331
17845
  borderBottom: `1px solid ${theme.appBorderColor}`
16332
17846
  }));
17847
+ var TagRow = styled.div({
17848
+ display: "flex",
17849
+ "& button": {
17850
+ width: 64,
17851
+ maxWidth: 64,
17852
+ marginLeft: 4,
17853
+ paddingLeft: 0,
17854
+ paddingRight: 0,
17855
+ fontWeight: "normal",
17856
+ transition: "all 150ms"
17857
+ },
17858
+ "&:not(:hover)": {
17859
+ "& button": {
17860
+ marginLeft: 0,
17861
+ maxWidth: 0,
17862
+ opacity: 0
17863
+ },
17864
+ "& svg + input": {
17865
+ display: "none"
17866
+ }
17867
+ }
17868
+ });
17869
+ var Label = styled.div({
17870
+ overflow: "hidden",
17871
+ textOverflow: "ellipsis",
17872
+ whiteSpace: "nowrap"
17873
+ });
17874
+ var MutedText = styled.span(({ theme }) => ({
17875
+ color: theme.textMutedColor
17876
+ }));
16333
17877
  var TagsFilterPanel = /* @__PURE__ */ __name(({
16334
17878
  api,
16335
- allTags,
16336
- selectedTags,
16337
- toggleTag,
16338
- setAllTags,
16339
- inverted,
16340
- setInverted,
16341
- isDevelopment
17879
+ filtersById,
17880
+ includedFilters,
17881
+ excludedFilters,
17882
+ toggleFilter,
17883
+ setAllFilters,
17884
+ resetFilters,
17885
+ isDevelopment,
17886
+ isDefaultSelection,
17887
+ hasDefaultSelection
16342
17888
  }) => {
16343
- const [builtInEntries, userEntries] = Array.from(allTags.entries()).reduce(
16344
- (acc, [tag, count]) => {
16345
- acc[BUILT_IN_TAGS.has(tag) ? 0 : 1].push([tag, count]);
16346
- return acc;
16347
- },
16348
- [[], []]
17889
+ const ref = useRef(null);
17890
+ const renderLink = /* @__PURE__ */ __name(({
17891
+ id,
17892
+ type,
17893
+ title,
17894
+ icon,
17895
+ count
17896
+ }) => {
17897
+ const onToggle = /* @__PURE__ */ __name((selected, excluded) => toggleFilter(id, selected, excluded), "onToggle");
17898
+ const isIncluded = includedFilters.has(id);
17899
+ const isExcluded = excludedFilters.has(id);
17900
+ const isChecked = isIncluded || isExcluded;
17901
+ const toggleTagLabel = `${isChecked ? "Remove" : "Add"} ${type} filter: ${title}`;
17902
+ const invertButtonLabel = `${isExcluded ? "Include" : "Exclude"} ${type}: ${title}`;
17903
+ if (count === 0 && type === "built-in") {
17904
+ return void 0;
17905
+ }
17906
+ return {
17907
+ id: `filter-${type}-${id}`,
17908
+ content: react_default.createElement(TagRow, null, react_default.createElement(
17909
+ WithTooltip,
17910
+ {
17911
+ delayShow: 1e3,
17912
+ hasChrome: false,
17913
+ style: { minWidth: 0, flex: 1 },
17914
+ tooltip: react_default.createElement(TooltipNote, { note: toggleTagLabel }),
17915
+ trigger: "hover"
17916
+ },
17917
+ react_default.createElement(
17918
+ ListItem,
17919
+ {
17920
+ as: "label",
17921
+ icon: react_default.createElement(react_default.Fragment, null, isExcluded ? react_default.createElement(DeleteIcon, null) : isIncluded ? null : icon, react_default.createElement(
17922
+ Form.Checkbox,
17923
+ {
17924
+ checked: isChecked,
17925
+ onChange: () => onToggle(!isChecked),
17926
+ "data-tag": title
17927
+ }
17928
+ )),
17929
+ "aria-label": toggleTagLabel,
17930
+ title: react_default.createElement(Label, null, title, isExcluded && react_default.createElement(MutedText, null, " (excluded)")),
17931
+ right: isExcluded ? react_default.createElement("s", null, count) : react_default.createElement("span", null, count)
17932
+ }
17933
+ )
17934
+ ), react_default.createElement(
17935
+ WithTooltip,
17936
+ {
17937
+ delayShow: 1e3,
17938
+ hasChrome: false,
17939
+ tooltip: react_default.createElement(TooltipNote, { note: invertButtonLabel }),
17940
+ trigger: "hover"
17941
+ },
17942
+ react_default.createElement(
17943
+ Button,
17944
+ {
17945
+ variant: "ghost",
17946
+ size: "medium",
17947
+ onClick: () => onToggle(true, !isExcluded),
17948
+ "aria-label": invertButtonLabel
17949
+ },
17950
+ isExcluded ? "Include" : "Exclude"
17951
+ )
17952
+ ))
17953
+ };
17954
+ }, "renderLink");
17955
+ const groups = groupByType(Object.values(filtersById));
17956
+ const links = Object.values(groups).map(
17957
+ (group) => group.sort((a2, b2) => a2.id.localeCompare(b2.id)).map((filter2) => renderLink(filter2)).filter(Boolean)
16349
17958
  );
16350
- const docsUrl = api.getDocsUrl({ subpath: "writing-stories/tags#filtering-by-custom-tags" });
16351
- const noTags = {
16352
- id: "no-tags",
16353
- title: "There are no tags. Use tags to organize and filter your Storybook.",
16354
- isIndented: false
16355
- };
16356
- const groups = [
16357
- allTags.size === 0 ? [noTags] : [],
16358
- userEntries.sort((a2, b2) => a2[0].localeCompare(b2[0])).map(([tag, count]) => {
16359
- const checked = selectedTags.includes(tag);
16360
- const id = `tag-${tag}`;
16361
- return {
16362
- id,
16363
- title: tag,
16364
- right: count,
16365
- input: react_default.createElement(Form.Checkbox, { checked, onChange: () => toggleTag(tag) })
16366
- };
16367
- }),
16368
- builtInEntries.sort((a2, b2) => a2[0].localeCompare(b2[0])).map(([tag, count]) => {
16369
- const checked = selectedTags.includes(tag);
16370
- const id = `tag-${tag}`;
16371
- return {
16372
- id,
16373
- title: tag,
16374
- right: count,
16375
- input: react_default.createElement(Form.Checkbox, { checked, onChange: () => toggleTag(tag) })
16376
- };
16377
- })
16378
- ];
16379
- if (userEntries.length === 0 && isDevelopment) {
16380
- groups.push([
17959
+ if (!groups.tag?.length && isDevelopment) {
17960
+ links.push([
16381
17961
  {
16382
17962
  id: "tags-docs",
16383
17963
  title: "Learn how to add tags",
16384
17964
  icon: react_default.createElement(DocumentIcon, null),
16385
17965
  right: react_default.createElement(ShareAltIcon, null),
16386
- href: docsUrl
17966
+ href: api.getDocsUrl({ subpath: "writing-stories/tags#filtering-by-custom-tags" })
16387
17967
  }
16388
17968
  ]);
16389
17969
  }
16390
- return react_default.createElement(Wrapper3, null, allTags.size > 0 && react_default.createElement(Actions3, null, selectedTags.length ? react_default.createElement(IconButton, { id: "unselect-all", onClick: () => setAllTags(false) }, react_default.createElement(CloseIcon, null), "Clear filters") : react_default.createElement(IconButton, { id: "select-all", onClick: () => setAllTags(true) }, react_default.createElement(BatchAcceptIcon, null), "Select all"), react_default.createElement(
17970
+ const filtersLabel = includedFilters.size === 0 && excludedFilters.size === 0 ? "Select all" : "Clear filters";
17971
+ return react_default.createElement(Wrapper3, { ref }, Object.keys(filtersById).length > 0 && react_default.createElement(Actions3, null, includedFilters.size === 0 && excludedFilters.size === 0 ? react_default.createElement(
16391
17972
  IconButton,
16392
17973
  {
16393
- id: "invert-selection",
16394
- disabled: selectedTags.length === 0,
16395
- onClick: () => setInverted(!inverted),
16396
- active: inverted
17974
+ id: "select-all",
17975
+ "aria-label": filtersLabel,
17976
+ key: "select-all",
17977
+ onClick: () => setAllFilters(true)
17978
+ },
17979
+ react_default.createElement(BatchAcceptIcon, null),
17980
+ filtersLabel
17981
+ ) : react_default.createElement(
17982
+ IconButton,
17983
+ {
17984
+ id: "deselect-all",
17985
+ "aria-label": filtersLabel,
17986
+ key: "deselect-all",
17987
+ onClick: () => setAllFilters(false)
17988
+ },
17989
+ react_default.createElement(SweepIcon, null),
17990
+ filtersLabel
17991
+ ), hasDefaultSelection && react_default.createElement(
17992
+ WithTooltip,
17993
+ {
17994
+ delayShow: 1e3,
17995
+ hasChrome: false,
17996
+ tooltip: react_default.createElement(TooltipNote, { note: "Reset to default selection" }),
17997
+ trigger: "hover"
16397
17998
  },
16398
- inverted ? react_default.createElement(EyeCloseIcon, null) : react_default.createElement(EyeIcon, null),
16399
- "Invert"
16400
- )), react_default.createElement(TooltipLinkList, { links: groups }));
17999
+ react_default.createElement(
18000
+ IconButton,
18001
+ {
18002
+ id: "reset-filters",
18003
+ key: "reset-filters",
18004
+ onClick: resetFilters,
18005
+ "aria-label": "Reset filters",
18006
+ disabled: isDefaultSelection
18007
+ },
18008
+ react_default.createElement(UndoIcon, null)
18009
+ )
18010
+ )), react_default.createElement(TooltipLinkList, { links }));
16401
18011
  }, "TagsFilterPanel");
16402
18012
 
16403
18013
  // src/manager/components/sidebar/TagsFilter.tsx
16404
18014
  var TAGS_FILTER = "tags-filter";
16405
- var BUILT_IN_TAGS_HIDE = /* @__PURE__ */ new Set(["dev", "autodocs", "test", "attached-mdx", "unattached-mdx"]);
18015
+ var BUILT_IN_TAGS = /* @__PURE__ */ new Set([
18016
+ "dev",
18017
+ "test",
18018
+ "autodocs",
18019
+ "attached-mdx",
18020
+ "unattached-mdx",
18021
+ "play-fn",
18022
+ "test-fn"
18023
+ ]);
16406
18024
  var Wrapper4 = styled.div({
16407
18025
  position: "relative"
16408
18026
  });
@@ -16423,53 +18041,119 @@ var TagSelected = styled(Badge)(({ theme }) => ({
16423
18041
  background: theme.color.secondary,
16424
18042
  color: theme.color.lightest
16425
18043
  }));
16426
- var TagsFilter = /* @__PURE__ */ __name(({
16427
- api,
16428
- indexJson,
16429
- initialSelectedTags = [],
16430
- isDevelopment
16431
- }) => {
16432
- const [selectedTags, setSelectedTags] = useState(initialSelectedTags);
18044
+ var TagsFilter = /* @__PURE__ */ __name(({ api, indexJson, isDevelopment, tagPresets }) => {
18045
+ const filtersById = useMemo(() => {
18046
+ const userTagsCounts = Object.values(indexJson.entries).reduce((acc, entry) => {
18047
+ entry.tags?.forEach((tag) => {
18048
+ if (!BUILT_IN_TAGS.has(tag)) {
18049
+ acc.set(tag, (acc.get(tag) || 0) + 1);
18050
+ }
18051
+ });
18052
+ return acc;
18053
+ }, /* @__PURE__ */ new Map());
18054
+ const userFilters = Object.fromEntries(
18055
+ userTagsCounts.entries().map(([tag, count]) => {
18056
+ const filterFn = /* @__PURE__ */ __name((entry, excluded) => excluded ? !entry.tags?.includes(tag) : !!entry.tags?.includes(tag), "filterFn");
18057
+ return [tag, { id: tag, type: "tag", title: tag, count, filterFn }];
18058
+ })
18059
+ );
18060
+ const withCount = /* @__PURE__ */ __name((filterFn) => ({
18061
+ count: Object.values(indexJson.entries).filter((entry) => filterFn(entry)).length,
18062
+ filterFn
18063
+ }), "withCount");
18064
+ const builtInFilters = {
18065
+ _docs: {
18066
+ id: "_docs",
18067
+ type: "built-in",
18068
+ title: "Documentation",
18069
+ icon: react_default.createElement(DocumentIcon, { color: color.gold }),
18070
+ ...withCount(
18071
+ (entry, excluded) => excluded ? entry.type !== "docs" : entry.type === "docs"
18072
+ )
18073
+ },
18074
+ _play: {
18075
+ id: "_play",
18076
+ type: "built-in",
18077
+ title: "Play",
18078
+ icon: react_default.createElement(PlayHollowIcon, { color: color.seafoam }),
18079
+ ...withCount(
18080
+ (entry, excluded) => excluded ? entry.type !== "story" || !entry.tags?.includes("play-fn") : entry.type === "story" && !!entry.tags?.includes("play-fn")
18081
+ )
18082
+ },
18083
+ _test: {
18084
+ id: "_test",
18085
+ type: "built-in",
18086
+ title: "Testing",
18087
+ icon: react_default.createElement(BeakerIcon, { color: color.green }),
18088
+ ...withCount(
18089
+ (entry, excluded) => excluded ? entry.type !== "story" || entry.subtype !== "test" : entry.type === "story" && entry.subtype === "test"
18090
+ )
18091
+ }
18092
+ };
18093
+ return { ...userFilters, ...builtInFilters };
18094
+ }, [indexJson.entries]);
18095
+ const { defaultIncluded, defaultExcluded } = useMemo(() => {
18096
+ return Object.entries(tagPresets).reduce(
18097
+ (acc, [tag, { defaultFilterSelection }]) => {
18098
+ if (defaultFilterSelection === "include") {
18099
+ acc.defaultIncluded.add(tag);
18100
+ } else if (defaultFilterSelection === "exclude") {
18101
+ acc.defaultExcluded.add(tag);
18102
+ }
18103
+ return acc;
18104
+ },
18105
+ { defaultIncluded: /* @__PURE__ */ new Set(), defaultExcluded: /* @__PURE__ */ new Set() }
18106
+ );
18107
+ }, [tagPresets]);
18108
+ const [includedFilters, setIncludedFilters] = useState(new Set(defaultIncluded));
18109
+ const [excludedFilters, setExcludedFilters] = useState(new Set(defaultExcluded));
16433
18110
  const [expanded, setExpanded] = useState(false);
16434
- const [inverted, setInverted] = useState(false);
16435
- const tagsActive = selectedTags.length > 0;
18111
+ const tagsActive = includedFilters.size > 0 || excludedFilters.size > 0;
18112
+ const resetFilters = useCallback(() => {
18113
+ setIncludedFilters(new Set(defaultIncluded));
18114
+ setExcludedFilters(new Set(defaultExcluded));
18115
+ }, [defaultIncluded, defaultExcluded]);
18116
+ useEffect(resetFilters, [resetFilters]);
16436
18117
  useEffect(() => {
16437
18118
  api.experimental_setFilter(TAGS_FILTER, (item) => {
16438
- if (selectedTags.length === 0) {
16439
- return true;
16440
- }
16441
- const match = selectedTags.some((tag) => item.tags?.includes(tag));
16442
- return inverted ? !match : match;
16443
- });
16444
- }, [api, selectedTags, inverted]);
16445
- const allTags = Object.values(indexJson.entries).reduce((acc, entry) => {
16446
- entry.tags?.forEach((tag) => {
16447
- if (!BUILT_IN_TAGS_HIDE.has(tag)) {
16448
- acc.set(tag, (acc.get(tag) || 0) + 1);
16449
- }
18119
+ const included = Object.values(
18120
+ groupByType(Array.from(includedFilters).map((id) => filtersById[id]))
18121
+ );
18122
+ const excluded = Object.values(
18123
+ groupByType(Array.from(excludedFilters).map((id) => filtersById[id]))
18124
+ );
18125
+ return (!included.length || included.every((group) => group.some(({ filterFn }) => filterFn(item, false)))) && (!excluded.length || excluded.every((group) => group.every(({ filterFn }) => filterFn(item, true))));
16450
18126
  });
16451
- return acc;
16452
- }, /* @__PURE__ */ new Map());
16453
- const toggleTag = useCallback(
16454
- (tag) => {
16455
- if (selectedTags.includes(tag)) {
16456
- setSelectedTags(selectedTags.filter((t2) => t2 !== tag));
18127
+ }, [api, includedFilters, excludedFilters, filtersById]);
18128
+ const toggleFilter = useCallback(
18129
+ (id, selected, excluded) => {
18130
+ const set2 = /* @__PURE__ */ new Set([id]);
18131
+ if (excluded === true) {
18132
+ setExcludedFilters(excludedFilters.union(set2));
18133
+ setIncludedFilters(includedFilters.difference(set2));
18134
+ } else if (excluded === false) {
18135
+ setIncludedFilters(includedFilters.union(set2));
18136
+ setExcludedFilters(excludedFilters.difference(set2));
18137
+ } else if (selected) {
18138
+ setIncludedFilters(includedFilters.union(set2));
18139
+ setExcludedFilters(excludedFilters.difference(set2));
16457
18140
  } else {
16458
- setSelectedTags([...selectedTags, tag]);
18141
+ setIncludedFilters(includedFilters.difference(set2));
18142
+ setExcludedFilters(excludedFilters.difference(set2));
16459
18143
  }
16460
18144
  },
16461
- [selectedTags, setSelectedTags]
18145
+ [includedFilters, excludedFilters]
16462
18146
  );
16463
- const setAllTags = useCallback(
18147
+ const setAllFilters = useCallback(
16464
18148
  (selected) => {
16465
18149
  if (selected) {
16466
- setSelectedTags(Array.from(allTags.keys()));
18150
+ setIncludedFilters(new Set(Object.keys(filtersById)));
16467
18151
  } else {
16468
- setSelectedTags([]);
16469
- setInverted(false);
18152
+ setIncludedFilters(/* @__PURE__ */ new Set());
16470
18153
  }
18154
+ setExcludedFilters(/* @__PURE__ */ new Set());
16471
18155
  },
16472
- [allTags, setSelectedTags]
18156
+ [filtersById]
16473
18157
  );
16474
18158
  const handleToggleExpand = useCallback(
16475
18159
  (event) => {
@@ -16478,7 +18162,7 @@ var TagsFilter = /* @__PURE__ */ __name(({
16478
18162
  },
16479
18163
  [expanded, setExpanded]
16480
18164
  );
16481
- if (allTags.size === 0 && !isDevelopment) {
18165
+ if (Object.keys(filtersById).length === 0 && !isDevelopment) {
16482
18166
  return null;
16483
18167
  }
16484
18168
  return react_default.createElement(
@@ -16492,18 +18176,20 @@ var TagsFilter = /* @__PURE__ */ __name(({
16492
18176
  TagsFilterPanel,
16493
18177
  {
16494
18178
  api,
16495
- allTags,
16496
- selectedTags,
16497
- toggleTag,
16498
- setAllTags,
16499
- inverted,
16500
- setInverted,
16501
- isDevelopment
18179
+ filtersById,
18180
+ includedFilters,
18181
+ excludedFilters,
18182
+ toggleFilter,
18183
+ setAllFilters,
18184
+ resetFilters,
18185
+ isDevelopment,
18186
+ isDefaultSelection: includedFilters.symmetricDifference(defaultIncluded).size === 0 && excludedFilters.symmetricDifference(defaultExcluded).size === 0,
18187
+ hasDefaultSelection: defaultIncluded.size > 0 || defaultExcluded.size > 0
16502
18188
  }
16503
18189
  ),
16504
18190
  closeOnOutsideClick: true
16505
18191
  },
16506
- react_default.createElement(Wrapper4, null, react_default.createElement(IconButton, { key: "tags", title: "Tag filters", active: tagsActive, onClick: handleToggleExpand }, react_default.createElement(FilterIcon, null)), selectedTags.length > 0 && react_default.createElement(TagSelected, null))
18192
+ react_default.createElement(Wrapper4, null, react_default.createElement(IconButton, { key: "tags", title: "Tag filters", active: tagsActive, onClick: handleToggleExpand }, react_default.createElement(FilterIcon, null)), includedFilters.size + excludedFilters.size > 0 && react_default.createElement(TagSelected, null))
16507
18193
  );
16508
18194
  }, "TagsFilter");
16509
18195
 
@@ -17322,11 +19008,11 @@ function countBy(collection, iteratee$1) {
17322
19008
  return {};
17323
19009
  }
17324
19010
  const array = isArrayLike(collection) ? Array.from(collection) : Object.values(collection);
17325
- const mapper3 = iteratee(iteratee$1 ?? void 0);
19011
+ const mapper5 = iteratee(iteratee$1 ?? void 0);
17326
19012
  const result2 = /* @__PURE__ */ Object.create(null);
17327
19013
  for (let i2 = 0; i2 < array.length; i2++) {
17328
19014
  const item = array[i2];
17329
- const key = mapper3(item);
19015
+ const key = mapper5(item);
17330
19016
  result2[key] = (result2[key] ?? 0) + 1;
17331
19017
  }
17332
19018
  return result2;
@@ -17385,10 +19071,10 @@ function last2(array) {
17385
19071
  __name(last2, "last");
17386
19072
 
17387
19073
  // ../node_modules/es-toolkit/dist/array/differenceBy.mjs
17388
- function differenceBy(firstArr, secondArr, mapper3) {
17389
- const mappedSecondSet = new Set(secondArr.map((item) => mapper3(item)));
19074
+ function differenceBy(firstArr, secondArr, mapper5) {
19075
+ const mappedSecondSet = new Set(secondArr.map((item) => mapper5(item)));
17390
19076
  return firstArr.filter((item) => {
17391
- return !mappedSecondSet.has(mapper3(item));
19077
+ return !mappedSecondSet.has(mapper5(item));
17392
19078
  });
17393
19079
  }
17394
19080
  __name(differenceBy, "differenceBy");
@@ -18151,9 +19837,9 @@ function intersection2(...arrays) {
18151
19837
  __name(intersection2, "intersection");
18152
19838
 
18153
19839
  // ../node_modules/es-toolkit/dist/array/intersectionBy.mjs
18154
- function intersectionBy(firstArr, secondArr, mapper3) {
18155
- const mappedSecondSet = new Set(secondArr.map(mapper3));
18156
- return firstArr.filter((item) => mappedSecondSet.has(mapper3(item)));
19840
+ function intersectionBy(firstArr, secondArr, mapper5) {
19841
+ const mappedSecondSet = new Set(secondArr.map(mapper5));
19842
+ return firstArr.filter((item) => mappedSecondSet.has(mapper5(item)));
18157
19843
  }
18158
19844
  __name(intersectionBy, "intersectionBy");
18159
19845
 
@@ -19353,11 +21039,11 @@ function union(...arrays) {
19353
21039
  __name(union, "union");
19354
21040
 
19355
21041
  // ../node_modules/es-toolkit/dist/array/uniqBy.mjs
19356
- function uniqBy(arr, mapper3) {
21042
+ function uniqBy(arr, mapper5) {
19357
21043
  const map2 = /* @__PURE__ */ new Map();
19358
21044
  for (let i2 = 0; i2 < arr.length; i2++) {
19359
21045
  const item = arr[i2];
19360
- const key = mapper3(item);
21046
+ const key = mapper5(item);
19361
21047
  if (!map2.has(key)) {
19362
21048
  map2.set(key, item);
19363
21049
  }
@@ -19530,15 +21216,15 @@ __name(windowed, "windowed");
19530
21216
  // ../node_modules/es-toolkit/dist/compat/array/xorBy.mjs
19531
21217
  function xorBy(...values3) {
19532
21218
  const lastValue = last2(values3);
19533
- let mapper3 = identity;
21219
+ let mapper5 = identity;
19534
21220
  if (!isArrayLikeObject(lastValue) && lastValue != null) {
19535
- mapper3 = iteratee(lastValue);
21221
+ mapper5 = iteratee(lastValue);
19536
21222
  values3 = values3.slice(0, -1);
19537
21223
  }
19538
21224
  const arrays = values3.filter(isArrayLikeObject);
19539
- const union2 = unionBy(...arrays, mapper3);
19540
- const intersections = windowed(arrays, 2).map(([arr1, arr2]) => intersectionBy2(arr1, arr2, mapper3));
19541
- return differenceBy2(union2, unionBy(...intersections, mapper3), mapper3);
21225
+ const union2 = unionBy(...arrays, mapper5);
21226
+ const intersections = windowed(arrays, 2).map(([arr1, arr2]) => intersectionBy2(arr1, arr2, mapper5));
21227
+ return differenceBy2(union2, unionBy(...intersections, mapper5), mapper5);
19542
21228
  }
19543
21229
  __name(xorBy, "xorBy");
19544
21230
 
@@ -23562,6 +25248,14 @@ var Sidebar = react_default.memo(/* @__PURE__ */ __name(function Sidebar2({
23562
25248
  const lastViewedProps = useLastViewed(selected);
23563
25249
  const { isMobile } = useLayout();
23564
25250
  const api = useStorybookApi();
25251
+ const tagPresets = useMemo(
25252
+ () => Object.entries(scope.TAGS_OPTIONS ?? {}).reduce((acc, entry) => {
25253
+ const [tag, option] = entry;
25254
+ acc[tag] = option;
25255
+ return acc;
25256
+ }, {}),
25257
+ []
25258
+ );
23565
25259
  return react_default.createElement(Container7, { className: "container sidebar-container", "aria-label": "Global" }, react_default.createElement(ScrollArea, { vertical: true, offset: 3, scrollbarSize: 6 }, react_default.createElement(Top, { row: 1.6 }, react_default.createElement(
23566
25260
  Heading,
23567
25261
  {
@@ -23603,7 +25297,15 @@ var Sidebar = react_default.memo(/* @__PURE__ */ __name(function Sidebar2({
23603
25297
  onOpenChange: setIsFileSearchModalOpen
23604
25298
  }
23605
25299
  )),
23606
- searchFieldContent: indexJson && react_default.createElement(TagsFilter, { api, indexJson, isDevelopment }),
25300
+ searchFieldContent: indexJson && react_default.createElement(
25301
+ TagsFilter,
25302
+ {
25303
+ api,
25304
+ indexJson,
25305
+ isDevelopment,
25306
+ tagPresets
25307
+ }
25308
+ ),
23607
25309
  ...lastViewedProps
23608
25310
  },
23609
25311
  ({
@@ -23639,241 +25341,9 @@ var Sidebar = react_default.memo(/* @__PURE__ */ __name(function Sidebar2({
23639
25341
  )), isMobile || isLoading ? null : react_default.createElement(SidebarBottom, { isDevelopment })));
23640
25342
  }, "Sidebar"));
23641
25343
 
23642
- // src/manager/container/Menu.tsx
23643
- var focusableUIElements = {
23644
- storySearchField: "storybook-explorer-searchfield",
23645
- storyListMenu: "storybook-explorer-menu",
23646
- storyPanelRoot: "storybook-panel-root"
23647
- };
23648
- var Key = styled.span(({ theme }) => ({
23649
- display: "inline-block",
23650
- height: 16,
23651
- lineHeight: "16px",
23652
- textAlign: "center",
23653
- fontSize: "11px",
23654
- background: theme.base === "light" ? "rgba(0,0,0,0.05)" : "rgba(255,255,255,0.05)",
23655
- color: theme.base === "light" ? theme.color.dark : theme.textMutedColor,
23656
- borderRadius: 2,
23657
- userSelect: "none",
23658
- pointerEvents: "none",
23659
- padding: "0 6px"
23660
- }));
23661
- var KeyChild = styled.code({
23662
- padding: 0,
23663
- verticalAlign: "middle",
23664
- "& + &": {
23665
- marginLeft: 6
23666
- }
23667
- });
23668
- var Shortcut = /* @__PURE__ */ __name(({ keys: keys2 }) => react_default.createElement(Key, null, keys2.map((key) => react_default.createElement(KeyChild, { key }, shortcutToHumanString([key])))), "Shortcut");
23669
- var useMenu = /* @__PURE__ */ __name((state, api, showToolbar, isFullscreen, isPanelShown, isNavShown, enableShortcuts) => {
23670
- const shortcutKeys = api.getShortcutKeys();
23671
- const about = useMemo(
23672
- () => ({
23673
- id: "about",
23674
- title: "About your Storybook",
23675
- onClick: /* @__PURE__ */ __name(() => api.changeSettingsTab("about"), "onClick"),
23676
- icon: react_default.createElement(InfoIcon, null)
23677
- }),
23678
- [api]
23679
- );
23680
- const documentation = useMemo(() => {
23681
- const docsUrl = api.getDocsUrl({ versioned: true, renderer: true });
23682
- return {
23683
- id: "documentation",
23684
- title: "Documentation",
23685
- href: docsUrl,
23686
- icon: react_default.createElement(ShareAltIcon, null)
23687
- };
23688
- }, [api]);
23689
- const whatsNewNotificationsEnabled = state.whatsNewData?.status === "SUCCESS" && !state.disableWhatsNewNotifications;
23690
- const isWhatsNewUnread = api.isWhatsNewUnread();
23691
- const whatsNew = useMemo(
23692
- () => ({
23693
- id: "whats-new",
23694
- title: "What's new?",
23695
- onClick: /* @__PURE__ */ __name(() => api.changeSettingsTab("whats-new"), "onClick"),
23696
- right: whatsNewNotificationsEnabled && isWhatsNewUnread && react_default.createElement(Badge, { status: "positive" }, "Check it out"),
23697
- icon: react_default.createElement(WandIcon, null)
23698
- }),
23699
- [api, whatsNewNotificationsEnabled, isWhatsNewUnread]
23700
- );
23701
- const shortcuts = useMemo(
23702
- () => ({
23703
- id: "shortcuts",
23704
- title: "Keyboard shortcuts",
23705
- onClick: /* @__PURE__ */ __name(() => api.changeSettingsTab("shortcuts"), "onClick"),
23706
- right: enableShortcuts ? react_default.createElement(Shortcut, { keys: shortcutKeys.shortcutsPage }) : null,
23707
- icon: react_default.createElement(CommandIcon, null)
23708
- }),
23709
- [api, enableShortcuts, shortcutKeys.shortcutsPage]
23710
- );
23711
- const sidebarToggle = useMemo(
23712
- () => ({
23713
- id: "S",
23714
- title: "Show sidebar",
23715
- onClick: /* @__PURE__ */ __name(() => api.toggleNav(), "onClick"),
23716
- active: isNavShown,
23717
- right: enableShortcuts ? react_default.createElement(Shortcut, { keys: shortcutKeys.toggleNav }) : null,
23718
- icon: isNavShown ? react_default.createElement(CheckIcon, null) : null
23719
- }),
23720
- [api, enableShortcuts, shortcutKeys, isNavShown]
23721
- );
23722
- const toolbarToogle = useMemo(
23723
- () => ({
23724
- id: "T",
23725
- title: "Show toolbar",
23726
- onClick: /* @__PURE__ */ __name(() => api.toggleToolbar(), "onClick"),
23727
- active: showToolbar,
23728
- right: enableShortcuts ? react_default.createElement(Shortcut, { keys: shortcutKeys.toolbar }) : null,
23729
- icon: showToolbar ? react_default.createElement(CheckIcon, null) : null
23730
- }),
23731
- [api, enableShortcuts, shortcutKeys, showToolbar]
23732
- );
23733
- const addonsToggle = useMemo(
23734
- () => ({
23735
- id: "A",
23736
- title: "Show addons panel",
23737
- onClick: /* @__PURE__ */ __name(() => api.togglePanel(), "onClick"),
23738
- active: isPanelShown,
23739
- right: enableShortcuts ? react_default.createElement(Shortcut, { keys: shortcutKeys.togglePanel }) : null,
23740
- icon: isPanelShown ? react_default.createElement(CheckIcon, null) : null
23741
- }),
23742
- [api, enableShortcuts, shortcutKeys, isPanelShown]
23743
- );
23744
- const addonsOrientationToggle = useMemo(
23745
- () => ({
23746
- id: "D",
23747
- title: "Change addons orientation",
23748
- onClick: /* @__PURE__ */ __name(() => api.togglePanelPosition(), "onClick"),
23749
- right: enableShortcuts ? react_default.createElement(Shortcut, { keys: shortcutKeys.panelPosition }) : null
23750
- }),
23751
- [api, enableShortcuts, shortcutKeys]
23752
- );
23753
- const fullscreenToggle = useMemo(
23754
- () => ({
23755
- id: "F",
23756
- title: "Go full screen",
23757
- onClick: /* @__PURE__ */ __name(() => api.toggleFullscreen(), "onClick"),
23758
- active: isFullscreen,
23759
- right: enableShortcuts ? react_default.createElement(Shortcut, { keys: shortcutKeys.fullScreen }) : null,
23760
- icon: isFullscreen ? react_default.createElement(CheckIcon, null) : null
23761
- }),
23762
- [api, enableShortcuts, shortcutKeys, isFullscreen]
23763
- );
23764
- const searchToggle = useMemo(
23765
- () => ({
23766
- id: "/",
23767
- title: "Search",
23768
- onClick: /* @__PURE__ */ __name(() => api.focusOnUIElement(focusableUIElements.storySearchField), "onClick"),
23769
- right: enableShortcuts ? react_default.createElement(Shortcut, { keys: shortcutKeys.search }) : null
23770
- }),
23771
- [api, enableShortcuts, shortcutKeys]
23772
- );
23773
- const up = useMemo(
23774
- () => ({
23775
- id: "up",
23776
- title: "Previous component",
23777
- onClick: /* @__PURE__ */ __name(() => api.jumpToComponent(-1), "onClick"),
23778
- right: enableShortcuts ? react_default.createElement(Shortcut, { keys: shortcutKeys.prevComponent }) : null
23779
- }),
23780
- [api, enableShortcuts, shortcutKeys]
23781
- );
23782
- const down = useMemo(
23783
- () => ({
23784
- id: "down",
23785
- title: "Next component",
23786
- onClick: /* @__PURE__ */ __name(() => api.jumpToComponent(1), "onClick"),
23787
- right: enableShortcuts ? react_default.createElement(Shortcut, { keys: shortcutKeys.nextComponent }) : null
23788
- }),
23789
- [api, enableShortcuts, shortcutKeys]
23790
- );
23791
- const prev = useMemo(
23792
- () => ({
23793
- id: "prev",
23794
- title: "Previous story",
23795
- onClick: /* @__PURE__ */ __name(() => api.jumpToStory(-1), "onClick"),
23796
- right: enableShortcuts ? react_default.createElement(Shortcut, { keys: shortcutKeys.prevStory }) : null
23797
- }),
23798
- [api, enableShortcuts, shortcutKeys]
23799
- );
23800
- const next = useMemo(
23801
- () => ({
23802
- id: "next",
23803
- title: "Next story",
23804
- onClick: /* @__PURE__ */ __name(() => api.jumpToStory(1), "onClick"),
23805
- right: enableShortcuts ? react_default.createElement(Shortcut, { keys: shortcutKeys.nextStory }) : null
23806
- }),
23807
- [api, enableShortcuts, shortcutKeys]
23808
- );
23809
- const collapse = useMemo(
23810
- () => ({
23811
- id: "collapse",
23812
- title: "Collapse all",
23813
- onClick: /* @__PURE__ */ __name(() => api.emit(STORIES_COLLAPSE_ALL), "onClick"),
23814
- right: enableShortcuts ? react_default.createElement(Shortcut, { keys: shortcutKeys.collapseAll }) : null
23815
- }),
23816
- [api, enableShortcuts, shortcutKeys]
23817
- );
23818
- const getAddonsShortcuts = useCallback(() => {
23819
- const addonsShortcuts = api.getAddonsShortcuts();
23820
- const keys2 = shortcutKeys;
23821
- return Object.entries(addonsShortcuts).filter(([_2, { showInMenu }]) => showInMenu).map(([actionName, { label, action }]) => ({
23822
- id: actionName,
23823
- title: label,
23824
- onClick: /* @__PURE__ */ __name(() => action(), "onClick"),
23825
- right: enableShortcuts ? react_default.createElement(Shortcut, { keys: keys2[actionName] }) : null
23826
- }));
23827
- }, [api, enableShortcuts, shortcutKeys]);
23828
- return useMemo(
23829
- () => [
23830
- [
23831
- about,
23832
- ...state.whatsNewData?.status === "SUCCESS" ? [whatsNew] : [],
23833
- documentation,
23834
- ...enableShortcuts ? [shortcuts] : []
23835
- ],
23836
- [
23837
- sidebarToggle,
23838
- toolbarToogle,
23839
- addonsToggle,
23840
- addonsOrientationToggle,
23841
- fullscreenToggle,
23842
- searchToggle,
23843
- up,
23844
- down,
23845
- prev,
23846
- next,
23847
- collapse
23848
- ],
23849
- getAddonsShortcuts()
23850
- ],
23851
- [
23852
- about,
23853
- state,
23854
- whatsNew,
23855
- documentation,
23856
- shortcuts,
23857
- sidebarToggle,
23858
- toolbarToogle,
23859
- addonsToggle,
23860
- addonsOrientationToggle,
23861
- fullscreenToggle,
23862
- searchToggle,
23863
- up,
23864
- down,
23865
- prev,
23866
- next,
23867
- collapse,
23868
- getAddonsShortcuts,
23869
- enableShortcuts
23870
- ]
23871
- );
23872
- }, "useMenu");
23873
-
23874
25344
  // src/manager/container/Sidebar.tsx
23875
25345
  var Sidebar3 = react_default.memo(/* @__PURE__ */ __name(function Sideber({ onMenuClick }) {
23876
- const mapper3 = /* @__PURE__ */ __name(({ state, api }) => {
25346
+ const mapper5 = /* @__PURE__ */ __name(({ state, api }) => {
23877
25347
  const {
23878
25348
  ui: { name, url, enableShortcuts },
23879
25349
  viewMode,
@@ -23914,7 +25384,7 @@ var Sidebar3 = react_default.memo(/* @__PURE__ */ __name(function Sideber({ onMe
23914
25384
  enableShortcuts
23915
25385
  };
23916
25386
  }, "mapper");
23917
- return react_default.createElement(Consumer, { filter: mapper3 }, (fromState) => {
25387
+ return react_default.createElement(Consumer, { filter: mapper5 }, (fromState) => {
23918
25388
  const allStatuses = experimental_useStatusStore();
23919
25389
  return react_default.createElement(Sidebar, { ...fromState, allStatuses, onMenuClick });
23920
25390
  });
@@ -24145,7 +25615,11 @@ var shortcutLabels = {
24145
25615
  aboutPage: "Go to about page",
24146
25616
  collapseAll: "Collapse all items on sidebar",
24147
25617
  expandAll: "Expand all items on sidebar",
24148
- remount: "Remount component"
25618
+ remount: "Remount component",
25619
+ openInEditor: "Open story in editor",
25620
+ copyStoryLink: "Copy story link to clipboard"
25621
+ // TODO: bring this back once we want to add shortcuts for this
25622
+ // copyStoryName: 'Copy story name to clipboard',
24149
25623
  };
24150
25624
  var fixedShortcuts = ["escape"];
24151
25625
  function toShortcutState(shortcutKeys) {
@@ -24168,11 +25642,14 @@ var _ShortcutsScreen = class _ShortcutsScreen extends Component {
24168
25642
  if (!shortcut) {
24169
25643
  return false;
24170
25644
  }
25645
+ const normalizedShortcut = shortcut.map(
25646
+ (key) => Array.isArray(key) ? key.at(-1) : key
25647
+ );
24171
25648
  const error = !!Object.entries(shortcutKeys).find(
24172
- ([feature, { shortcut: existingShortcut }]) => feature !== activeFeature && existingShortcut && shortcutMatchesShortcut(shortcut, existingShortcut)
25649
+ ([feature, { shortcut: existingShortcut }]) => feature !== activeFeature && existingShortcut && shortcutMatchesShortcut(normalizedShortcut, existingShortcut)
24173
25650
  );
24174
25651
  return this.setState({
24175
- shortcutKeys: { ...shortcutKeys, [activeFeature]: { shortcut, error } }
25652
+ shortcutKeys: { ...shortcutKeys, [activeFeature]: { shortcut: normalizedShortcut, error } }
24176
25653
  });
24177
25654
  }, "onKeyDown");
24178
25655
  this.onFocus = /* @__PURE__ */ __name((focusedInput) => () => {