zudoku 0.32.0 → 0.32.2

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 (203) hide show
  1. package/dist/app/tailwind.js +6 -0
  2. package/dist/app/tailwind.js.map +1 -1
  3. package/dist/config/validators/InputSidebarSchema.d.ts +15 -15
  4. package/dist/config/validators/InputSidebarSchema.js +10 -1
  5. package/dist/config/validators/InputSidebarSchema.js.map +1 -1
  6. package/dist/config/validators/common.d.ts +40 -40
  7. package/dist/config/validators/icon-types.d.ts +1 -1
  8. package/dist/config/validators/validate.d.ts +19 -19
  9. package/dist/lib/components/Header.js +1 -1
  10. package/dist/lib/components/Header.js.map +1 -1
  11. package/dist/lib/components/Layout.js +1 -1
  12. package/dist/lib/components/Layout.js.map +1 -1
  13. package/dist/lib/components/TopNavigation.js +3 -2
  14. package/dist/lib/components/TopNavigation.js.map +1 -1
  15. package/dist/lib/components/context/ZudokuContext.d.ts +1 -1
  16. package/dist/lib/components/index.d.ts +1 -0
  17. package/dist/lib/components/index.js +2 -0
  18. package/dist/lib/components/index.js.map +1 -1
  19. package/dist/lib/components/navigation/SidebarBadge.d.ts +2 -0
  20. package/dist/lib/components/navigation/SidebarBadge.js +3 -1
  21. package/dist/lib/components/navigation/SidebarBadge.js.map +1 -1
  22. package/dist/lib/components/navigation/SidebarItem.js +1 -1
  23. package/dist/lib/components/navigation/SidebarItem.js.map +1 -1
  24. package/dist/lib/components/navigation/SidebarWrapper.js +1 -1
  25. package/dist/lib/components/navigation/SidebarWrapper.js.map +1 -1
  26. package/dist/lib/oas/graphql/index.js +3 -1
  27. package/dist/lib/oas/graphql/index.js.map +1 -1
  28. package/dist/lib/plugins/api-catalog/Catalog.d.ts +2 -2
  29. package/dist/lib/plugins/api-catalog/Catalog.js +11 -24
  30. package/dist/lib/plugins/api-catalog/Catalog.js.map +1 -1
  31. package/dist/lib/plugins/api-catalog/index.d.ts +1 -0
  32. package/dist/lib/plugins/api-catalog/index.js +37 -8
  33. package/dist/lib/plugins/api-catalog/index.js.map +1 -1
  34. package/dist/lib/plugins/markdown/MdxPage.js +1 -1
  35. package/dist/lib/plugins/markdown/MdxPage.js.map +1 -1
  36. package/dist/lib/plugins/openapi/Sidecar.js +1 -1
  37. package/dist/lib/plugins/openapi/Sidecar.js.map +1 -1
  38. package/dist/lib/plugins/openapi/SidecarExamples.js +2 -2
  39. package/dist/lib/plugins/openapi/SidecarExamples.js.map +1 -1
  40. package/dist/lib/plugins/openapi/graphql/gql.js +0 -11
  41. package/dist/lib/plugins/openapi/graphql/gql.js.map +1 -1
  42. package/dist/lib/plugins/openapi/playground/result-panel/ResponseTab.js +1 -1
  43. package/dist/lib/plugins/openapi/playground/result-panel/ResponseTab.js.map +1 -1
  44. package/dist/lib/ui/Badge.d.ts +1 -1
  45. package/dist/lib/ui/Button.d.ts +1 -1
  46. package/dist/lib/ui/Command.d.ts +1 -1
  47. package/dist/lib/ui/SyntaxHighlight.d.ts +14 -0
  48. package/dist/lib/{components → ui}/SyntaxHighlight.js +9 -6
  49. package/dist/lib/ui/SyntaxHighlight.js.map +1 -0
  50. package/dist/lib/ui/util.d.ts +2 -0
  51. package/dist/lib/ui/util.js +3 -0
  52. package/dist/lib/ui/util.js.map +1 -0
  53. package/dist/lib/util/MdxComponents.js +1 -1
  54. package/dist/lib/util/MdxComponents.js.map +1 -1
  55. package/dist/vite/config.js +4 -1
  56. package/dist/vite/config.js.map +1 -1
  57. package/dist/vite/plugin-api.js +2 -2
  58. package/dist/vite/plugin-api.js.map +1 -1
  59. package/dist/vite/plugin-sidebar.js +3 -9
  60. package/dist/vite/plugin-sidebar.js.map +1 -1
  61. package/lib/{AuthenticationPlugin-_YVa673u.js → AuthenticationPlugin-BlxA4Mbn.js} +4 -4
  62. package/lib/{AuthenticationPlugin-_YVa673u.js.map → AuthenticationPlugin-BlxA4Mbn.js.map} +1 -1
  63. package/lib/{CategoryHeading-MYL1u_6K.js → CategoryHeading-DpB47wvk.js} +3 -3
  64. package/lib/{CategoryHeading-MYL1u_6K.js.map → CategoryHeading-DpB47wvk.js.map} +1 -1
  65. package/lib/{Markdown-8mv9nhGd.js → Markdown-Cr9sYpR_.js} +4800 -4729
  66. package/lib/Markdown-Cr9sYpR_.js.map +1 -0
  67. package/lib/{MdxPage-GM1T5jmO.js → MdxPage-Dt-UEQl8.js} +10 -10
  68. package/lib/MdxPage-Dt-UEQl8.js.map +1 -0
  69. package/lib/{OasProvider-IS9wBrb7.js → OasProvider-WVtvHP5H.js} +6 -6
  70. package/lib/{OasProvider-IS9wBrb7.js.map → OasProvider-WVtvHP5H.js.map} +1 -1
  71. package/lib/{OperationList-BTmRbbXk.js → OperationList-DhOwupvv.js} +18 -19
  72. package/lib/{OperationList-BTmRbbXk.js.map → OperationList-DhOwupvv.js.map} +1 -1
  73. package/lib/Select-D9hI1G-y.js +223 -0
  74. package/lib/{Select-D9CKL33X.js.map → Select-D9hI1G-y.js.map} +1 -1
  75. package/lib/{SlotletProvider-D0mFmGJu.js → SlotletProvider-CEfNOA8i.js} +53 -53
  76. package/lib/{SlotletProvider-D0mFmGJu.js.map → SlotletProvider-CEfNOA8i.js.map} +1 -1
  77. package/lib/{Spinner-BlzrEEk1.js → Spinner-1KrEmx1V.js} +3 -3
  78. package/lib/{Spinner-BlzrEEk1.js.map → Spinner-1KrEmx1V.js.map} +1 -1
  79. package/lib/{SyntaxHighlight-B0L4SC_N.js → SyntaxHighlight-CcnUjERD.js} +445 -445
  80. package/lib/SyntaxHighlight-CcnUjERD.js.map +1 -0
  81. package/lib/{chunk-SYFQ2XB5-QijJrSf0.js → chunk-IR6S3I6Y-D_3UmFIn.js} +597 -597
  82. package/lib/chunk-IR6S3I6Y-D_3UmFIn.js.map +1 -0
  83. package/lib/{circular-DxaIIlWD.js → circular-v7K6lDDh.js} +1413 -1413
  84. package/lib/{circular-DxaIIlWD.js.map → circular-v7K6lDDh.js.map} +1 -1
  85. package/lib/context-DLCwaMXN.js +22 -0
  86. package/lib/{context-rwLGh-6_.js.map → context-DLCwaMXN.js.map} +1 -1
  87. package/lib/{createServer-DSQiPwjN.js → createServer-DMf6O2Rz.js} +3669 -3562
  88. package/lib/createServer-DMf6O2Rz.js.map +1 -0
  89. package/lib/{hook-C_t2ISLC.js → hook-CWwSAAlH.js} +384 -379
  90. package/lib/hook-CWwSAAlH.js.map +1 -0
  91. package/lib/index-Bn6Lc9tq.js +9 -0
  92. package/lib/index-Bn6Lc9tq.js.map +1 -0
  93. package/lib/index-CPNSgwSb.js +36 -0
  94. package/lib/{index-Djenk2Hj.js.map → index-CPNSgwSb.js.map} +1 -1
  95. package/lib/{index-BANyVRgL.js → index-Do_30Hpk.js} +78 -78
  96. package/lib/index-Do_30Hpk.js.map +1 -0
  97. package/lib/{index-B7mqiOei.js → index-Du5aNddU.js} +101 -101
  98. package/lib/index-Du5aNddU.js.map +1 -0
  99. package/lib/{index-CjJS0l4l.js → index-LNp6rxyU.js} +2 -2
  100. package/lib/{index-CjJS0l4l.js.map → index-LNp6rxyU.js.map} +1 -1
  101. package/lib/{index.esm-CrSoEshU.js → index.esm--gIChbWs.js} +3 -3
  102. package/lib/{index.esm-CrSoEshU.js.map → index.esm--gIChbWs.js.map} +1 -1
  103. package/lib/{index.esm-9-TF9KQB.js → index.esm-CQHE3GEU.js} +52 -53
  104. package/lib/{index.esm-9-TF9KQB.js.map → index.esm-CQHE3GEU.js.map} +1 -1
  105. package/lib/joinUrl-10po2Jdj.js +20 -0
  106. package/lib/{joinUrl-nLx9pD-Z.js.map → joinUrl-10po2Jdj.js.map} +1 -1
  107. package/lib/{jsx-runtime-Bdg6XQ1m.js → jsx-runtime-CYK1ROHF.js} +99 -99
  108. package/lib/{jsx-runtime-Bdg6XQ1m.js.map → jsx-runtime-CYK1ROHF.js.map} +1 -1
  109. package/lib/{mutation-Cm3O9f3X.js → mutation-B0wxqzSN.js} +26 -26
  110. package/lib/{mutation-Cm3O9f3X.js.map → mutation-B0wxqzSN.js.map} +1 -1
  111. package/lib/post-processors/removeExtensions.js +4 -4
  112. package/lib/ui/Accordion.js +1 -1
  113. package/lib/ui/ActionButton.js +2 -2
  114. package/lib/ui/Alert.js +2 -2
  115. package/lib/ui/AlertDialog.js +1 -1
  116. package/lib/ui/Badge.js +2 -2
  117. package/lib/ui/Breadcrumb.js +4 -4
  118. package/lib/ui/Button.js +2 -2
  119. package/lib/ui/Callout.js +4 -4
  120. package/lib/ui/Card.js +1 -1
  121. package/lib/ui/Carousel.js +1 -1
  122. package/lib/ui/Checkbox.js +2 -2
  123. package/lib/ui/Command.js +2 -2
  124. package/lib/ui/Dialog.js +1 -1
  125. package/lib/ui/Drawer.js +521 -543
  126. package/lib/ui/Drawer.js.map +1 -1
  127. package/lib/ui/DropdownMenu.js +1 -1
  128. package/lib/ui/Form.js +5 -5
  129. package/lib/ui/HoverCard.js +1 -1
  130. package/lib/ui/Input.js +1 -1
  131. package/lib/ui/Label.js +2 -2
  132. package/lib/ui/Pagination.js +10 -10
  133. package/lib/ui/Popover.js +1 -1
  134. package/lib/ui/Progress.js +1 -1
  135. package/lib/ui/RadioGroup.js +1 -1
  136. package/lib/ui/ScrollArea.js +1 -1
  137. package/lib/ui/Select.js +1 -1
  138. package/lib/ui/Skeleton.js +1 -1
  139. package/lib/ui/Slider.js +1 -1
  140. package/lib/ui/Switch.js +1 -1
  141. package/lib/ui/SyntaxHighlight.js +10 -0
  142. package/lib/ui/SyntaxHighlight.js.map +1 -0
  143. package/lib/ui/Tabs.js +1 -1
  144. package/lib/ui/Textarea.js +1 -1
  145. package/lib/ui/Toggle.js +2 -2
  146. package/lib/ui/ToggleGroup.js +1 -1
  147. package/lib/ui/Tooltip.js +1 -1
  148. package/lib/ui/util.js +6 -0
  149. package/lib/ui/util.js.map +1 -0
  150. package/lib/{useExposedProps-Bbf99zic.js → useExposedProps-RIvey2Oy.js} +2 -2
  151. package/lib/{useExposedProps-Bbf99zic.js.map → useExposedProps-RIvey2Oy.js.map} +1 -1
  152. package/lib/{useScrollToAnchor-BGEcH3HM.js → useScrollToAnchor-C-sRxs9o.js} +13 -9
  153. package/lib/useScrollToAnchor-C-sRxs9o.js.map +1 -0
  154. package/lib/zudoku.auth-auth0.js +1 -1
  155. package/lib/zudoku.auth-clerk.js +18 -18
  156. package/lib/zudoku.auth-openid.js +255 -295
  157. package/lib/zudoku.auth-openid.js.map +1 -1
  158. package/lib/zudoku.components.js +305 -298
  159. package/lib/zudoku.components.js.map +1 -1
  160. package/lib/zudoku.icons.js +1 -1
  161. package/lib/zudoku.plugin-api-catalog.js +91 -108
  162. package/lib/zudoku.plugin-api-catalog.js.map +1 -1
  163. package/lib/zudoku.plugin-api-keys.js +6 -6
  164. package/lib/zudoku.plugin-custom-pages.js +3 -3
  165. package/lib/zudoku.plugin-markdown.js +2 -2
  166. package/lib/zudoku.plugin-openapi.js +6 -6
  167. package/lib/zudoku.plugin-redirect.js +1 -1
  168. package/lib/zudoku.plugin-search-inkeep.js +9 -9
  169. package/package.json +49 -50
  170. package/src/app/tailwind.ts +6 -0
  171. package/src/lib/components/Header.tsx +1 -1
  172. package/src/lib/components/Layout.tsx +1 -1
  173. package/src/lib/components/TopNavigation.tsx +13 -9
  174. package/src/lib/components/index.ts +2 -0
  175. package/src/lib/components/navigation/SidebarBadge.tsx +4 -1
  176. package/src/lib/components/navigation/SidebarItem.tsx +1 -0
  177. package/src/lib/components/navigation/SidebarWrapper.tsx +1 -1
  178. package/src/lib/oas/graphql/index.ts +4 -1
  179. package/src/lib/plugins/api-catalog/Catalog.tsx +31 -94
  180. package/src/lib/plugins/api-catalog/index.tsx +54 -9
  181. package/src/lib/plugins/markdown/MdxPage.tsx +1 -1
  182. package/src/lib/plugins/openapi/Sidecar.tsx +1 -1
  183. package/src/lib/plugins/openapi/SidecarExamples.tsx +1 -2
  184. package/src/lib/plugins/openapi/graphql/gql.ts +9 -1
  185. package/src/lib/plugins/openapi/playground/result-panel/ResponseTab.tsx +1 -1
  186. package/src/lib/{components → ui}/SyntaxHighlight.tsx +23 -8
  187. package/src/lib/ui/util.tsx +3 -0
  188. package/src/lib/util/MdxComponents.tsx +1 -1
  189. package/dist/lib/components/SyntaxHighlight.d.ts +0 -12
  190. package/dist/lib/components/SyntaxHighlight.js.map +0 -1
  191. package/lib/Markdown-8mv9nhGd.js.map +0 -1
  192. package/lib/MdxPage-GM1T5jmO.js.map +0 -1
  193. package/lib/Select-D9CKL33X.js +0 -223
  194. package/lib/SyntaxHighlight-B0L4SC_N.js.map +0 -1
  195. package/lib/chunk-SYFQ2XB5-QijJrSf0.js.map +0 -1
  196. package/lib/context-rwLGh-6_.js +0 -22
  197. package/lib/createServer-DSQiPwjN.js.map +0 -1
  198. package/lib/hook-C_t2ISLC.js.map +0 -1
  199. package/lib/index-B7mqiOei.js.map +0 -1
  200. package/lib/index-BANyVRgL.js.map +0 -1
  201. package/lib/index-Djenk2Hj.js +0 -36
  202. package/lib/joinUrl-nLx9pD-Z.js +0 -20
  203. package/lib/useScrollToAnchor-BGEcH3HM.js.map +0 -1
