storybook 10.0.0-beta.6 → 10.0.0-beta.8

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 (80) hide show
  1. package/dist/_browser-chunks/{chunk-YQV3EGQ5.js → chunk-OQ6NCFPL.js} +38 -15
  2. package/dist/_browser-chunks/{chunk-O5R5CGFA.js → chunk-TMDZCWME.js} +1 -2
  3. package/dist/_node-chunks/{builder-manager-V33CQT2M.js → builder-manager-Y34L3HC4.js} +30 -15
  4. package/dist/_node-chunks/camelcase-W6EWLMZP.js +18 -0
  5. package/dist/_node-chunks/{chunk-A7CUP23N.js → chunk-3VCGPS3V.js} +7 -7
  6. package/dist/_node-chunks/{chunk-EAOPWIKA.js → chunk-4QSDBUYK.js} +8 -8
  7. package/dist/_node-chunks/{chunk-UYKQJMQY.js → chunk-4SIVISOF.js} +21 -27
  8. package/dist/_node-chunks/{chunk-MLBTKECD.js → chunk-5SPDSTWP.js} +7 -7
  9. package/dist/_node-chunks/{chunk-VQH4ZFTS.js → chunk-6NAUDAPE.js} +8 -8
  10. package/dist/_node-chunks/{chunk-NUVGSFQI.js → chunk-6SXRGPL6.js} +7 -7
  11. package/dist/_node-chunks/{chunk-2DMFI367.js → chunk-7JZFWQN4.js} +72 -8
  12. package/dist/_node-chunks/{chunk-IINJT47N.js → chunk-7Q5EKYUL.js} +7 -7
  13. package/dist/_node-chunks/{chunk-B3AMFGAL.js → chunk-AND2M2X5.js} +7 -7
  14. package/dist/_node-chunks/{chunk-RIPA4LFD.js → chunk-AZWKFSEJ.js} +108 -76
  15. package/dist/_node-chunks/{chunk-7NJGTQ3W.js → chunk-CL53RP5L.js} +8 -8
  16. package/dist/_node-chunks/{chunk-BNOZ3EKF.js → chunk-CZLW5B2W.js} +7 -7
  17. package/dist/_node-chunks/{chunk-DC7OWBHB.js → chunk-DRNU7FEF.js} +12 -12
  18. package/dist/_node-chunks/{chunk-VSC6LSCQ.js → chunk-EMCS3ZKS.js} +6 -6
  19. package/dist/_node-chunks/{chunk-EY5PTUZL.js → chunk-F43CI3CD.js} +10 -10
  20. package/dist/_node-chunks/{chunk-XZTBG2TG.js → chunk-FRTUAT3V.js} +6 -6
  21. package/dist/_node-chunks/{chunk-JNHUDBJL.js → chunk-HRBWZFVH.js} +7 -7
  22. package/dist/_node-chunks/{chunk-55VWKF63.js → chunk-IE2VBA4V.js} +9 -9
  23. package/dist/_node-chunks/{chunk-5IEY46LQ.js → chunk-JEIQPNWQ.js} +7 -7
  24. package/dist/_node-chunks/{chunk-NKZ4UPPV.js → chunk-JG7IEUS3.js} +7 -7
  25. package/dist/_node-chunks/{chunk-HEBHWRWL.js → chunk-LKGWQEHR.js} +7 -7
  26. package/dist/_node-chunks/{chunk-6PTV7XGR.js → chunk-MIJKYKSO.js} +264 -109
  27. package/dist/_node-chunks/{chunk-F3PO67U3.js → chunk-O33XSHQE.js} +7 -7
  28. package/dist/_node-chunks/{chunk-HPFXREVG.js → chunk-SOIRRZYG.js} +7 -7
  29. package/dist/_node-chunks/chunk-T46D5USU.js +18 -0
  30. package/dist/_node-chunks/{chunk-NJXBURX7.js → chunk-T5VNV7FG.js} +7 -7
  31. package/dist/_node-chunks/{chunk-E6TLN2J2.js → chunk-TL5UYDH2.js} +7 -7
  32. package/dist/_node-chunks/{chunk-JOXYGIZK.js → chunk-UORO6DG4.js} +9 -9
  33. package/dist/_node-chunks/chunk-USP6T4QU.js +62 -0
  34. package/dist/_node-chunks/{chunk-7WH7AGOR.js → chunk-WS3L7DA7.js} +7 -7
  35. package/dist/_node-chunks/{chunk-4TOI4VSK.js → chunk-YMZK6547.js} +7 -7
  36. package/dist/_node-chunks/{dist-CGGAYWME.js → dist-RINWIIFC.js} +9 -9
  37. package/dist/_node-chunks/{globby-3IFB7BJC.js → globby-G3CLKE4Y.js} +9 -9
  38. package/dist/_node-chunks/{lib-IT6OBSID.js → lib-67I574Z7.js} +7 -7
  39. package/dist/_node-chunks/{mdx-N42X6CFJ-WM36SSZ6.js → mdx-N42X6CFJ-6DP2YFMY.js} +8 -8
  40. package/dist/_node-chunks/{p-limit-3V5XIKA7.js → p-limit-JBOY5PGK.js} +7 -7
  41. package/dist/_node-chunks/{plugin-3YREMMJJ.js → plugin-2IR6AOYP.js} +10 -10
  42. package/dist/_node-chunks/{plugin-GJUBUKCT.js → plugin-5XCSTKS6.js} +10 -10
  43. package/dist/_node-chunks/{webpack-inject-mocker-runtime-plugin-DCJQFJQ5.js → webpack-inject-mocker-runtime-plugin-5FUND5HJ.js} +10 -10
  44. package/dist/_node-chunks/{webpack-mock-plugin-XJNFAHBI.js → webpack-mock-plugin-JVWSZ2PI.js} +9 -9
  45. package/dist/babel/index.js +11 -11
  46. package/dist/bin/core.js +11 -11
  47. package/dist/bin/dispatcher.js +11 -11
  48. package/dist/bin/loader.js +8 -8
  49. package/dist/cli/index.js +20 -20
  50. package/dist/common/index.js +20 -21
  51. package/dist/components/index.js +7 -3
  52. package/dist/core-server/index.js +90 -63
  53. package/dist/core-server/presets/common-manager.js +575 -531
  54. package/dist/core-server/presets/common-override-preset.js +9 -9
  55. package/dist/core-server/presets/common-preset.js +22 -22
  56. package/dist/core-server/presets/webpack/loaders/storybook-mock-transform-loader.js +9 -9
  57. package/dist/core-server/presets/webpack/loaders/webpack-automock-loader.js +10 -10
  58. package/dist/csf/index.d.ts +9 -4
  59. package/dist/csf/index.js +37 -8
  60. package/dist/csf-tools/index.d.ts +13 -6
  61. package/dist/csf-tools/index.js +9 -9
  62. package/dist/manager/globals-runtime.js +73 -34
  63. package/dist/manager/runtime.js +501 -257
  64. package/dist/manager-api/index.d.ts +11 -6
  65. package/dist/manager-api/index.js +69 -34
  66. package/dist/node-logger/index.js +14 -14
  67. package/dist/preview/globals.js +1 -1
  68. package/dist/preview/runtime.js +97 -63
  69. package/dist/preview-api/index.d.ts +70 -71
  70. package/dist/preview-api/index.js +1 -1
  71. package/dist/server-errors.js +10 -10
  72. package/dist/telemetry/index.js +23 -24
  73. package/dist/types/index.d.ts +24 -7
  74. package/dist/viewport/index.d.ts +36 -4
  75. package/dist/viewport/index.js +1 -1
  76. package/package.json +1 -33
  77. package/dist/_node-chunks/camelcase-BZ55OCHI.js +0 -18
  78. package/dist/_node-chunks/chunk-FDDJHDCE.js +0 -62
  79. package/dist/_node-chunks/chunk-R5DIBOM6.js +0 -18
  80. package/dist/_node-chunks/chunk-TJIMCNYJ.js +0 -80