@@ -7,6 +7,7 @@ import { ZudokuError } from "../util/invariant.js";
7
7
  import { joinPath } from "../util/joinPath.js";
8
8
  import { useCurrentNavigation, useZudoku } from "./context/ZudokuContext.js";
9
9
  import { traverseSidebar } from "./navigation/utils.js";
10
+ import { Slotlet } from "./SlotletProvider.js";
10
11
 
11
12
  export const isHiddenItem =
12
13
  (isAuthenticated?: boolean) =>
@@ -30,15 +31,18 @@ export const TopNavigation = () => {
30
31
 
31
32
  return (
32
33
  <Suspense>
33
- <nav className="hidden lg:block text-sm px-12 h-[--top-nav-height]">
34
- <ul className="flex flex-row items-center gap-8">
35
- {topNavigation.filter(isHiddenItem(isAuthenticated)).map((item) => (
36
- <li key={item.id}>
37
- <TopNavItem {...item} />
38
- </li>
39
- ))}
40
- </ul>
41
- </nav>
34
+ <div className=" items-center justify-between px-8 h-[--top-nav-height] hidden lg:flex text-sm">
35
+ <nav className="text-sm">
36
+ <ul className="flex flex-row items-center gap-8">
37
+ {topNavigation.filter(isHiddenItem(isAuthenticated)).map((item) => (
38
+ <li key={item.id}>
39
+ <TopNavItem {...item} />
40
+ </li>
41
+ ))}
42
+ </ul>
43
+ </nav>
44
+ <Slotlet name="top-navigation-side" />
45
+ </div>
42
46
  </Suspense>
43
47
  );
44
48
  };
@@ -1,5 +1,6 @@
1
1
  import { useMDXComponents as useMDXComponentsImport } from "@mdx-js/react";
2
2
  import { Helmet } from "@zudoku/react-helmet-async";
3
+ import { useTheme as useThemeImport } from "next-themes";
3
4
  import { Link as LinkImport } from "react-router";
4
5
  import { useAuth as useAuthImport } from "../authentication/hook.js";
5
6
  import { RouteGuard as RouteGuardImport } from "../core/RouteGuard.js";
@@ -46,3 +47,4 @@ export const Spinner = /*@__PURE__*/ SpinnerImport;
46
47
  export const ClientOnly = /*@__PURE__*/ ClientOnlyImport;
47
48
  export const Button = /*@__PURE__*/ ButtonImport;
48
49
  export const Link = /*@__PURE__*/ LinkImport;
50
+ export const useTheme = /*@__PURE__*/ useThemeImport;
@@ -8,6 +8,7 @@ export const ColorMap = {
8
8
  purple: "bg-purple-400 dark:bg-purple-600",
9
9
  indigo: "bg-indigo-400 dark:bg-indigo-600",
10
10
  gray: "bg-gray-400 dark:bg-gray-600",
11
+ outline: "border border-border rounded-md text-foreground",
11
12
  };