@@ -6696,6 +6696,7 @@ var useLayoutSyncingState = /* @__PURE__ */ __name(({
6696
6696
  });
6697
6697
  const { navSize, rightPanelWidth, bottomPanelHeight } = internalDraggingSizeState.isDragging ? internalDraggingSizeState : managerLayoutState;
6698
6698
  const customisedNavSize = api.getNavSizeWithCustomisations?.(navSize) ?? navSize;
6699
+ const customisedShowPanel = api.getShowPanelWithCustomisations?.(isPanelShown) ?? isPanelShown;
6699
6700
  return {
6700
6701
  navSize: customisedNavSize,
6701
6702
  rightPanelWidth,
@@ -6704,7 +6705,7 @@ var useLayoutSyncingState = /* @__PURE__ */ __name(({
6704
6705
  panelResizerRef,
6705
6706
  sidebarResizerRef,
6706
6707
  showPages: isPagesShown,
6707
- showPanel: isPanelShown,
6708
+ showPanel: customisedShowPanel,
6708
6709
  isDragging: internalDraggingSizeState.isDragging
6709
6710
  };
6710
6711
  }, "useLayoutSyncingState");
@@ -6774,7 +6775,7 @@ var LayoutContainer = styled.div(
6774
6775
  gridTemplateColumns: `minmax(0, ${navSize}px) minmax(${MINIMUM_CONTENT_WIDTH_PX}px, 1fr) minmax(0, ${rightPanelWidth}px)`,
6775
6776
  gridTemplateRows: `1fr minmax(0, ${bottomPanelHeight}px)`,
6776
6777
  gridTemplateAreas: (() => {
6777
- if (viewMode === "docs" || !showPanel) {
6778
+ if (!showPanel) {
6778
6779
  return `"sidebar content content"
6779
6780
  "sidebar content content"`;
6780
6781
  }
@@ -11220,7 +11221,7 @@ var HighlightStyles = /* @__PURE__ */ __name(({ refId, itemId }) => react_defaul
11220
11221
  background: background2,
11221
11222
  "&:hover, &:focus": { background: background2 }
11222
11223
  },
11223
- [`&[data-nodetype="story"], &[data-nodetype="document"]`]: {
11224
+ [`&[data-nodetype="story"], &[data-nodetype="document"], &[data-nodetype="test"]`]: {
11224
11225
  color: color2.defaultText,
11225
11226
  background: background2,
11226
11227
  "&:hover, &:focus": { background: background2 }
@@ -11252,7 +11253,7 @@ var getAncestorIds = (0, import_memoizerific2.default)(1e3)(
11252
11253
  );
11253
11254
  var getDescendantIds = (0, import_memoizerific2.default)(1e3)((data, id, skipLeafs) => {
11254
11255
  const entry = data[id];
11255
- if (!entry || entry.type === "story" || entry.type === "docs" || !entry.children) {
11256
+ if (!entry || !("children" in entry) || !entry.children) {
11256
11257
  return [];
11257
11258
  }
11258
11259
  return entry.children.reduce((acc, childId) => {
@@ -11358,6 +11359,23 @@ var Loader2 = /* @__PURE__ */ __name(({ size: size2 }) => {
11358
11359
  return react_default.createElement(Fragment, null, sequence.map((depth, index) => react_default.createElement(Loadingitem, { depth, key: index })));
11359
11360
  }, "Loader");
11360
11361
 
11362
+ // src/manager/components/sidebar/NoResults.tsx
11363
+ var NoResults2 = styled.div(({ theme }) => ({
11364
+ display: "flex",
11365
+ flexDirection: "column",
11366
+ textAlign: "center",
11367
+ textWrap: "balance",
11368
+ gap: 4,
11369
+ padding: "20px 0",
11370
+ lineHeight: `18px`,
11371
+ fontSize: `${theme.typography.size.s2}px`,
11372
+ color: theme.color.defaultText,
11373
+ small: {
11374
+ color: theme.textMutedColor,
11375
+ fontSize: `${theme.typography.size.s1}px`
11376
+ }
11377
+ }));
11378
+
11361
11379
  // src/manager/components/sidebar/RefBlocks.tsx
11362
11380
  var { window: globalWindow2 } = scope;
11363
11381
  var TextStyle = styled.div(({ theme }) => ({
@@ -11423,7 +11441,23 @@ var FlexSpaced = styled(Spaced)({
11423
11441
  var WideSpaced = styled(Spaced)({
11424
11442
  flex: 1
11425
11443
  });
11426
- var EmptyBlock = /* @__PURE__ */ __name(({ isMain }) => react_default.createElement(Contained, null, react_default.createElement(FlexSpaced, { col: 1 }, react_default.createElement(WideSpaced, null, react_default.createElement(Text2, null, isMain ? react_default.createElement(react_default.Fragment, null, "Oh no! Your Storybook is empty. Possible reasons why:", react_default.createElement("ul", null, react_default.createElement("li", null, "The glob specified in ", react_default.createElement("code", null, "main.js"), " isn't correct."), react_default.createElement("li", null, "No stories are defined in your story files."), react_default.createElement("li", null, "You're using filter-functions, and all stories are filtered away.")), " ") : react_default.createElement(react_default.Fragment, null, "This composed storybook is empty, maybe you're using filter-functions, and all stories are filtered away."))))), "EmptyBlock");
11444
+ var EmptyBlock = /* @__PURE__ */ __name(({ isMain, hasEntries }) => react_default.createElement(Contained, null, react_default.createElement(FlexSpaced, { col: 1 }, react_default.createElement(WideSpaced, null, hasEntries ? react_default.createElement(NoResults2, null, react_default.createElement("strong", null, "No stories found"), react_default.createElement("small", null, "Your selected filters did not match any stories.")) : isMain ? react_default.createElement(Text2, null, "Oh no! Your Storybook is empty. This can happen when:", react_default.createElement("ul", null, react_default.createElement("li", null, "Your", " ", react_default.createElement(
11445
+ Link,
11446
+ {
11447
+ href: "https://storybook.js.org/docs/api/main-config/main-config-stories?ref=ui",
11448
+ cancel: false,
11449
+ target: "_blank"
11450
+ },
11451
+ "stories glob configuration"
11452
+ ), " ", "does not match any files.", " "), react_default.createElement("li", null, "You have", " ", react_default.createElement(
11453
+ Link,
11454
+ {
11455
+ href: "https://storybook.js.org/docs/writing-stories?ref=ui",
11456
+ cancel: false,
11457
+ target: "_blank"
11458
+ },
11459
+ "no stories defined"
11460
+ ), " ", "in your story files.", " "))) : react_default.createElement(Text2, null, "This composed Storybook is empty. Perhaps no stories match your selected filters.")))), "EmptyBlock");
11427
11461
  var LoaderBlock = /* @__PURE__ */ __name(({ isMain }) => react_default.createElement(Contained, null, react_default.createElement(Loader2, { size: isMain ? 17 : 5 })), "LoaderBlock");
11428
11462
 
11429
11463
  // src/manager/components/sidebar/RefIndicator.tsx
@@ -11649,6 +11683,7 @@ var GROUP_ID = "icon--group";
11649
11683
  var COMPONENT_ID = "icon--component";
11650
11684
  var DOCUMENT_ID = "icon--document";
11651
11685
  var STORY_ID = "icon--story";
11686
+ var TEST_ID = "icon--test";
11652
11687
  var SUCCESS_ID = "icon--success";
11653
11688
  var ERROR_ID = "icon--error";
11654
11689
  var WARNING_ID = "icon--warning";
@@ -11692,6 +11727,14 @@ var IconSymbols = /* @__PURE__ */ __name(() => {
11692
11727
  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",
11693
11728
  fill: "currentColor"
11694
11729
  }
11730
+ )), react_default.createElement("symbol", { id: TEST_ID }, react_default.createElement(
11731
+ "path",
11732
+ {
11733
+ fillRule: "evenodd",
11734
+ clipRule: "evenodd",
11735
+ 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",
11736
+ fill: "currentColor"
11737
+ }
11695
11738
  )), react_default.createElement("symbol", { id: SUCCESS_ID }, react_default.createElement(
11696
11739
  "path",
11697
11740
  {
@@ -11731,6 +11774,9 @@ var UseSymbol = /* @__PURE__ */ __name(({ type }) => {
11731
11774
  if (type === "story") {
11732
11775
  return react_default.createElement("use", { xlinkHref: `#${STORY_ID}` });
11733
11776
  }
11777
+ if (type === "test") {
11778
+ return react_default.createElement("use", { xlinkHref: `#${TEST_ID}` });
11779
+ }
11734
11780
  if (type === "success") {
11735
11781
  return react_default.createElement("use", { xlinkHref: `#${SUCCESS_ID}` });
11736
11782
  }
@@ -11790,7 +11836,7 @@ var getMostCriticalStatusValue = /* @__PURE__ */ __name((statusValues) => {
11790
11836
  }, "getMostCriticalStatusValue");
11791
11837
  function getGroupStatus(collapsedData, allStatuses) {
11792
11838
  return Object.values(collapsedData).reduce((acc, item) => {
11793
- if (item.type === "group" || item.type === "component") {
11839
+ if (item.type === "group" || item.type === "component" || item.type === "story") {
11794
11840
  const leafs = getDescendantIds(collapsedData, item.id, false).map((id) => collapsedData[id]).filter((i2) => i2.type === "story");
11795
11841
  const combinedStatus = getMostCriticalStatusValue(
11796
11842
  // @ts-expect-error (non strict)
@@ -12033,23 +12079,22 @@ var useStatusSummary = /* @__PURE__ */ __name((item) => {
12033
12079
  }, "useStatusSummary");
12034
12080
 
12035
12081
  // src/manager/components/sidebar/components/CollapseIcon.tsx
12036
- var CollapseIconWrapper = styled.div(({ theme, isExpanded }) => ({
12082
+ var CollapseIconWrapper = styled.div(({ isExpanded }) => ({
12037
12083
  width: 8,
12038
12084
  height: 8,
12039
12085
  display: "flex",
12040
12086
  justifyContent: "center",
12041
12087
  alignItems: "center",
12042
- color: curriedTransparentize$1(0.4, theme.textMutedColor),
12043
12088
  transform: isExpanded ? "rotateZ(90deg)" : "none",
12044
12089
  transition: "transform .1s ease-out"
12045
12090
  }));
12046
- 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(
12091
+ 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(
12047
12092
  "path",
12048
12093
  {
12049
- fill: "#73828C",
12094
+ fill: "currentColor",
12050
12095
  fillRule: "evenodd",
12051
- 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",
12052
- clipRule: "evenodd"
12096
+ clipRule: "evenodd",
12097
+ 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"
12053
12098
  }
12054
12099
  ))), "CollapseIcon");
12055
12100
 
@@ -12072,44 +12117,42 @@ var TypeIcon2 = styled.svg(
12072
12117
  if (type === "story") {
12073
12118
  return theme.color.seafoam;
12074
12119
  }
12120
+ if (type === "test") {
12121
+ return theme.color.green;
12122
+ }
12075
12123
  return "currentColor";
12076
12124
  })()
12077
12125
  })
12078
12126
  );
12079
- var BranchNode = styled.button(({ theme, depth = 0, isExpandable = false }) => ({
12127
+ var commonNodeStyles = /* @__PURE__ */ __name(({
12128
+ theme,
12129
+ depth = 0,
12130
+ isExpandable = false
12131
+ }) => ({
12132
+ flex: 1,
12080
12133
  width: "100%",
12081
- border: "none",
12082
12134
  cursor: "pointer",
12083
12135
  display: "flex",
12084
12136
  alignItems: "start",
12085
12137
  textAlign: "left",
12086
- paddingLeft: `${(isExpandable ? 8 : 22) + depth * 18}px`,
12138
+ textDecoration: "none",
12139
+ border: "none",
12087
12140
  color: "inherit",
12088
12141
  fontSize: `${theme.typography.size.s2}px`,
12142
+ fontWeight: "inherit",
12089
12143
  background: "transparent",
12090
12144
  minHeight: 28,
12091
12145
  borderRadius: 4,
12092
12146
  gap: 6,
12093
- paddingTop: 5,
12094
- paddingBottom: 4
12095
- }));
12096
- var LeafNode = styled.a(({ theme, depth = 0 }) => ({
12097
- width: "100%",
12098
- cursor: "pointer",
12099
- color: "inherit",
12100
- display: "flex",
12101
- gap: 6,
12102
- flex: 1,
12103
- alignItems: "start",
12104
- paddingLeft: `${22 + depth * 18}px`,
12147
+ paddingLeft: `${(isExpandable ? 8 : 22) + depth * 18}px`,
12105
12148
  paddingTop: 5,
12106
12149
  paddingBottom: 4,
12107
- fontSize: `${theme.typography.size.s2}px`,
12108
- textDecoration: "none",
12109
12150
  overflowWrap: "break-word",
12110
12151
  wordWrap: "break-word",
12111
12152
  wordBreak: "break-word"
12112
- }));
12153
+ }), "commonNodeStyles");
12154
+ var BranchNode = styled.button(commonNodeStyles);
12155
+ var LeafNode = styled.a(commonNodeStyles);
12113
12156
  var RootNode = styled.div(({ theme }) => ({
12114
12157
  display: "flex",
12115
12158
  alignItems: "center",
@@ -12139,22 +12182,37 @@ var GroupNode = react_default.memo(/* @__PURE__ */ __name(function GroupNode2({
12139
12182
  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);
12140
12183
  }, "GroupNode"));
12141
12184
  var ComponentNode = react_default.memo(
12142
- /* @__PURE__ */ __name(function ComponentNode2({ theme, children: children2, isExpanded, isExpandable, isSelected, ...props }) {
12185
+ /* @__PURE__ */ __name(function ComponentNode2({
12186
+ theme,
12187
+ children: children2,
12188
+ isExpanded = false,
12189
+ isExpandable = false,
12190
+ isSelected,
12191
+ ...props
12192
+ }) {
12143
12193
  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);
12144
12194
  }, "ComponentNode")
12145
12195
  );
12146
- var DocumentNode = react_default.memo(
12147
- /* @__PURE__ */ __name(function DocumentNode2({ theme, children: children2, docsMode, ...props }) {
12148
- 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);
12149
- }, "DocumentNode")
12150
- );
12196
+ var DocumentNode = react_default.memo(/* @__PURE__ */ __name(function DocumentNode2({ theme, children: children2, docsMode, ...props }) {
12197
+ 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);
12198
+ }, "DocumentNode"));
12151
12199
  var StoryNode = react_default.memo(/* @__PURE__ */ __name(function StoryNode2({
12152
12200
  theme,
12153
12201
  children: children2,
12202
+ isExpandable = false,
12203
+ isExpanded = false,
12204
+ isSelected,
12154
12205
  ...props
12155
12206
  }) {
12156
- 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);
12207
+ 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);
12157
12208
  }, "StoryNode"));
12209
+ var TestNode = react_default.memo(/* @__PURE__ */ __name(function TestNode2({
12210
+ theme,
12211
+ children: children2,
12212
+ ...props
12213
+ }) {
12214
+ 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);
12215
+ }, "TestNode"));
12158
12216
 
12159
12217
  // ../node_modules/es-toolkit/dist/function/after.mjs
12160
12218
  function after(n3, func) {
@@ -12520,7 +12578,7 @@ var useExpanded = /* @__PURE__ */ __name(({
12520
12578
  target.blur();
12521
12579
  }
12522
12580
  const type = highlightedElement.getAttribute("data-nodetype");
12523
- if ((isEnter || isSpace) && ["component", "story", "document"].includes(type)) {
12581
+ if (type && (isEnter || isSpace) && ["component", "story", "document", "test"].includes(type)) {
12524
12582
  onSelectStoryId(highlightedItemId);
12525
12583
  }
12526
12584
  const isExpanded = highlightedElement.getAttribute("aria-expanded");
@@ -12565,7 +12623,7 @@ var Container6 = styled.div((props) => ({
12565
12623
  marginTop: props.hasOrphans ? 20 : 0,
12566
12624
  marginBottom: 20
12567
12625
  }));
12568
- var CollapseButton = styled.button(({ theme }) => ({
12626
+ var CollapseButton = styled.button({
12569
12627
  all: "unset",
12570
12628
  display: "flex",
12571
12629
  padding: "0px 8px",
@@ -12579,7 +12637,7 @@ var CollapseButton = styled.button(({ theme }) => ({
12579
12637
  outline: "none",
12580
12638
  background: "var(--tree-node-background-hover)"
12581
12639
  }
12582
- }));
12640
+ });
12583
12641
  var LeafNodeStyleWrapper = styled.div(({ theme }) => ({
12584
12642
  position: "relative",
12585
12643
  display: "flex",
@@ -12673,22 +12731,23 @@ var statusOrder = [
12673
12731
  "status-value:pending",
12674
12732
  "status-value:unknown"
12675
12733
  ];
12676
- var Node2 = react_default.memo(/* @__PURE__ */ __name(function Node3({
12677
- item,
12678
- statuses,
12679
- groupStatus,
12680
- refId,
12681
- docsMode,
12682
- isOrphan,
12683
- isDisplayed,
12684
- isSelected,
12685
- isFullyExpanded,
12686
- setFullyExpanded,
12687
- isExpanded,
12688
- setExpanded,
12689
- onSelectStoryId,
12690
- api
12691
- }) {
12734
+ var Node2 = react_default.memo(/* @__PURE__ */ __name(function Node3(props) {
12735
+ const {
12736
+ item,
12737
+ statuses,
12738
+ groupStatus,
12739
+ refId,
12740
+ docsMode,
12741
+ isOrphan,
12742
+ isDisplayed,
12743
+ isSelected,
12744
+ isFullyExpanded,
12745
+ setFullyExpanded,
12746
+ isExpanded,
12747
+ setExpanded,
12748
+ onSelectStoryId,
12749
+ api
12750
+ } = props;
12692
12751
  const { isDesktop, isMobile, setMobileMenuOpen } = useLayout();
12693
12752
  const { counts, statusesByValue } = useStatusSummary(item);
12694
12753
  if (!isDisplayed) {
@@ -12745,58 +12804,6 @@ var Node2 = react_default.memo(/* @__PURE__ */ __name(function Node3({
12745
12804
  const id = createId(item.id, refId);
12746
12805
  const contextMenu = refId === "storybook_internal" ? useContextMenu(item, statusLinks, api) : { node: null, onMouseEnter: /* @__PURE__ */ __name(() => {
12747
12806
  }, "onMouseEnter") };
12748
- if (item.type === "story" || item.type === "docs") {
12749
- const LeafNode2 = item.type === "docs" ? DocumentNode : StoryNode;
12750
- const statusValue = getMostCriticalStatusValue(
12751
- Object.values(statuses || {}).map((s2) => s2.value)
12752
- );
12753
- const [icon, textColor] = statusMapping[statusValue];
12754
- return react_default.createElement(
12755
- LeafNodeStyleWrapper,
12756
- {
12757
- key: id,
12758
- className: "sidebar-item",
12759
- "data-selected": isSelected,
12760
- "data-ref-id": refId,
12761
- "data-item-id": item.id,
12762
- "data-parent-id": item.parent,
12763
- "data-nodetype": item.type === "docs" ? "document" : "story",
12764
- "data-highlightable": isDisplayed,
12765
- onMouseEnter: contextMenu.onMouseEnter
12766
- },
12767
- react_default.createElement(
12768
- LeafNode2,
12769
- {
12770
- style: isSelected ? {} : { color: textColor },
12771
- href: getLink(item, refId),
12772
- id,
12773
- depth: isOrphan ? item.depth : item.depth - 1,
12774
- onClick: (event) => {
12775
- event.preventDefault();
12776
- onSelectStoryId(item.id);
12777
- if (isMobile) {
12778
- setMobileMenuOpen(false);
12779
- }
12780
- },
12781
- ...item.type === "docs" && { docsMode }
12782
- },
12783
- item.renderLabel?.(item, api) || item.name
12784
- ),
12785
- isSelected && react_default.createElement(SkipToContentLink, { asChild: true }, react_default.createElement("a", { href: "#storybook-preview-wrapper" }, "Skip to canvas")),
12786
- contextMenu.node,
12787
- icon ? react_default.createElement(
12788
- StatusButton,
12789
- {
12790
- "aria-label": `Test status: ${statusValue.replace("status-value:", "")}`,
12791
- role: "status",
12792
- type: "button",
12793
- status: statusValue,
12794
- selectedItem: isSelected
12795
- },
12796
- icon
12797
- ) : null
12798
- );
12799
- }
12800
12807
  if (item.type === "root") {
12801
12808
  return react_default.createElement(
12802
12809
  RootNode,
@@ -12838,15 +12845,31 @@ var Node2 = react_default.memo(/* @__PURE__ */ __name(function Node3({
12838
12845
  )
12839
12846
  );
12840
12847
  }
12841
- if (item.type === "component" || item.type === "group") {
12842
- const itemStatus = groupStatus?.[item.id];
12843
- const color2 = itemStatus ? statusMapping[itemStatus][1] : null;
12844
- const BranchNode2 = item.type === "component" ? ComponentNode : GroupNode;
12848
+ const itemStatus = getMostCriticalStatusValue(Object.values(statuses || {}).map((s2) => s2.value));
12849
+ const [itemIcon, itemColor] = statusMapping[itemStatus];
12850
+ const itemStatusButton = itemIcon ? react_default.createElement(
12851
+ StatusButton,
12852
+ {
12853
+ "aria-label": `Test status: ${itemStatus.replace("status-value:", "")}`,
12854
+ role: "status",
12855
+ type: "button",
12856
+ status: itemStatus,
12857
+ selectedItem: isSelected
12858
+ },
12859
+ itemIcon
12860
+ ) : null;
12861
+ if (item.type === "component" || item.type === "group" || item.type === "story" && "children" in item && item.children) {
12862
+ const { children: children2 = [] } = item;
12863
+ const BranchNode2 = { component: ComponentNode, group: GroupNode, story: StoryNode }[item.type];
12864
+ const status = getMostCriticalStatusValue([itemStatus, groupStatus?.[item.id]]);
12865
+ const color2 = status ? statusMapping[status][1] : null;
12866
+ const showBranchStatus = status === "status-value:error" || status === "status-value:warning";
12845
12867
  return react_default.createElement(
12846
12868
  LeafNodeStyleWrapper,
12847
12869
  {
12848
12870
  key: id,
12849
12871
  className: "sidebar-item",
12872
+ "data-selected": isSelected,
12850
12873
  "data-ref-id": refId,
12851
12874
  "data-item-id": item.id,
12852
12875
  "data-parent-id": item.parent,
@@ -12858,24 +12881,32 @@ var Node2 = react_default.memo(/* @__PURE__ */ __name(function Node3({
12858
12881
  BranchNode2,
12859
12882
  {
12860
12883
  id,
12861
- style: color2 ? { color: color2 } : {},
12862
- "aria-controls": item.children && item.children.join(" "),
12884
+ style: color2 && !isSelected ? { color: color2 } : {},
12885
+ "aria-controls": children2.join(" "),
12863
12886
  "aria-expanded": isExpanded,
12864
12887
  depth: isOrphan ? item.depth : item.depth - 1,
12865
- isComponent: item.type === "component",
12866
- isExpandable: item.children && item.children.length > 0,
12888
+ isExpandable: children2.length > 0,
12867
12889
  isExpanded,
12868
12890
  onClick: (event) => {
12869
12891
  event.preventDefault();
12870
- setExpanded({ ids: [item.id], value: !isExpanded });
12871
- if (item.type === "component" && !isExpanded && isDesktop) {
12892
+ if (item.type === "story") {
12872
12893
  onSelectStoryId(item.id);
12894
+ if (!isExpanded || isSelected) {
12895
+ setExpanded({ ids: [item.id], value: !isExpanded });
12896
+ }
12897
+ } else if (item.type === "component") {
12898
+ if (!isExpanded && isDesktop) {
12899
+ onSelectStoryId(item.id);
12900
+ }
12901
+ setExpanded({ ids: [item.id], value: !isExpanded });
12902
+ } else {
12903
+ setExpanded({ ids: [item.id], value: !isExpanded });
12873
12904
  }
12874
12905
  },
12875
12906
  onMouseEnter: () => {
12876
- if (item.type === "component") {
12907
+ if (item.type === "component" || item.type === "story") {
12877
12908
  api.emit(PRELOAD_ENTRIES, {
12878
- ids: [item.children[0]],
12909
+ ids: [children2[0]],
12879
12910
  options: { target: refId }
12880
12911
  });
12881
12912
  }
@@ -12883,11 +12914,49 @@ var Node2 = react_default.memo(/* @__PURE__ */ __name(function Node3({
12883
12914
  },
12884
12915
  item.renderLabel?.(item, api) || item.name
12885
12916
  ),
12917
+ isSelected && react_default.createElement(SkipToContentLink, { asChild: true }, react_default.createElement("a", { href: "#storybook-preview-wrapper" }, "Skip to canvas")),
12886
12918
  contextMenu.node,
12887
- ["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" })))
12919
+ 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
12888
12920
  );
12889
12921
  }
12890
- return null;
12922
+ const isTest = item.type === "story" && item.subtype === "test";
12923
+ const LeafNode2 = isTest ? TestNode : { docs: DocumentNode, story: StoryNode }[item.type];
12924
+ const nodeType = isTest ? "test" : { docs: "document", story: "story" }[item.type];
12925
+ return react_default.createElement(
12926
+ LeafNodeStyleWrapper,
12927
+ {
12928
+ key: id,
12929
+ className: "sidebar-item",
12930
+ "data-selected": isSelected,
12931
+ "data-ref-id": refId,
12932
+ "data-item-id": item.id,
12933
+ "data-parent-id": item.parent,
12934
+ "data-nodetype": nodeType,
12935
+ "data-highlightable": isDisplayed,
12936
+ onMouseEnter: contextMenu.onMouseEnter
12937
+ },
12938
+ react_default.createElement(
12939
+ LeafNode2,
12940
+ {
12941
+ style: itemColor && !isSelected ? { color: itemColor } : {},
12942
+ href: getLink(item, refId),
12943
+ id,
12944
+ depth: isOrphan ? item.depth : item.depth - 1,
12945
+ onClick: (event) => {
12946
+ event.preventDefault();
12947
+ onSelectStoryId(item.id);
12948
+ if (isMobile) {
12949
+ setMobileMenuOpen(false);
12950
+ }
12951
+ },
12952
+ ...item.type === "docs" && { docsMode }
12953
+ },
12954
+ item.renderLabel?.(item, api) || item.name
12955
+ ),
12956
+ isSelected && react_default.createElement(SkipToContentLink, { asChild: true }, react_default.createElement("a", { href: "#storybook-preview-wrapper" }, "Skip to canvas")),
12957
+ contextMenu.node,
12958
+ itemStatusButton
12959
+ );
12891
12960
  }, "Node"));
12892
12961
  var Root = react_default.memo(/* @__PURE__ */ __name(function Root2({
12893
12962
  setExpanded,
@@ -12966,7 +13035,7 @@ var Tree = react_default.memo(/* @__PURE__ */ __name(function Tree2({
12966
13035
  if (onlyChild.type === "docs") {
12967
13036
  return true;
12968
13037
  }
12969
- if (onlyChild.type === "story") {
13038
+ if (onlyChild.type === "story" && onlyChild.subtype === "story") {
12970
13039
  return isStoryHoistable(onlyChild.name, name);
12971
13040
  }
12972
13041
  return false;
@@ -12974,7 +13043,7 @@ var Tree = react_default.memo(/* @__PURE__ */ __name(function Tree2({
12974
13043
  }, [data]);
12975
13044
  const collapsedItems = useMemo(
12976
13045
  () => Object.keys(data).filter((id) => !singleStoryComponentIds.includes(id)),
12977
- [singleStoryComponentIds]
13046
+ [data, singleStoryComponentIds]
12978
13047
  );
12979
13048
  const collapsedData = useMemo(() => {
12980
13049
  return singleStoryComponentIds.reduce(
@@ -12996,7 +13065,7 @@ var Tree = react_default.memo(/* @__PURE__ */ __name(function Tree2({
12996
13065
  },
12997
13066
  { ...data }
12998
13067
  );
12999
- }, [data]);
13068
+ }, [data, singleStoryComponentIds]);
13000
13069
  const ancestry = useMemo(() => {
13001
13070
  return collapsedItems.reduce(
13002
13071
  (acc, id) => Object.assign(acc, { [id]: getAncestorIds(collapsedData, id) }),
@@ -13145,6 +13214,7 @@ var Ref = react_default.memo(/* @__PURE__ */ __name(function Ref2(props) {
13145
13214
  title = refId,
13146
13215
  isLoading: isLoadingMain,
13147
13216
  isBrowsing,
13217
+ hasEntries,
13148
13218
  selectedStoryId,
13149
13219
  highlightedRef,
13150
13220
  setHighlighted,
@@ -13173,11 +13243,10 @@ var Ref = react_default.memo(/* @__PURE__ */ __name(function Ref2(props) {
13173
13243
  const handleClick = useCallback(() => setExpanded((value) => !value), [setExpanded]);
13174
13244
  const setHighlightedItemId = useCallback(
13175
13245
  (itemId) => setHighlighted({ itemId, refId }),
13176
- [setHighlighted]
13246
+ [setHighlighted, refId]
13177
13247
  );
13178
13248
  const onSelectStoryId = useCallback(
13179
- // @ts-expect-error (non strict)
13180
- (storyId) => api && api.selectStory(storyId, void 0, { ref: !isMain && refId }),
13249
+ (storyId) => api?.selectStory(storyId, void 0, { ref: isMain ? void 0 : refId }),
13181
13250
  [api, isMain, refId]
13182
13251
  );
13183
13252
  return react_default.createElement(react_default.Fragment, null, isMain || react_default.createElement(
@@ -13188,7 +13257,7 @@ var Ref = react_default.memo(/* @__PURE__ */ __name(function Ref2(props) {
13188
13257
  },
13189
13258
  react_default.createElement(CollapseButton2, { "data-action": "collapse-ref", onClick: handleClick }, react_default.createElement(CollapseIcon2, { isExpanded }), react_default.createElement(RefTitle, { title }, title)),
13190
13259
  react_default.createElement(RefIndicator, { ...props, state, ref: indicatorRef })
13191
- ), isExpanded && react_default.createElement(Wrapper2, { "data-title": title, isMain }, state === "auth" && react_default.createElement(AuthBlock, { id: refId, loginUrl }), state === "error" && react_default.createElement(ErrorBlock, { error: indexError }), state === "loading" && react_default.createElement(LoaderBlock, { isMain }), state === "empty" && react_default.createElement(EmptyBlock, { isMain }), state === "ready" && react_default.createElement(
13260
+ ), isExpanded && react_default.createElement(Wrapper2, { "data-title": title, isMain }, state === "auth" && react_default.createElement(AuthBlock, { id: refId, loginUrl }), state === "error" && react_default.createElement(ErrorBlock, { error: indexError }), state === "loading" && react_default.createElement(LoaderBlock, { isMain }), state === "empty" && react_default.createElement(EmptyBlock, { isMain, hasEntries }), state === "ready" && react_default.createElement(
13192
13261
  Tree,
13193
13262
  {
13194
13263
  allStatuses,
@@ -13293,9 +13362,8 @@ var useHighlighted = /* @__PURE__ */ __name(({
13293
13362
  if (highlightable[nextIndex].getAttribute("data-nodetype") === "component") {
13294
13363
  const { itemId, refId } = highlightedRef.current;
13295
13364
  const item = api.resolveStory(itemId, refId === "storybook_internal" ? void 0 : refId);
13296
- if (item.type === "component") {
13365
+ if (item?.type === "component") {
13297
13366
  api.emit(PRELOAD_ENTRIES, {
13298
- // @ts-expect-error (non strict)
13299
13367
  ids: [item.children[0]],
13300
13368
  options: { target: refId }
13301
13369
  });
@@ -13305,12 +13373,13 @@ var useHighlighted = /* @__PURE__ */ __name(({
13305
13373
  }, "navigateTree");
13306
13374
  document6.addEventListener("keydown", navigateTree);
13307
13375
  return () => document6.removeEventListener("keydown", navigateTree);
13308
- }, [isLoading, isBrowsing, highlightedRef, highlightElement]);
13376
+ }, [api, containerRef, isLoading, isBrowsing, highlightedRef, highlightElement]);
13309
13377
  return [highlighted, updateHighlighted, highlightedRef];
13310
13378
  }, "useHighlighted");
13311
13379
 
13312
13380
  // src/manager/components/sidebar/Explorer.tsx
13313
13381
  var Explorer = react_default.memo(/* @__PURE__ */ __name(function Explorer2({
13382
+ hasEntries,
13314
13383
  isLoading,
13315
13384
  isBrowsing,
13316
13385
  dataset,
@@ -13339,6 +13408,7 @@ var Explorer = react_default.memo(/* @__PURE__ */ __name(function Explorer2({
13339
13408
  key: refId,
13340
13409
  isLoading,
13341
13410
  isBrowsing,
13411
+ hasEntries,
13342
13412
  selectedStoryId: selected?.refId === ref.id ? selected.storyId : null,
13343
13413
  highlightedRef,
13344
13414
  setHighlighted
@@ -17037,17 +17107,6 @@ var ResultRowContent = styled.div({
17037
17107
  display: "flex",
17038
17108
  flexDirection: "column"
17039
17109
  });
17040
- var NoResults2 = styled.div(({ theme }) => ({
17041
- marginTop: 20,
17042
- textAlign: "center",
17043
- fontSize: `${theme.typography.size.s2}px`,
17044
- lineHeight: `18px`,
17045
- color: theme.color.defaultText,
17046
- small: {
17047
- color: theme.textMutedColor,
17048
- fontSize: `${theme.typography.size.s1}px`
17049
- }
17050
- }));
17051
17110
  var Mark = styled.mark(({ theme }) => ({
17052
17111
  background: "transparent",
17053
17112
  color: theme.color.secondary
@@ -17144,7 +17203,7 @@ var Result = react_default.memo(/* @__PURE__ */ __name(function Result2({ item,
17144
17203
  const nameMatch = matches2.find((match) => match.key === "name");
17145
17204
  const pathMatches = matches2.filter((match) => match.key === "path");
17146
17205
  const [icon] = item.status ? statusMapping[item.status] : [];
17147
- 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);
17206
+ 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);
17148
17207
  }, "Result"));
17149
17208
  var SearchResults = react_default.memo(/* @__PURE__ */ __name(function SearchResults2({
17150
17209
  query,
@@ -17202,7 +17261,7 @@ var SearchResults = react_default.memo(/* @__PURE__ */ __name(function SearchRes
17202
17261
  onClick: handleClearLastViewed
17203
17262
  },
17204
17263
  react_default.createElement(TrashIcon, null)
17205
- )), results.length === 0 && query && react_default.createElement("li", null, react_default.createElement(NoResults2, null, react_default.createElement("strong", null, "No components found"), react_default.createElement("br", null), react_default.createElement("small", null, "Find components by name or path."))), results.map((result2, index) => {
17264
+ )), results.length === 0 && query && react_default.createElement("li", null, react_default.createElement(NoResults2, null, react_default.createElement("strong", null, "No components found"), react_default.createElement("small", null, "Find components by name or path."))), results.map((result2, index) => {
17206
17265
  if (isExpandType(result2)) {
17207
17266
  const props = { ...results, ...getItemProps({ key: index, index, item: result2 }) };
17208
17267
  const { key: key2, ...rest3 } = props;
@@ -17791,19 +17850,14 @@ var SidebarBottom = /* @__PURE__ */ __name(({ isDevelopment }) => {
17791
17850
  }, "SidebarBottom");
17792
17851
 
17793
17852
  // src/manager/components/sidebar/TagsFilterPanel.tsx
17794
- var BUILT_IN_TAGS = /* @__PURE__ */ new Set([
17795
- "dev",
17796
- "test",
17797
- "autodocs",
17798
- "attached-mdx",
17799
- "unattached-mdx",
17800
- "play-fn",
17801
- "test-fn",
17802
- "vitest",
17803
- "svelte-csf",
17804
- "svelte-csf-v4",
17805
- "svelte-csf-v5"
17806
- ]);
17853
+ var groupByType = /* @__PURE__ */ __name((filters) => filters.reduce(
17854
+ (acc, filter2) => {
17855
+ acc[filter2.type] = acc[filter2.type] || [];
17856
+ acc[filter2.type].push(filter2);
17857
+ return acc;
17858
+ },
17859
+ {}
17860
+ ), "groupByType");
17807
17861
  var Wrapper3 = styled.div({
17808
17862
  minWidth: 240,
17809
17863
  maxWidth: 300
@@ -17815,79 +17869,183 @@ var Actions3 = styled.div(({ theme }) => ({
17815
17869
  padding: 4,
17816
17870
  borderBottom: `1px solid ${theme.appBorderColor}`
17817
17871
  }));
17872
+ var TagRow = styled.div({
17873
+ display: "flex",
17874
+ "& button": {
17875
+ width: 64,
17876
+ maxWidth: 64,
17877
+ marginLeft: 4,
17878
+ paddingLeft: 0,
17879
+ paddingRight: 0,
17880
+ fontWeight: "normal",
17881
+ transition: "all 150ms"
17882
+ },
17883
+ "&:not(:hover)": {
17884
+ "& button": {
17885
+ marginLeft: 0,
17886
+ maxWidth: 0,
17887
+ opacity: 0
17888
+ },
17889
+ "& svg + input": {
17890
+ display: "none"
17891
+ }
17892
+ }
17893
+ });
17894
+ var Label = styled.div({
17895
+ overflow: "hidden",
17896
+ textOverflow: "ellipsis",
17897
+ whiteSpace: "nowrap"
17898
+ });
17899
+ var MutedText = styled.span(({ theme }) => ({
17900
+ color: theme.textMutedColor
17901
+ }));
17818
17902
  var TagsFilterPanel = /* @__PURE__ */ __name(({
17819
17903
  api,
17820
- allTags,
17821
- selectedTags,
17822
- toggleTag,
17823
- setAllTags,
17824
- inverted,
17825
- setInverted,
17826
- isDevelopment
17904
+ filtersById,
17905
+ includedFilters,
17906
+ excludedFilters,
17907
+ toggleFilter,
17908
+ setAllFilters,
17909
+ resetFilters,
17910
+ isDevelopment,
17911
+ isDefaultSelection,
17912
+ hasDefaultSelection
17827
17913
  }) => {
17828
- const [builtInEntries, userEntries] = Array.from(allTags.entries()).reduce(
17829
- (acc, [tag, count]) => {
17830
- acc[BUILT_IN_TAGS.has(tag) ? 0 : 1].push([tag, count]);
17831
- return acc;
17832
- },
17833
- [[], []]
17914
+ const ref = useRef(null);
17915
+ const renderLink = /* @__PURE__ */ __name(({
17916
+ id,
17917
+ type,
17918
+ title,
17919
+ icon,
17920
+ count
17921
+ }) => {
17922
+ const onToggle = /* @__PURE__ */ __name((selected, excluded) => toggleFilter(id, selected, excluded), "onToggle");
17923
+ const isIncluded = includedFilters.has(id);
17924
+ const isExcluded = excludedFilters.has(id);
17925
+ const isChecked = isIncluded || isExcluded;
17926
+ const toggleTagLabel = `${isChecked ? "Remove" : "Add"} ${type} filter: ${title}`;
17927
+ const invertButtonLabel = `${isExcluded ? "Include" : "Exclude"} ${type}: ${title}`;
17928
+ if (count === 0 && type === "built-in") {
17929
+ return void 0;
17930
+ }
17931
+ return {
17932
+ id: `filter-${type}-${id}`,
17933
+ content: react_default.createElement(TagRow, null, react_default.createElement(
17934
+ WithTooltip,
17935
+ {
17936
+ delayShow: 1e3,
17937
+ hasChrome: false,
17938
+ style: { minWidth: 0, flex: 1 },
17939
+ tooltip: react_default.createElement(TooltipNote, { note: toggleTagLabel }),
17940
+ trigger: "hover"
17941
+ },
17942
+ react_default.createElement(
17943
+ ListItem,
17944
+ {
17945
+ as: "label",
17946
+ icon: react_default.createElement(react_default.Fragment, null, isExcluded ? react_default.createElement(DeleteIcon, null) : isIncluded ? null : icon, react_default.createElement(
17947
+ Form.Checkbox,
17948
+ {
17949
+ checked: isChecked,
17950
+ onChange: () => onToggle(!isChecked),
17951
+ "data-tag": title
17952
+ }
17953
+ )),
17954
+ "aria-label": toggleTagLabel,
17955
+ title: react_default.createElement(Label, null, title, isExcluded && react_default.createElement(MutedText, null, " (excluded)")),
17956
+ right: isExcluded ? react_default.createElement("s", null, count) : react_default.createElement("span", null, count)
17957
+ }
17958
+ )
17959
+ ), react_default.createElement(
17960
+ WithTooltip,
17961
+ {
17962
+ delayShow: 1e3,
17963
+ hasChrome: false,
17964
+ tooltip: react_default.createElement(TooltipNote, { note: invertButtonLabel }),
17965
+ trigger: "hover"
17966
+ },
17967
+ react_default.createElement(
17968
+ Button,
17969
+ {
17970
+ variant: "ghost",
17971
+ size: "medium",
17972
+ onClick: () => onToggle(true, !isExcluded),
17973
+ "aria-label": invertButtonLabel
17974
+ },
17975
+ isExcluded ? "Include" : "Exclude"
17976
+ )
17977
+ ))
17978
+ };
17979
+ }, "renderLink");
17980
+ const groups = groupByType(Object.values(filtersById));
17981
+ const links = Object.values(groups).map(
17982
+ (group) => group.sort((a2, b2) => a2.id.localeCompare(b2.id)).map((filter2) => renderLink(filter2)).filter(Boolean)
17834
17983
  );
17835
- const docsUrl = api.getDocsUrl({ subpath: "writing-stories/tags#filtering-by-custom-tags" });
17836
- const noTags = {
17837
- id: "no-tags",
17838
- title: "There are no tags. Use tags to organize and filter your Storybook.",
17839
- isIndented: false
17840
- };
17841
- const groups = [
17842
- allTags.size === 0 ? [noTags] : [],
17843
- userEntries.sort((a2, b2) => a2[0].localeCompare(b2[0])).map(([tag, count]) => {
17844
- const checked = selectedTags.includes(tag);
17845
- const id = `tag-${tag}`;
17846
- return {
17847
- id,
17848
- title: tag,
17849
- right: count,
17850
- input: react_default.createElement(Form.Checkbox, { checked, onChange: () => toggleTag(tag) })
17851
- };
17852
- }),
17853
- builtInEntries.sort((a2, b2) => a2[0].localeCompare(b2[0])).map(([tag, count]) => {
17854
- const checked = selectedTags.includes(tag);
17855
- const id = `tag-${tag}`;
17856
- return {
17857
- id,
17858
- title: tag,
17859
- right: count,
17860
- input: react_default.createElement(Form.Checkbox, { checked, onChange: () => toggleTag(tag) })
17861
- };
17862
- })
17863
- ];
17864
- if (userEntries.length === 0 && isDevelopment) {
17865
- groups.push([
17984
+ if (!groups.tag?.length && isDevelopment) {
17985
+ links.push([
17866
17986
  {
17867
17987
  id: "tags-docs",
17868
17988
  title: "Learn how to add tags",
17869
17989
  icon: react_default.createElement(DocumentIcon, null),
17870
17990
  right: react_default.createElement(ShareAltIcon, null),
17871
- href: docsUrl
17991
+ href: api.getDocsUrl({ subpath: "writing-stories/tags#filtering-by-custom-tags" })
17872
17992
  }
17873
17993
  ]);
17874
17994
  }
17875
- 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(
17995
+ const filtersLabel = includedFilters.size === 0 && excludedFilters.size === 0 ? "Select all" : "Clear filters";
17996
+ 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(
17997
+ IconButton,
17998
+ {
17999
+ id: "select-all",
18000
+ "aria-label": filtersLabel,
18001
+ key: "select-all",
18002
+ onClick: () => setAllFilters(true)
18003
+ },
18004
+ react_default.createElement(BatchAcceptIcon, null),
18005
+ filtersLabel
18006
+ ) : react_default.createElement(
17876
18007
  IconButton,
17877
18008
  {
17878
- id: "invert-selection",
17879
- disabled: selectedTags.length === 0,
17880
- onClick: () => setInverted(!inverted),
17881
- active: inverted
18009
+ id: "deselect-all",
18010
+ "aria-label": filtersLabel,
18011
+ key: "deselect-all",
18012
+ onClick: () => setAllFilters(false)
17882
18013
  },
17883
- inverted ? react_default.createElement(EyeCloseIcon, null) : react_default.createElement(EyeIcon, null),
17884
- "Invert"
17885
- )), react_default.createElement(TooltipLinkList, { links: groups }));
18014
+ react_default.createElement(SweepIcon, null),
18015
+ filtersLabel
18016
+ ), hasDefaultSelection && react_default.createElement(
18017
+ WithTooltip,
18018
+ {
18019
+ delayShow: 1e3,
18020
+ hasChrome: false,
18021
+ tooltip: react_default.createElement(TooltipNote, { note: "Reset to default selection" }),
18022
+ trigger: "hover"
18023
+ },
18024
+ react_default.createElement(
18025
+ IconButton,
18026
+ {
18027
+ id: "reset-filters",
18028
+ key: "reset-filters",
18029
+ onClick: resetFilters,
18030
+ "aria-label": "Reset filters",
18031
+ disabled: isDefaultSelection
18032
+ },
18033
+ react_default.createElement(UndoIcon, null)
18034
+ )
18035
+ )), react_default.createElement(TooltipLinkList, { links }));
17886
18036
  }, "TagsFilterPanel");
17887
18037
 
17888
18038
  // src/manager/components/sidebar/TagsFilter.tsx
17889
18039
  var TAGS_FILTER = "tags-filter";
17890
- var BUILT_IN_TAGS_HIDE = /* @__PURE__ */ new Set(["dev", "autodocs", "test", "attached-mdx", "unattached-mdx"]);
18040
+ var BUILT_IN_TAGS = /* @__PURE__ */ new Set([
18041
+ "dev",
18042
+ "test",
18043
+ "autodocs",
18044
+ "attached-mdx",
18045
+ "unattached-mdx",
18046
+ "play-fn",
18047
+ "test-fn"
18048
+ ]);
17891
18049
  var Wrapper4 = styled.div({
17892
18050
  position: "relative"
17893
18051
  });
@@ -17908,53 +18066,119 @@ var TagSelected = styled(Badge)(({ theme }) => ({
17908
18066
  background: theme.color.secondary,
17909
18067
  color: theme.color.lightest
17910
18068
  }));
17911
- var TagsFilter = /* @__PURE__ */ __name(({
17912
- api,
17913
- indexJson,
17914
- initialSelectedTags = [],
17915
- isDevelopment
17916
- }) => {
17917
- const [selectedTags, setSelectedTags] = useState(initialSelectedTags);
18069
+ var TagsFilter = /* @__PURE__ */ __name(({ api, indexJson, isDevelopment, tagPresets }) => {
18070
+ const filtersById = useMemo(() => {
18071
+ const userTagsCounts = Object.values(indexJson.entries).reduce((acc, entry) => {
18072
+ entry.tags?.forEach((tag) => {
18073
+ if (!BUILT_IN_TAGS.has(tag)) {
18074
+ acc.set(tag, (acc.get(tag) || 0) + 1);
18075
+ }
18076
+ });
18077
+ return acc;
18078
+ }, /* @__PURE__ */ new Map());
18079
+ const userFilters = Object.fromEntries(
18080
+ userTagsCounts.entries().map(([tag, count]) => {
18081
+ const filterFn = /* @__PURE__ */ __name((entry, excluded) => excluded ? !entry.tags?.includes(tag) : !!entry.tags?.includes(tag), "filterFn");
18082
+ return [tag, { id: tag, type: "tag", title: tag, count, filterFn }];
18083
+ })
18084
+ );
18085
+ const withCount = /* @__PURE__ */ __name((filterFn) => ({
18086
+ count: Object.values(indexJson.entries).filter((entry) => filterFn(entry)).length,
18087
+ filterFn
18088
+ }), "withCount");
18089
+ const builtInFilters = {
18090
+ _docs: {
18091
+ id: "_docs",
18092
+ type: "built-in",
18093
+ title: "Documentation",
18094
+ icon: react_default.createElement(DocumentIcon, { color: color.gold }),
18095
+ ...withCount(
18096
+ (entry, excluded) => excluded ? entry.type !== "docs" : entry.type === "docs"
18097
+ )
18098
+ },
18099
+ _play: {
18100
+ id: "_play",
18101
+ type: "built-in",
18102
+ title: "Play",
18103
+ icon: react_default.createElement(PlayHollowIcon, { color: color.seafoam }),
18104
+ ...withCount(
18105
+ (entry, excluded) => excluded ? entry.type !== "story" || !entry.tags?.includes("play-fn") : entry.type === "story" && !!entry.tags?.includes("play-fn")
18106
+ )
18107
+ },
18108
+ _test: {
18109
+ id: "_test",
18110
+ type: "built-in",
18111
+ title: "Testing",
18112
+ icon: react_default.createElement(BeakerIcon, { color: color.green }),
18113
+ ...withCount(
18114
+ (entry, excluded) => excluded ? entry.type !== "story" || entry.subtype !== "test" : entry.type === "story" && entry.subtype === "test"
18115
+ )
18116
+ }
18117
+ };
18118
+ return { ...userFilters, ...builtInFilters };
18119
+ }, [indexJson.entries]);
18120
+ const { defaultIncluded, defaultExcluded } = useMemo(() => {
18121
+ return Object.entries(tagPresets).reduce(
18122
+ (acc, [tag, { defaultFilterSelection }]) => {
18123
+ if (defaultFilterSelection === "include") {
18124
+ acc.defaultIncluded.add(tag);
18125
+ } else if (defaultFilterSelection === "exclude") {
18126
+ acc.defaultExcluded.add(tag);
18127
+ }
18128
+ return acc;
18129
+ },
18130
+ { defaultIncluded: /* @__PURE__ */ new Set(), defaultExcluded: /* @__PURE__ */ new Set() }
18131
+ );
18132
+ }, [tagPresets]);
18133
+ const [includedFilters, setIncludedFilters] = useState(new Set(defaultIncluded));
18134
+ const [excludedFilters, setExcludedFilters] = useState(new Set(defaultExcluded));
17918
18135
  const [expanded, setExpanded] = useState(false);
17919
- const [inverted, setInverted] = useState(false);
17920
- const tagsActive = selectedTags.length > 0;
18136
+ const tagsActive = includedFilters.size > 0 || excludedFilters.size > 0;
18137
+ const resetFilters = useCallback(() => {
18138
+ setIncludedFilters(new Set(defaultIncluded));
18139
+ setExcludedFilters(new Set(defaultExcluded));
18140
+ }, [defaultIncluded, defaultExcluded]);
18141
+ useEffect(resetFilters, [resetFilters]);
17921
18142
  useEffect(() => {
17922
18143
  api.experimental_setFilter(TAGS_FILTER, (item) => {
17923
- if (selectedTags.length === 0) {
17924
- return true;
17925
- }
17926
- const match = selectedTags.some((tag) => item.tags?.includes(tag));
17927
- return inverted ? !match : match;
17928
- });
17929
- }, [api, selectedTags, inverted]);
17930
- const allTags = Object.values(indexJson.entries).reduce((acc, entry) => {
17931
- entry.tags?.forEach((tag) => {
17932
- if (!BUILT_IN_TAGS_HIDE.has(tag)) {
17933
- acc.set(tag, (acc.get(tag) || 0) + 1);
17934
- }
18144
+ const included = Object.values(
18145
+ groupByType(Array.from(includedFilters).map((id) => filtersById[id]))
18146
+ );
18147
+ const excluded = Object.values(
18148
+ groupByType(Array.from(excludedFilters).map((id) => filtersById[id]))
18149
+ );
18150
+ return (!included.length || included.every((group) => group.some(({ filterFn }) => filterFn(item, false)))) && (!excluded.length || excluded.every((group) => group.every(({ filterFn }) => filterFn(item, true))));
17935
18151
  });
17936
- return acc;
17937
- }, /* @__PURE__ */ new Map());
17938
- const toggleTag = useCallback(
17939
- (tag) => {
17940
- if (selectedTags.includes(tag)) {
17941
- setSelectedTags(selectedTags.filter((t2) => t2 !== tag));
18152
+ }, [api, includedFilters, excludedFilters, filtersById]);
18153
+ const toggleFilter = useCallback(
18154
+ (id, selected, excluded) => {
18155
+ const set2 = /* @__PURE__ */ new Set([id]);
18156
+ if (excluded === true) {
18157
+ setExcludedFilters(excludedFilters.union(set2));
18158
+ setIncludedFilters(includedFilters.difference(set2));
18159
+ } else if (excluded === false) {
18160
+ setIncludedFilters(includedFilters.union(set2));
18161
+ setExcludedFilters(excludedFilters.difference(set2));
18162
+ } else if (selected) {
18163
+ setIncludedFilters(includedFilters.union(set2));
18164
+ setExcludedFilters(excludedFilters.difference(set2));
17942
18165
  } else {
17943
- setSelectedTags([...selectedTags, tag]);
18166
+ setIncludedFilters(includedFilters.difference(set2));
18167
+ setExcludedFilters(excludedFilters.difference(set2));
17944
18168
  }
17945
18169
  },
17946
- [selectedTags, setSelectedTags]
18170
+ [includedFilters, excludedFilters]
17947
18171
  );
17948
- const setAllTags = useCallback(
18172
+ const setAllFilters = useCallback(
17949
18173
  (selected) => {
17950
18174
  if (selected) {
17951
- setSelectedTags(Array.from(allTags.keys()));
18175
+ setIncludedFilters(new Set(Object.keys(filtersById)));
17952
18176
  } else {
17953
- setSelectedTags([]);
17954
- setInverted(false);
18177
+ setIncludedFilters(/* @__PURE__ */ new Set());
17955
18178
  }
18179
+ setExcludedFilters(/* @__PURE__ */ new Set());
17956
18180
  },
17957
- [allTags, setSelectedTags]
18181
+ [filtersById]
17958
18182
  );
17959
18183
  const handleToggleExpand = useCallback(
17960
18184
  (event) => {
@@ -17963,7 +18187,7 @@ var TagsFilter = /* @__PURE__ */ __name(({
17963
18187
  },
17964
18188
  [expanded, setExpanded]
17965
18189
  );
17966
- if (allTags.size === 0 && !isDevelopment) {
18190
+ if (Object.keys(filtersById).length === 0 && !isDevelopment) {
17967
18191
  return null;
17968
18192
  }
17969
18193
  return react_default.createElement(
@@ -17977,18 +18201,20 @@ var TagsFilter = /* @__PURE__ */ __name(({
17977
18201
  TagsFilterPanel,
17978
18202
  {
17979
18203
  api,
17980
- allTags,
17981
- selectedTags,
17982
- toggleTag,
17983
- setAllTags,
17984
- inverted,
17985
- setInverted,
17986
- isDevelopment
18204
+ filtersById,
18205
+ includedFilters,
18206
+ excludedFilters,
18207
+ toggleFilter,
18208
+ setAllFilters,
18209
+ resetFilters,
18210
+ isDevelopment,
18211
+ isDefaultSelection: includedFilters.symmetricDifference(defaultIncluded).size === 0 && excludedFilters.symmetricDifference(defaultExcluded).size === 0,
18212
+ hasDefaultSelection: defaultIncluded.size > 0 || defaultExcluded.size > 0
17987
18213
  }
17988
18214
  ),
17989
18215
  closeOnOutsideClick: true
17990
18216
  },
17991
- 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))
18217
+ 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))
17992
18218
  );
17993
18219
  }, "TagsFilter");
17994
18220
 
@@ -25044,9 +25270,18 @@ var Sidebar = react_default.memo(/* @__PURE__ */ __name(function Sidebar2({
25044
25270
  const selected = useMemo(() => storyId && { storyId, refId }, [storyId, refId]);
25045
25271
  const dataset = useCombination(index, indexError, previewInitialized, allStatuses, refs);
25046
25272
  const isLoading = !index && !indexError;
25273
+ const hasEntries = Object.keys(indexJson?.entries ?? {}).length > 0;
25047
25274
  const lastViewedProps = useLastViewed(selected);
25048
25275
  const { isMobile } = useLayout();
25049
25276
  const api = useStorybookApi();
25277
+ const tagPresets = useMemo(
25278
+ () => Object.entries(scope.TAGS_OPTIONS ?? {}).reduce((acc, entry) => {
25279
+ const [tag, option] = entry;
25280
+ acc[tag] = option;
25281
+ return acc;
25282
+ }, {}),
25283
+ []
25284
+ );
25050
25285
  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(
25051
25286
  Heading,
25052
25287
  {
@@ -25088,7 +25323,15 @@ var Sidebar = react_default.memo(/* @__PURE__ */ __name(function Sidebar2({
25088
25323
  onOpenChange: setIsFileSearchModalOpen
25089
25324
  }
25090
25325
  )),
25091
- searchFieldContent: indexJson && react_default.createElement(TagsFilter, { api, indexJson, isDevelopment }),
25326
+ searchFieldContent: indexJson && react_default.createElement(
25327
+ TagsFilter,
25328
+ {
25329
+ api,
25330
+ indexJson,
25331
+ isDevelopment,
25332
+ tagPresets
25333
+ }
25334
+ ),
25092
25335
  ...lastViewedProps
25093
25336
  },
25094
25337
  ({
@@ -25105,7 +25348,8 @@ var Sidebar = react_default.memo(/* @__PURE__ */ __name(function Sidebar2({
25105
25348
  dataset,
25106
25349
  selected,
25107
25350
  isLoading,
25108
- isBrowsing
25351
+ isBrowsing,
25352
+ hasEntries
25109
25353
  }
25110
25354
  ), react_default.createElement(
25111
25355
  SearchResults,