12
13
 
13
14
  export const ColorMapInvert = {
@@ -18,6 +19,7 @@ export const ColorMapInvert = {
18
19
  purple: "text-purple-400 dark:text-purple-600",
19
20
  indigo: "text-indigo-400 dark:text-indigo-600",
20
21
  gray: "text-gray-400 dark:text-gray-600",
22
+ outline: "",
21
23
  };
22
24
 
23
25
  export const SidebarBadge = ({
@@ -34,7 +36,8 @@ export const SidebarBadge = ({
34
36
  return (
35
37
  <span
36
38
  className={cn(
37
- "mt-0.5 flex items-center duration-200 transition-opacity text-center uppercase font-mono text-[0.65rem] font-bold rounded text-background dark:text-zinc-50 h-4 px-1",
39
+ "flex items-center duration-200 transition-opacity text-center uppercase text-[0.65rem] font-bold rounded text-background dark:text-zinc-50 h-full",
40
+ color === "outline" ? "px-3" : "mt-0.5 px-1",
38
41
  invert ? ColorMapInvert[color] : ColorMap[color],
39
42
  className,
40
43
  )}
@@ -51,6 +51,7 @@ export const SidebarItem = ({
51
51
  className={({ isActive }) => navigationListItem({ isActive })}
52
52
  to={joinPath(item.id)}
53
53
  onClick={onRequestClose}
54
+ end
54
55
  >
55
56
  {item.icon && <item.icon size={16} className="align-[-0.125em]" />}
56
57
  {item.badge ? (
@@ -12,7 +12,7 @@ export const SidebarWrapper = forwardRef<
12
12
  // maybe this could be simplified by adjusting the layout
13
13
  data-navigation={String(pushMainContent)}
14
14
  className={cn(
15
- "scrollbar peer hidden lg:flex flex-col fixed text-sm overflow-y-auto shrink-0 border-r pr-10",
15
+ "scrollbar peer hidden lg:flex flex-col fixed text-sm overflow-y-auto shrink-0 border-r pr-6",
16
16
  "-mx-[--padding-nav-item] pb-20 pt-[--padding-content-top]",
17
17
  "w-[--side-nav-width] h-[calc(100%-var(--header-height))] scroll-pt-2 gap-2",
18
18
  !pushMainContent && "border-r-0",
@@ -59,6 +59,7 @@ export type SchemaImports = Record<
59
59
  >;
60
60
 
61
61
  const builder = new SchemaBuilder<{
62
+ DefaultFieldNullability: false;
62
63
  Scalars: {
63
64
  JSON: any;
64
65
  JSONObject: any;
@@ -72,7 +73,9 @@ const builder = new SchemaBuilder<{
72
73
  currentTag?: string;
73
74
  slugify: CountableSlugify;
74
75
  };
75
- }>({});
76
+ }>({
77
+ defaultFieldNullability: false,
78
+ });
76
79
 
77
80
  type GraphQLOperationObject = OperationObject & {
78
81
  path: string;
@@ -1,23 +1,20 @@
1
- import slugify from "@sindresorhus/slugify";
2
1
  import { useSuspenseQuery } from "@tanstack/react-query";
3
- import { useSearchParams } from "react-router";
2
+ import { useMatch } from "react-router";
4
3
  import { Head, Link } from "zudoku/components";
5
4
  import { useAuthState } from "../../authentication/state.js";
5
+ import { Heading } from "../../components/Heading.js";
6
6
  import { Markdown } from "../../components/Markdown.js";
7
- import { cn } from "../../util/cn.js";
8
- import type { ApiCatalogPluginOptions } from "./index.js";
9
-
10
- const getKey = (category: string, tag: string) => slugify(`${category}-${tag}`);
7
+ import { joinUrl } from "../../util/joinUrl.js";
8
+ import { type ApiCatalogPluginOptions, getKey } from "./index.js";
11
9
 
12
10
  export const Catalog = ({
13
11
  items,
14
12
  filterCatalogItems = (items) => items,
15
- categories,
16
13
  label = "API Library",
17
14
  }: Omit<ApiCatalogPluginOptions, "navigationId">) => {
18
- const [searchParams, setSearchParams] = useSearchParams();
19
- const activeCategory = searchParams.get("category");
20
15
  const auth = useAuthState();
16
+ const match = useMatch({ path: "/catalog/:category" });
17
+ const activeCategory = match?.params.category;
21
18
 
22
19
  const catalogItems = useSuspenseQuery({
23
20
  queryFn: () => filterCatalogItems(items, { auth }),
@@ -29,93 +26,33 @@ export const Catalog = ({
29
26
  <Head>
30
27
  <title>{label}</title>
31
28
  </Head>
32
- <div className="grid grid-cols-12 gap-12">
33
- <div className="flex flex-col gap-4 col-span-3 not-prose sticky top-48">
34
- <div className="max-w-[--side-nav-width] flex flex-col gap-4 justify-between">
35
- {categories?.map((category, idx) => (
36
- <div key={category.label}>
37
- <div className="flex justify-between mb-2.5">
38
- <span className="font-medium text-sm">{category.label}</span>
39
- {idx === 0 && activeCategory && (
40
- <button
41
- type="button"
42
- className="text-end text-sm text-foreground/60 hover:text-foreground"
43
- onClick={() => setSearchParams({})}
44
- >
45
- Clear
46
- </button>
47
- )}
48
- </div>
49
- <ul className="space-y-1 [&>li]:py-2">
50
- {category.tags
51
- .map((tag) => ({
52
- tag,
53
- count: items.filter((api) =>
54
- api.categories.find((c) => c.tags.includes(tag)),
55
- ).length,
56
- }))
57
- .map(({ tag, count }) => {
58
- const slug = getKey(category.label, tag);
59
- const isActive = slug === activeCategory;
29
+ <div className="grid gap-4">
30
+ <Heading level={2}>{label}</Heading>
60
31
 
61
- return (
62
- <li
63
- key={slug}
64
- className={cn(
65
- "flex rounded-lg justify-between text-sm cursor-pointer hover:text-primary transition px-[--padding-nav-item] -mx-[--padding-nav-item]",
66
- isActive && "bg-border/30 rounded",
67
- )}
68
- onClick={() => setSearchParams({ category: slug })}
69
- >
70
- <span>{tag}</span>
71
- <span
72
- className={cn(
73
- "flex items-center justify-center border rounded-md w-8 text-xs font-semibold",
74
- isActive &&
75
- "bg-primary border-primary text-primary-foreground",
76
- )}
77
- >
78
- {count}
79
- </span>
80
- </li>
81
- );
82
- })}
83
- </ul>
84
- </div>
32
+ <div className="grid grid-cols-2 gap-4">
33
+ {catalogItems.data
34
+ .filter(
35
+ (api) =>
36
+ !activeCategory ||
37
+ api.categories.find((c) =>
38
+ c.tags.find((t) => getKey(c.label, t) === activeCategory),
39
+ ),
40
+ )
41
+ .map((api) => (
42
+ <Link
43
+ to={joinUrl(api.path)}
44
+ className="no-underline hover:!text-foreground"
45
+ key={api.path}
46
+ >
47
+ <div className="border h-full rounded-lg p-4 flex flex-col gap-2 cursor-pointer hover:bg-border/20 font-normal">
48
+ <span className="font-semibold">{api.label}</span>
49
+ <Markdown
50
+ className="text-sm whitespace-pre-wrap mb-6 line-clamp-2"
51
+ content={api.description}
52
+ />
53
+ </div>
54
+ </Link>
85
55
  ))}
86
- </div>
87
- </div>
88
- <div className="col-span-9">
89
- <h3 className="mt-0 text-2xl font-bold mb-4">{label}</h3>
90
-
91
- <div className="grid grid-cols-2 gap-4">
92
- {catalogItems.data
93
- .filter(
94
- (api) =>
95
- !activeCategory ||
96
- api.categories.find((c) =>
97
- c.tags.find((t) => getKey(c.label, t) === activeCategory),
98
- ),
99
- )
100
- .map((api) => (
101
- <Link
102
- to={{
103
- pathname: `/${api.path}`,
104
- search: activeCategory ? `category=${activeCategory}` : "",
105
- }}
106
- className="no-underline hover:!text-foreground"
107
- key={api.path}
108
- >
109
- <div className="border h-full rounded p-4 flex flex-col gap-2 cursor-pointer hover:bg-border/20 font-normal">
110
- <span className="font-semibold">{api.label}</span>
111
- <Markdown
112
- className="text-sm whitespace-pre-wrap mb-6 line-clamp-2"
113
- content={api.description}
114
- />
115
- </div>
116
- </Link>
117
- ))}
118
- </div>
119
56
  </div>
120
57
  </div>
121
58
  </section>
@@ -1,7 +1,14 @@
1
+ import slugify from "@sindresorhus/slugify";
2
+ import { matchPath } from "react-router";
3
+ import type { SidebarItem } from "../../../config/validators/SidebarSchema.js";
1
4
  import type { AuthState } from "../../authentication/state.js";
2
5
  import type { ZudokuPlugin } from "../../core/plugins.js";
6
+ import { joinUrl } from "../../util/joinUrl.js";
3
7
  import { Catalog } from "./Catalog.js";
4
8
 
9
+ export const getKey = (category: string, tag: string) =>
10
+ slugify(`${category}-${tag}`);
11
+
5
12
  export type ApiCatalogItem = {
6
13
  path: string;
7
14
  label: string;
@@ -35,7 +42,7 @@ export const apiCatalogPlugin = ({
35
42
  navigationId,
36
43
  items,
37
44
  label,
38
- categories,
45
+ categories = [],
39
46
  filterCatalogItems,
40
47
  }: {
41
48
  navigationId: string;
@@ -45,20 +52,58 @@ export const apiCatalogPlugin = ({
45
52
  filterCatalogItems?: filterCatalogItems;
46
53
  }): ZudokuPlugin => {
47
54
  return {
48
- getRoutes: () => {
49
- return [
50
- {
51
- path: navigationId,
55
+ getSidebar: async function Sidebar(path) {
56
+ if (!matchPath({ path: joinUrl(navigationId), end: false }, path)) {
57
+ return [];
58
+ }
59
+
60
+ const sidebar: SidebarItem[] = categories.map((category) => ({
61
+ type: "category" as const,
62
+ label: category.label,
63
+ collapsible: false,
64
+ items: category.tags.map((tag) => {
65
+ const tagPath = getKey(category.label, tag);
66
+ return {
67
+ type: "doc" as const,
68
+ id: joinUrl(navigationId, tagPath),
69
+ label: tag,
70
+ badge: {
71
+ label: String(
72
+ items.filter((api) =>
73
+ api.categories.find((c) => c.tags.includes(tag)),
74
+ ).length,
75
+ ),
76
+ color: "outline" as const,
77
+ },
78
+ };
79
+ }),
80
+ }));
81
+
82
+ sidebar.unshift({
83
+ type: "doc" as const,
84
+ id: joinUrl(navigationId),
85
+ label: "Overview",
86
+ badge: { label: String(items.length), color: "outline" as const },
87
+ });
88
+
89
+ return sidebar;
90
+ },
91
+ getRoutes: () =>
92
+ categories.flatMap((category) =>
93
+ [undefined, ...category.tags].map((tag) => ({
94
+ path: joinUrl(
95
+ navigationId,
96
+ tag ? getKey(category.label, tag) : undefined,
97
+ ),
52
98
  element: (
53
99
  <Catalog
54
100
  label={label}
55
101
  items={items}
56
102
  filterCatalogItems={filterCatalogItems}
57
- categories={categories ?? []}
103
+ categories={categories}
58
104
  />
59
105
  ),
60
- },
61
- ];
62
- },
106
+ })),
107
+ ),
63
108
  };
64
109
  };
@@ -99,7 +99,7 @@ export const MdxPage = ({
99
99
  <div
100
100
  className={cn(
101
101
  ProseClasses,
102
- "max-w-full xl:w-full xl:max-w-prose flex-1 flex-shrink pt-[--padding-content-top] pb-[--padding-content-bottom]",
102
+ "max-w-full xl:w-full xl:max-w-3xl flex-1 flex-shrink pt-[--padding-content-top] pb-[--padding-content-bottom]",
103
103
  )}
104
104
  >
105
105
  {(category || title) && (
@@ -4,8 +4,8 @@ import { useMemo, useState, useTransition } from "react";
4
4
  import { useSearchParams } from "react-router";
5
5
  import { useSelectedServer } from "../../authentication/state.js";
6
6
  import { PathRenderer } from "../../components/PathRenderer.js";
7
- import { SyntaxHighlight } from "../../components/SyntaxHighlight.js";
8
7
  import type { SchemaObject } from "../../oas/parser/index.js";
8
+ import { SyntaxHighlight } from "../../ui/SyntaxHighlight.js";
9
9
  import { cn } from "../../util/cn.js";
10
10
  import { useOnScreen } from "../../util/useOnScreen.js";
11
11
  import { useCreateQuery } from "./client/useCreateQuery.js";
@@ -1,6 +1,6 @@
1
1
  import { useEffect, useMemo, useState } from "react";
2
- import { SyntaxHighlight } from "../../components/SyntaxHighlight.js";
3
2
  import { SchemaObject } from "../../oas/parser/index.js";
3
+ import { SyntaxHighlight } from "../../ui/SyntaxHighlight.js";
4
4
  import { CollapsibleCode } from "./CollapsibleCode.js";
5
5
  import type { OperationListItemResult } from "./OperationList.js";
6
6
  import * as SidecarBox from "./SidecarBox.js";
@@ -97,7 +97,6 @@ export const SidecarExamples = ({
97
97
  <SyntaxHighlight
98
98
  language={language}
99
99
  noBackground
100
- copyable
101
100
  className="[--scrollbar-color:gray] text-xs max-h-[500px] p-2"
102
101
  code={formattedExample}
103
102
  />
@@ -12,7 +12,15 @@ import * as types from "./graphql.js";
12
12
  * Therefore it is highly recommended to use the babel or swc plugin for production.
13
13
  * Learn more about it here: https://the-guild.dev/graphql/codegen/plugins/presets/preset-client#reducing-bundle-size
14
14
  */
15
- const documents = {
15
+ type Documents = {
16
+ "\n query ServersQuery($input: JSON!, $type: SchemaType!) {\n schema(input: $input, type: $type) {\n url\n servers {\n url\n }\n }\n }\n": typeof types.ServersQueryDocument;
17
+ "\n fragment OperationsFragment on OperationItem {\n slug\n summary\n method\n description\n operationId\n contentTypes\n path\n parameters {\n name\n in\n description\n required\n schema\n style\n examples {\n name\n description\n externalValue\n value\n summary\n }\n }\n requestBody {\n content {\n mediaType\n encoding {\n name\n }\n examples {\n name\n description\n externalValue\n value\n summary\n }\n schema\n }\n description\n required\n }\n responses {\n statusCode\n links\n description\n content {\n examples {\n name\n description\n externalValue\n value\n summary\n }\n mediaType\n encoding {\n name\n }\n schema\n }\n }\n }\n": typeof types.OperationsFragmentFragmentDoc;
18
+ "\n query AllOperations(\n $input: JSON!\n $type: SchemaType!\n $tag: String\n $untagged: Boolean\n ) {\n schema(input: $input, type: $type) {\n servers {\n url\n }\n description\n summary\n title\n url\n version\n tags(name: $tag) {\n name\n description\n }\n operations(tag: $tag, untagged: $untagged) {\n slug\n ...OperationsFragment\n }\n }\n }\n": typeof types.AllOperationsDocument;
19
+ "\n query getServerQuery($input: JSON!, $type: SchemaType!) {\n schema(input: $input, type: $type) {\n url\n servers {\n url\n }\n }\n }\n": typeof types.GetServerQueryDocument;
20
+ "\n query GetCategories($input: JSON!, $type: SchemaType!) {\n schema(input: $input, type: $type) {\n url\n tags {\n name\n }\n }\n }\n": typeof types.GetCategoriesDocument;
21
+ "\n query GetOperations($input: JSON!, $type: SchemaType!, $tag: String) {\n schema(input: $input, type: $type) {\n operations(tag: $tag) {\n slug\n deprecated\n method\n summary\n operationId\n path\n tags {\n name\n }\n }\n untagged: operations(untagged: true) {\n slug\n deprecated\n method\n summary\n operationId\n path\n }\n }\n }\n": typeof types.GetOperationsDocument;
22
+ };
23
+ const documents: Documents = {
16
24
  "\n query ServersQuery($input: JSON!, $type: SchemaType!) {\n schema(input: $input, type: $type) {\n url\n servers {\n url\n }\n }\n }\n":
17
25
  types.ServersQueryDocument,
18
26
  "\n fragment OperationsFragment on OperationItem {\n slug\n summary\n method\n description\n operationId\n contentTypes\n path\n parameters {\n name\n in\n description\n required\n schema\n style\n examples {\n name\n description\n externalValue\n value\n summary\n }\n }\n requestBody {\n content {\n mediaType\n encoding {\n name\n }\n examples {\n name\n description\n externalValue\n value\n summary\n }\n schema\n }\n description\n required\n }\n responses {\n statusCode\n links\n description\n content {\n examples {\n name\n description\n externalValue\n value\n summary\n }\n mediaType\n encoding {\n name\n }\n schema\n }\n }\n }\n":
@@ -13,8 +13,8 @@ import {
13
13
  SelectTrigger,
14
14
  SelectValue,
15
15
  } from "zudoku/ui/Select.js";
16
- import { SyntaxHighlight } from "../../../../components/SyntaxHighlight.js";
17
16
  import { Card } from "../../../../ui/Card.js";
17
+ import { SyntaxHighlight } from "../../../../ui/SyntaxHighlight.js";
18
18
  import { convertToTypes } from "./convertToTypes.js";
19
19
 
20
20
  const statusCodeMap: Record<number, string> = {
@@ -31,17 +31,20 @@ void import("prismjs/components/prism-typescript.min.js");
31
31
 
32
32
  import { useTheme } from "next-themes";
33
33
  import { useState } from "react";
34
+ import { ClientOnly } from "../components/ClientOnly.js";
34
35
  import { cn } from "../util/cn.js";
35
- import { ClientOnly } from "./ClientOnly.js";
36
36
 
37
- type SyntaxHighlightProps = {
37
+ export type SyntaxHighlightProps = {
38
38
  className?: string;
39
39
  noBackground?: boolean;
40
40
  wrapLines?: boolean;
41
- copyable?: boolean;
42
41
  showLanguageIndicator?: boolean;
43
42
  language?: string;
44
43
  title?: string;
44
+ children?: string;
45
+ code?: string;
46
+ showCopy?: "hover" | "always" | "never";
47
+ showCopyText?: boolean;
45
48
  } & Omit<HighlightProps, "children" | "language">;
46
49
 
47
50
  const remapLang = {
@@ -49,15 +52,19 @@ const remapLang = {
49
52
  } as Record<string, string>;
50
53
 
51
54
  export const SyntaxHighlight = ({
52
- copyable = true,
53
55
  language = "plain",
56
+ showCopy = "hover",
57
+ showCopyText,
54
58
  title,
59
+ children,
55
60
  ...props
56
61
  }: SyntaxHighlightProps) => {
57
62
  const { resolvedTheme } = useTheme();
58
63
  const [isCopied, setIsCopied] = useState(false);
59
64
 
60
- if (!props.code) {
65
+ const code = children ?? props.code;
66
+
67
+ if (!code) {
61
68
  return null;
62
69
  }
63
70
 
@@ -86,7 +93,7 @@ export const SyntaxHighlight = ({
86
93
  title && "pt-10",
87
94
  )}
88
95
  >
89
- {props.code}
96
+ {code}
90
97
  </pre>
91
98
  {props.showLanguageIndicator && (
92
99
  <span className="absolute top-1.5 right-3 text-[11px] font-mono text-muted-foreground transition group-hover:opacity-0">
@@ -100,6 +107,7 @@ export const SyntaxHighlight = ({
100
107
  theme={highlightTheme}
101
108
  language={remapLang[language] ?? language}
102
109
  {...props}
110
+ code={code}
103
111
  >
104
112
  {({ className, style, tokens, getLineProps, getTokenProps }) => (
105
113
  <div className="relative group">
@@ -134,12 +142,18 @@ export const SyntaxHighlight = ({
134
142
  {language}
135
143
  </span>
136
144
  )}
137
- {copyable && (
145
+ {showCopy !== "never" && (
138
146
  <button
139
147
  type="button"
140
148
  aria-label="Copy code"
141
149
  title="Copy code"
142
- className="absolute top-2 right-2 p-2 opacity-0 group-hover:opacity-100 group-hover:bg-zinc-100 group-hover:dark:bg-zinc-700 hover:outline hover:outline-border/75 dark:hover:outline-border rounded-md text-sm text-gray-400 hover:text-gray-600 dark:text-gray-500 dark:hover:text-gray-400 transition"
150
+ className={cn(
151
+ "absolute top-2 right-2 p-2 hover:outline hover:outline-border/75 dark:hover:outline-border rounded-md text-sm text-muted-foreground transition",
152
+ showCopy === "hover"
153
+ ? "opacity-0 group-hover:opacity-100 group-hover:bg-zinc-100 group-hover:dark:bg-zinc-700"
154
+ : "bg-zinc-100 dark:bg-zinc-700",
155
+ showCopyText && "flex gap-2 items-center font-medium",
156
+ )}
143
157
  disabled={isCopied}
144
158
  onClick={() => {
145
159
  setIsCopied(true);
@@ -161,6 +175,7 @@ export const SyntaxHighlight = ({
161
175
  ) : (
162
176
  <CopyIcon size={16} />
163
177
  )}
178
+ {showCopyText && "Copy"}
164
179
  </button>
165
180
  )}
166
181
  </div>
@@ -0,0 +1,3 @@
1
+ import { cn as cnUtil } from "../util/cn.js";
2
+
3
+ export const cn = cnUtil;
@@ -2,8 +2,8 @@ import { MDXComponents } from "mdx/types.js";
2
2
  import { Link } from "react-router";
3
3
  import { Heading } from "../components/Heading.js";
4
4
  import { InlineCode } from "../components/InlineCode.js";
5
- import { SyntaxHighlight } from "../components/SyntaxHighlight.js";
6
5
  import { Callout } from "../ui/Callout.js";
6
+ import { SyntaxHighlight } from "../ui/SyntaxHighlight.js";
7
7
 
8
8
  export type MdxComponentsType = Readonly<MDXComponents> | null | undefined;
9
9
 
@@ -1,12 +0,0 @@
1
- import { type HighlightProps } from "prism-react-renderer";
2
- type SyntaxHighlightProps = {
3
- className?: string;
4
- noBackground?: boolean;
5
- wrapLines?: boolean;
6
- copyable?: boolean;
7
- showLanguageIndicator?: boolean;
8
- language?: string;
9
- title?: string;
10
- } & Omit<HighlightProps, "children" | "language">;
11
- export declare const SyntaxHighlight: ({ copyable, language, title, ...props }: SyntaxHighlightProps) => import("react/jsx-runtime").JSX.Element | null;
12
- export {};
@@ -1 +0,0 @@
1
- {"version":3,"file":"SyntaxHighlight.js","sourceRoot":"","sources":["../../../src/lib/components/SyntaxHighlight.tsx"],"names":[],"mappings":";AAAA,OAAO,EACL,SAAS,EACT,KAAK,EACL,MAAM,GAEP,MAAM,sBAAsB,CAAC;AAE9B,OAAO,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAC;AAEnD,UAAU,CAAC,KAAK,GAAG,KAAK,CAAC;AACzB,mCAAmC;AACnC,KAAK,MAAM,CAAC,sCAAsC,CAAC,CAAC;AACpD,mCAAmC;AACnC,KAAK,MAAM,CAAC,sCAAsC,CAAC,CAAC;AACpD,mCAAmC;AACnC,KAAK,MAAM,CAAC,oCAAoC,CAAC,CAAC;AAClD,mCAAmC;AACnC,KAAK,MAAM,CAAC,sCAAsC,CAAC,CAAC;AACpD,mCAAmC;AACnC,KAAK,MAAM,CAAC,sCAAsC,CAAC,CAAC;AACpD,mCAAmC;AACnC,KAAK,MAAM,CAAC,wCAAwC,CAAC,CAAC;AACtD,mCAAmC;AACnC,KAAK,MAAM,CAAC,4CAA4C,CAAC,CAAC;AAC1D,mCAAmC;AACnC,KAAK,MAAM,CAAC,0CAA0C,CAAC,CAAC;AACxD,mCAAmC;AACnC,KAAK,MAAM,CAAC,4CAA4C,CAAC,CAAC;AAC1D,mCAAmC;AACnC,KAAK,MAAM,CAAC,4CAA4C,CAAC,CAAC;AAE1D,OAAO,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AACvC,OAAO,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC;AACjC,OAAO,EAAE,EAAE,EAAE,MAAM,eAAe,CAAC;AACnC,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAY7C,MAAM,SAAS,GAAG;IAChB,GAAG,EAAE,IAAI;CACgB,CAAC;AAE5B,MAAM,CAAC,MAAM,eAAe,GAAG,CAAC,EAC9B,QAAQ,GAAG,IAAI,EACf,QAAQ,GAAG,OAAO,EAClB,KAAK,EACL,GAAG,KAAK,EACa,EAAE,EAAE;IACzB,MAAM,EAAE,aAAa,EAAE,GAAG,QAAQ,EAAE,CAAC;IACrC,MAAM,CAAC,QAAQ,EAAE,WAAW,CAAC,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC;IAEhD,IAAI,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC;QAChB,OAAO,IAAI,CAAC;IACd,CAAC;IAED,MAAM,cAAc,GAClB,aAAa,KAAK,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC;IAE3D,+DAA+D;IAC/D,MAAM,iBAAiB,GACrB,mEAAmE,CAAC;IAEtE,OAAO,CACL,KAAC,UAAU,IACT,QAAQ,EACN,eAAK,SAAS,EAAC,gBAAgB,aAC5B,KAAK,IAAI,CACR,cAAK,SAAS,EAAC,mFAAmF,YAC/F,KAAK,GACF,CACP,EACD,cACE,SAAS,EAAE,EAAE,CACX,oCAAoC,EACpC,KAAK,CAAC,SAAS,EACf,KAAK,CAAC,YAAY,CAAC,CAAC,CAAC,iBAAiB,CAAC,CAAC,CAAC,iBAAiB,EAC1D,KAAK,CAAC,SAAS,IAAI,iCAAiC,EACpD,KAAK,IAAI,OAAO,CACjB,YAEA,KAAK,CAAC,IAAI,GACP,EACL,KAAK,CAAC,qBAAqB,IAAI,CAC9B,eAAM,SAAS,EAAC,uGAAuG,YACpH,QAAQ,GACJ,CACR,IACG,YAGR,KAAC,SAAS,IACR,KAAK,EAAE,cAAc,EACrB,QAAQ,EAAE,SAAS,CAAC,QAAQ,CAAC,IAAI,QAAQ,KACrC,KAAK,YAER,CAAC,EAAE,SAAS,EAAE,KAAK,EAAE,MAAM,EAAE,YAAY,EAAE,aAAa,EAAE,EAAE,EAAE,CAAC,CAC9D,eAAK,SAAS,EAAC,gBAAgB,aAC5B,KAAK,IAAI,CACR,cAAK,SAAS,EAAC,mFAAmF,YAC/F,KAAK,GACF,CACP,EACD,cACE,SAAS,EAAE,EAAE,CACX,oCAAoC,EACpC,SAAS,EACT,KAAK,CAAC,SAAS,EACf,KAAK,CAAC,YAAY,IAAI,iBAAiB,EACvC,KAAK,CAAC,SAAS,IAAI,iCAAiC,EACpD,KAAK,IAAI,OAAO,CACjB,EACD,KAAK,EAAE,KAAK,YAEX,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,CAAC,EAAE,EAAE,CAAC;wBACvB,oDAAoD;wBACpD,iBAAiB,YAAY,CAAC,EAAE,IAAI,EAAE,CAAC,YACpC,IAAI,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,GAAG,EAAE,EAAE,CAAC;4BACxB,oDAAoD;4BACpD,kBAAoB,aAAa,CAAC,EAAE,KAAK,EAAE,CAAC,IAAjC,GAAG,CAAkC,CACjD,CAAC,IAJM,CAAC,CAKL,CACP,CAAC,GACE,EACL,KAAK,CAAC,qBAAqB,IAAI,CAC9B,eAAM,SAAS,EAAC,uGAAuG,YACpH,QAAQ,GACJ,CACR,EACA,QAAQ,IAAI,CACX,iBACE,IAAI,EAAC,QAAQ,gBACF,WAAW,EACtB,KAAK,EAAC,WAAW,EACjB,SAAS,EAAC,+RAA+R,EACzS,QAAQ,EAAE,QAAQ,EAClB,OAAO,EAAE,GAAG,EAAE;4BACZ,WAAW,CAAC,IAAI,CAAC,CAAC;4BAClB,KAAK,SAAS,CAAC,SAAS,CAAC,SAAS,CAChC,MAAM;iCACH,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,EAAE,OAAO,EAAE,EAAE,EAAE,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;iCACpD,IAAI,CAAC,IAAI,CAAC,CACd,CAAC;4BACF,UAAU,CAAC,GAAG,EAAE,CAAC,WAAW,CAAC,KAAK,CAAC,EAAE,IAAI,CAAC,CAAC;wBAC7C,CAAC,YAEA,QAAQ,CAAC,CAAC,CAAC,CACV,KAAC,SAAS,IACR,SAAS,EAAC,kBAAkB,EAC5B,IAAI,EAAE,EAAE,EACR,WAAW,EAAE,GAAG,EAChB,mBAAmB,SACnB,CACH,CAAC,CAAC,CAAC,CACF,KAAC,QAAQ,IAAC,IAAI,EAAE,EAAE,GAAI,CACvB,GACM,CACV,IACG,CACP,GACS,GACD,CACd,CAAC;AACJ,CAAC,CAAC"}