zudoku 0.0.0-f865d81 → 0.0.0-fb7d300

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 (392) hide show
  1. package/dist/app/demo.js +0 -2
  2. package/dist/app/demo.js.map +1 -1
  3. package/dist/app/entry.client.js +14 -0
  4. package/dist/app/entry.client.js.map +1 -1
  5. package/dist/app/entry.server.js +6 -6
  6. package/dist/app/entry.server.js.map +1 -1
  7. package/dist/app/main.d.ts +1 -1
  8. package/dist/app/main.js +2 -2
  9. package/dist/app/main.js.map +1 -1
  10. package/dist/app/standalone.js +0 -2
  11. package/dist/app/standalone.js.map +1 -1
  12. package/dist/cli/cli.js +1 -2
  13. package/dist/cli/cli.js.map +1 -1
  14. package/dist/codegen.d.ts +3 -0
  15. package/dist/codegen.js +45 -0
  16. package/dist/codegen.js.map +1 -0
  17. package/dist/config/validators/InputSidebarSchema.d.ts +10 -10
  18. package/dist/config/validators/validate.d.ts +125 -114
  19. package/dist/config/validators/validate.js +6 -5
  20. package/dist/config/validators/validate.js.map +1 -1
  21. package/dist/index.d.ts +2 -2
  22. package/dist/index.js +1 -1
  23. package/dist/index.js.map +1 -1
  24. package/dist/lib/authentication/AuthenticationPlugin.d.ts +4 -2
  25. package/dist/lib/authentication/AuthenticationPlugin.js +3 -0
  26. package/dist/lib/authentication/AuthenticationPlugin.js.map +1 -1
  27. package/dist/lib/authentication/authentication.d.ts +3 -3
  28. package/dist/lib/authentication/hook.d.ts +5 -4
  29. package/dist/lib/authentication/hook.js +1 -3
  30. package/dist/lib/authentication/hook.js.map +1 -1
  31. package/dist/lib/authentication/providers/auth0.js +12 -11
  32. package/dist/lib/authentication/providers/auth0.js.map +1 -1
  33. package/dist/lib/authentication/providers/openid.d.ts +0 -1
  34. package/dist/lib/authentication/providers/openid.js +11 -26
  35. package/dist/lib/authentication/providers/openid.js.map +1 -1
  36. package/dist/lib/authentication/state.d.ts +25 -4
  37. package/dist/lib/authentication/state.js +28 -3
  38. package/dist/lib/authentication/state.js.map +1 -1
  39. package/dist/lib/authentication/use-broadcast/shared.d.ts +48 -0
  40. package/dist/lib/authentication/use-broadcast/shared.js +243 -0
  41. package/dist/lib/authentication/use-broadcast/shared.js.map +1 -0
  42. package/dist/lib/authentication/use-broadcast/useBroadcast.d.ts +24 -0
  43. package/dist/lib/authentication/use-broadcast/useBroadcast.js +106 -0
  44. package/dist/lib/authentication/use-broadcast/useBroadcast.js.map +1 -0
  45. package/dist/lib/components/Bootstrap.d.ts +3 -1
  46. package/dist/lib/components/Bootstrap.js +10 -4
  47. package/dist/lib/components/Bootstrap.js.map +1 -1
  48. package/dist/lib/components/ClientOnly.d.ts +4 -2
  49. package/dist/lib/components/ClientOnly.js +1 -1
  50. package/dist/lib/components/ClientOnly.js.map +1 -1
  51. package/dist/lib/components/DeveloperHint.js +2 -1
  52. package/dist/lib/components/DeveloperHint.js.map +1 -1
  53. package/dist/lib/components/Header.js +16 -10
  54. package/dist/lib/components/Header.js.map +1 -1
  55. package/dist/lib/components/Heading.d.ts +1 -1
  56. package/dist/lib/components/Layout.js +12 -4
  57. package/dist/lib/components/Layout.js.map +1 -1
  58. package/dist/lib/components/MobileTopNavigation.js +6 -7
  59. package/dist/lib/components/MobileTopNavigation.js.map +1 -1
  60. package/dist/lib/components/SyntaxHighlight.js +16 -12
  61. package/dist/lib/components/SyntaxHighlight.js.map +1 -1
  62. package/dist/lib/components/ThemeSwitch.d.ts +1 -0
  63. package/dist/lib/components/ThemeSwitch.js +13 -0
  64. package/dist/lib/components/ThemeSwitch.js.map +1 -0
  65. package/dist/lib/components/TopNavigation.d.ts +2 -0
  66. package/dist/lib/components/TopNavigation.js +13 -7
  67. package/dist/lib/components/TopNavigation.js.map +1 -1
  68. package/dist/lib/components/{DevPortal.d.ts → Zudoku.d.ts} +3 -3
  69. package/dist/lib/components/{DevPortal.js → Zudoku.js} +13 -14
  70. package/dist/lib/components/Zudoku.js.map +1 -0
  71. package/dist/lib/components/context/ZudokuContext.d.ts +7 -7
  72. package/dist/lib/components/context/ZudokuContext.js +8 -13
  73. package/dist/lib/components/context/ZudokuContext.js.map +1 -1
  74. package/dist/lib/components/context/ZudokuProvider.d.ts +2 -2
  75. package/dist/lib/components/context/ZudokuProvider.js.map +1 -1
  76. package/dist/lib/components/index.d.ts +18 -10
  77. package/dist/lib/components/index.js +2 -3
  78. package/dist/lib/components/index.js.map +1 -1
  79. package/dist/lib/components/navigation/Sidebar.js +1 -1
  80. package/dist/lib/components/navigation/Sidebar.js.map +1 -1
  81. package/dist/lib/components/navigation/utils.js +2 -2
  82. package/dist/lib/components/navigation/utils.js.map +1 -1
  83. package/dist/lib/core/{DevPortalContext.d.ts → ZudokuContext.d.ts} +3 -7
  84. package/dist/lib/core/{DevPortalContext.js → ZudokuContext.js} +2 -7
  85. package/dist/lib/core/ZudokuContext.js.map +1 -0
  86. package/dist/lib/core/plugins.d.ts +18 -12
  87. package/dist/lib/core/plugins.js.map +1 -1
  88. package/dist/lib/errors/ErrorAlert.js +1 -1
  89. package/dist/lib/errors/ErrorAlert.js.map +1 -1
  90. package/dist/lib/oas/graphql/index.js +4 -4
  91. package/dist/lib/oas/graphql/index.js.map +1 -1
  92. package/dist/lib/oas/parser/upgrade/index.js +3 -1
  93. package/dist/lib/oas/parser/upgrade/index.js.map +1 -1
  94. package/dist/lib/plugins/api-keys/index.d.ts +9 -9
  95. package/dist/lib/plugins/api-keys/index.js +3 -0
  96. package/dist/lib/plugins/api-keys/index.js.map +1 -1
  97. package/dist/lib/plugins/custom-pages/index.d.ts +2 -2
  98. package/dist/lib/plugins/custom-pages/index.js.map +1 -1
  99. package/dist/lib/plugins/markdown/index.d.ts +2 -2
  100. package/dist/lib/plugins/markdown/index.js.map +1 -1
  101. package/dist/lib/plugins/openapi/CollapsibleCode.d.ts +5 -0
  102. package/dist/lib/plugins/openapi/CollapsibleCode.js +24 -0
  103. package/dist/lib/plugins/openapi/CollapsibleCode.js.map +1 -0
  104. package/dist/lib/plugins/openapi/ColorizedParam.js +13 -9
  105. package/dist/lib/plugins/openapi/ColorizedParam.js.map +1 -1
  106. package/dist/lib/plugins/openapi/Endpoint.d.ts +1 -1
  107. package/dist/lib/plugins/openapi/Endpoint.js +5 -9
  108. package/dist/lib/plugins/openapi/Endpoint.js.map +1 -1
  109. package/dist/lib/plugins/openapi/OperationList.d.ts +2 -2
  110. package/dist/lib/plugins/openapi/OperationList.js +21 -22
  111. package/dist/lib/plugins/openapi/OperationList.js.map +1 -1
  112. package/dist/lib/plugins/openapi/ParameterListItem.js +6 -1
  113. package/dist/lib/plugins/openapi/ParameterListItem.js.map +1 -1
  114. package/dist/lib/plugins/openapi/RequestBodySidecarBox.js +7 -3
  115. package/dist/lib/plugins/openapi/RequestBodySidecarBox.js.map +1 -1
  116. package/dist/lib/plugins/openapi/ResponsesSidecarBox.js +9 -2
  117. package/dist/lib/plugins/openapi/ResponsesSidecarBox.js.map +1 -1
  118. package/dist/lib/plugins/openapi/Route.d.ts +4 -4
  119. package/dist/lib/plugins/openapi/Route.js +2 -4
  120. package/dist/lib/plugins/openapi/Route.js.map +1 -1
  121. package/dist/lib/plugins/openapi/Sidecar.d.ts +1 -1
  122. package/dist/lib/plugins/openapi/Sidecar.js +35 -33
  123. package/dist/lib/plugins/openapi/Sidecar.js.map +1 -1
  124. package/dist/lib/plugins/openapi/client/GraphQLClient.d.ts +8 -0
  125. package/dist/lib/plugins/openapi/client/GraphQLClient.js +102 -0
  126. package/dist/lib/plugins/openapi/client/GraphQLClient.js.map +1 -0
  127. package/dist/lib/plugins/openapi/client/GraphQLContext.d.ts +7 -0
  128. package/dist/lib/plugins/openapi/client/GraphQLContext.js +5 -0
  129. package/dist/lib/plugins/openapi/client/GraphQLContext.js.map +1 -0
  130. package/dist/lib/plugins/openapi/client/createServer.d.ts +1 -0
  131. package/dist/lib/plugins/openapi/client/useCreateQuery.d.ts +5 -0
  132. package/dist/lib/plugins/openapi/client/useCreateQuery.js +13 -0
  133. package/dist/lib/plugins/openapi/client/useCreateQuery.js.map +1 -0
  134. package/dist/lib/plugins/openapi/client/worker.d.ts +4 -1
  135. package/dist/lib/plugins/openapi/client/worker.js +23 -14
  136. package/dist/lib/plugins/openapi/client/worker.js.map +1 -1
  137. package/dist/lib/plugins/openapi/graphql/fragment-masking.d.ts +3 -3
  138. package/dist/lib/plugins/openapi/graphql/fragment-masking.js +3 -4
  139. package/dist/lib/plugins/openapi/graphql/fragment-masking.js.map +1 -1
  140. package/dist/lib/plugins/openapi/graphql/gql.d.ts +5 -51
  141. package/dist/lib/plugins/openapi/graphql/gql.js +4 -2
  142. package/dist/lib/plugins/openapi/graphql/gql.js.map +1 -1
  143. package/dist/lib/plugins/openapi/graphql/graphql.d.ts +32 -8
  144. package/dist/lib/plugins/openapi/graphql/graphql.js +194 -662
  145. package/dist/lib/plugins/openapi/graphql/graphql.js.map +1 -1
  146. package/dist/lib/plugins/openapi/index.d.ts +2 -2
  147. package/dist/lib/plugins/openapi/index.js +40 -53
  148. package/dist/lib/plugins/openapi/index.js.map +1 -1
  149. package/dist/lib/plugins/openapi/schema/SchemaView.js +2 -1
  150. package/dist/lib/plugins/openapi/schema/SchemaView.js.map +1 -1
  151. package/dist/lib/plugins/openapi/util/generateSchemaExample.d.ts +0 -1
  152. package/dist/lib/plugins/openapi/util/generateSchemaExample.js +25 -36
  153. package/dist/lib/plugins/openapi/util/generateSchemaExample.js.map +1 -1
  154. package/dist/lib/plugins/openapi-worker.d.ts +1 -1
  155. package/dist/lib/plugins/openapi-worker.js +7 -1
  156. package/dist/lib/plugins/openapi-worker.js.map +1 -1
  157. package/dist/lib/plugins/redirect/index.d.ts +4 -7
  158. package/dist/lib/plugins/redirect/index.js +1 -1
  159. package/dist/lib/plugins/redirect/index.js.map +1 -1
  160. package/dist/lib/plugins/search-inkeep/index.d.ts +2 -2
  161. package/dist/lib/plugins/search-inkeep/index.js.map +1 -1
  162. package/dist/lib/ui/ActionButton.d.ts +4 -0
  163. package/dist/lib/ui/ActionButton.js +10 -0
  164. package/dist/lib/ui/ActionButton.js.map +1 -0
  165. package/dist/lib/util/MdxComponents.d.ts +1 -1
  166. package/dist/lib/util/useIsomorphicLayoutEffect.d.ts +3 -0
  167. package/dist/lib/util/useIsomorphicLayoutEffect.js +4 -0
  168. package/dist/lib/util/useIsomorphicLayoutEffect.js.map +1 -0
  169. package/dist/lib/util/useOnScreen.d.ts +4 -0
  170. package/dist/lib/util/useOnScreen.js +19 -0
  171. package/dist/lib/util/useOnScreen.js.map +1 -0
  172. package/dist/vite/build.js +5 -1
  173. package/dist/vite/build.js.map +1 -1
  174. package/dist/vite/config.d.ts +2 -8
  175. package/dist/vite/config.js +13 -54
  176. package/dist/vite/config.js.map +1 -1
  177. package/dist/vite/html.js +0 -2
  178. package/dist/vite/html.js.map +1 -1
  179. package/dist/vite/output.d.ts +101 -0
  180. package/dist/vite/output.js +33 -0
  181. package/dist/vite/output.js.map +1 -0
  182. package/dist/vite/plugin-component.js +1 -1
  183. package/dist/vite/plugin-component.js.map +1 -1
  184. package/dist/vite/plugin-config.d.ts +2 -3
  185. package/dist/vite/plugin-config.js +2 -3
  186. package/dist/vite/plugin-config.js.map +1 -1
  187. package/dist/vite/plugin-mdx.d.ts +0 -6
  188. package/dist/vite/plugin-mdx.js +3 -2
  189. package/dist/vite/plugin-mdx.js.map +1 -1
  190. package/dist/vite/plugin.js +1 -3
  191. package/dist/vite/plugin.js.map +1 -1
  192. package/dist/vite/prerender.js +3 -2
  193. package/dist/vite/prerender.js.map +1 -1
  194. package/dist/vite/remarkStaticGeneration.d.ts +3 -0
  195. package/dist/vite/remarkStaticGeneration.js +125 -0
  196. package/dist/vite/remarkStaticGeneration.js.map +1 -0
  197. package/lib/{AnchorLink-BbB2q-jx.js → AnchorLink-CDlhr8gL.js} +11 -10
  198. package/lib/{AnchorLink-BbB2q-jx.js.map → AnchorLink-CDlhr8gL.js.map} +1 -1
  199. package/lib/AuthenticationPlugin-D0Em0SwR.js +59 -0
  200. package/lib/{AuthenticationPlugin-C9BHGXlE.js.map → AuthenticationPlugin-D0Em0SwR.js.map} +1 -1
  201. package/lib/Button-jK0EsymC.js +48 -0
  202. package/lib/Button-jK0EsymC.js.map +1 -0
  203. package/lib/{ClientOnly-CVN6leDu.js → ClientOnly-E7hGysn1.js} +4 -4
  204. package/lib/ClientOnly-E7hGysn1.js.map +1 -0
  205. package/lib/Markdown-ievDDhFT.js +15192 -0
  206. package/lib/Markdown-ievDDhFT.js.map +1 -0
  207. package/lib/{MdxPage-DKMH_t0f.js → MdxPage-Bwn-VSsH.js} +5 -5
  208. package/lib/{MdxPage-DKMH_t0f.js.map → MdxPage-Bwn-VSsH.js.map} +1 -1
  209. package/lib/OperationList-BwBl1xrD.js +4691 -0
  210. package/lib/OperationList-BwBl1xrD.js.map +1 -0
  211. package/lib/Route-DlG_HTMu.js +11 -0
  212. package/lib/Route-DlG_HTMu.js.map +1 -0
  213. package/lib/{Select-Bagt3Bme.js → Select-O9ZM3ZgX.js} +7 -7
  214. package/lib/Select-O9ZM3ZgX.js.map +1 -0
  215. package/lib/{Spinner-C6zroowC.js → SidebarBadge-DxFJcJ6V.js} +28 -17
  216. package/lib/SidebarBadge-DxFJcJ6V.js.map +1 -0
  217. package/lib/SlotletProvider-DyomlzGx.js +252 -0
  218. package/lib/SlotletProvider-DyomlzGx.js.map +1 -0
  219. package/lib/Spinner-3cQDBVGr.js +7 -0
  220. package/lib/Spinner-3cQDBVGr.js.map +1 -0
  221. package/lib/SyntaxHighlight-DkLOsjHS.js +2983 -0
  222. package/lib/SyntaxHighlight-DkLOsjHS.js.map +1 -0
  223. package/lib/assets/{worker-Bf8vjASY.js → worker-CPsGZsve.js} +565 -561
  224. package/lib/assets/{worker-Bf8vjASY.js.map → worker-CPsGZsve.js.map} +1 -1
  225. package/lib/context-D1nXWxm7.js +22 -0
  226. package/lib/context-D1nXWxm7.js.map +1 -0
  227. package/lib/createServer-DK-g7kbB.js +16089 -0
  228. package/lib/createServer-DK-g7kbB.js.map +1 -0
  229. package/lib/{hook-sn0zMTkE.js → hook-hEqe7fPB.js} +12 -14
  230. package/lib/hook-hEqe7fPB.js.map +1 -0
  231. package/lib/index-Czzd9rjU.js +899 -0
  232. package/lib/index-Czzd9rjU.js.map +1 -0
  233. package/lib/index-DNxQ_rCt.js +1273 -0
  234. package/lib/index-DNxQ_rCt.js.map +1 -0
  235. package/lib/index-Yn8c3UWE.js +921 -0
  236. package/lib/index-Yn8c3UWE.js.map +1 -0
  237. package/lib/{router-BsfSoK2j.js → router-lfyopgBI.js} +23 -23
  238. package/lib/{router-BsfSoK2j.js.map → router-lfyopgBI.js.map} +1 -1
  239. package/lib/state-tsXBLONe.js +203 -0
  240. package/lib/{state-CsuHT8ZO.js.map → state-tsXBLONe.js.map} +1 -1
  241. package/lib/ui/ActionButton.js +25 -0
  242. package/lib/ui/ActionButton.js.map +1 -0
  243. package/lib/useExposedProps-CTPtylCV.js +10 -0
  244. package/lib/{useExposedProps-ChOIUaS4.js.map → useExposedProps-CTPtylCV.js.map} +1 -1
  245. package/lib/{ZudokuContext-BKXGJTmu.js → utils-DcpDOncX.js} +242 -246
  246. package/lib/utils-DcpDOncX.js.map +1 -0
  247. package/lib/zudoku.auth-auth0.js +24 -18
  248. package/lib/zudoku.auth-auth0.js.map +1 -1
  249. package/lib/zudoku.auth-clerk.js +2 -2
  250. package/lib/zudoku.auth-openid.js +124 -138
  251. package/lib/zudoku.auth-openid.js.map +1 -1
  252. package/lib/zudoku.components.js +1291 -1119
  253. package/lib/zudoku.components.js.map +1 -1
  254. package/lib/zudoku.openapi-worker.js +10 -16336
  255. package/lib/zudoku.openapi-worker.js.map +1 -1
  256. package/lib/zudoku.plugin-api-keys.js +41 -39
  257. package/lib/zudoku.plugin-api-keys.js.map +1 -1
  258. package/lib/zudoku.plugin-custom-pages.js +2 -2
  259. package/lib/zudoku.plugin-custom-pages.js.map +1 -1
  260. package/lib/zudoku.plugin-markdown.js +1 -1
  261. package/lib/zudoku.plugin-markdown.js.map +1 -1
  262. package/lib/zudoku.plugin-openapi.js +5 -9
  263. package/lib/zudoku.plugin-openapi.js.map +1 -1
  264. package/lib/zudoku.plugin-redirect.js +2 -2
  265. package/lib/zudoku.plugin-redirect.js.map +1 -1
  266. package/lib/zudoku.plugin-search-inkeep.js +1 -1
  267. package/lib/zudoku.plugin-search-inkeep.js.map +1 -1
  268. package/package.json +15 -5
  269. package/src/app/demo.tsx +0 -3
  270. package/src/app/entry.client.tsx +14 -0
  271. package/src/app/entry.server.tsx +59 -53
  272. package/src/app/main.css +1 -1
  273. package/src/app/main.tsx +4 -4
  274. package/src/app/standalone.tsx +0 -3
  275. package/src/lib/authentication/AuthenticationPlugin.tsx +4 -1
  276. package/src/lib/authentication/authentication.ts +3 -3
  277. package/src/lib/authentication/hook.ts +1 -3
  278. package/src/lib/authentication/providers/auth0.tsx +17 -11
  279. package/src/lib/authentication/providers/openid.tsx +12 -30
  280. package/src/lib/authentication/state.ts +50 -9
  281. package/{LICENSE.md → src/lib/authentication/use-broadcast/LICENSE.md} +2 -2
  282. package/src/lib/authentication/use-broadcast/shared.ts +372 -0
  283. package/src/lib/authentication/use-broadcast/useBroadcast.ts +146 -0
  284. package/src/lib/components/Bootstrap.tsx +36 -14
  285. package/src/lib/components/ClientOnly.tsx +6 -3
  286. package/src/lib/components/DeveloperHint.tsx +6 -1
  287. package/src/lib/components/Header.tsx +68 -40
  288. package/src/lib/components/Layout.tsx +49 -37
  289. package/src/lib/components/MobileTopNavigation.tsx +15 -18
  290. package/src/lib/components/SyntaxHighlight.tsx +81 -46
  291. package/src/lib/components/ThemeSwitch.tsx +26 -0
  292. package/src/lib/components/TopNavigation.tsx +27 -19
  293. package/src/lib/components/Zudoku.tsx +108 -0
  294. package/src/lib/components/context/ZudokuContext.ts +11 -16
  295. package/src/lib/components/context/ZudokuProvider.tsx +2 -2
  296. package/src/lib/components/index.ts +2 -3
  297. package/src/lib/components/navigation/Sidebar.tsx +3 -3
  298. package/src/lib/components/navigation/utils.ts +2 -2
  299. package/src/lib/core/{DevPortalContext.ts → ZudokuContext.ts} +3 -11
  300. package/src/lib/core/plugins.ts +20 -16
  301. package/src/lib/errors/ErrorAlert.tsx +2 -1
  302. package/src/lib/oas/graphql/index.ts +4 -4
  303. package/src/lib/oas/parser/upgrade/index.ts +3 -1
  304. package/src/lib/plugins/api-keys/index.tsx +12 -9
  305. package/src/lib/plugins/custom-pages/index.tsx +2 -2
  306. package/src/lib/plugins/markdown/index.tsx +2 -2
  307. package/src/lib/plugins/openapi/CollapsibleCode.tsx +80 -0
  308. package/src/lib/plugins/openapi/ColorizedParam.tsx +23 -14
  309. package/src/lib/plugins/openapi/Endpoint.tsx +5 -10
  310. package/src/lib/plugins/openapi/OperationList.tsx +20 -40
  311. package/src/lib/plugins/openapi/ParameterListItem.tsx +37 -31
  312. package/src/lib/plugins/openapi/RequestBodySidecarBox.tsx +18 -13
  313. package/src/lib/plugins/openapi/ResponsesSidecarBox.tsx +17 -12
  314. package/src/lib/plugins/openapi/Route.tsx +11 -12
  315. package/src/lib/plugins/openapi/Sidecar.tsx +73 -59
  316. package/src/lib/plugins/openapi/client/GraphQLClient.tsx +140 -0
  317. package/src/lib/plugins/openapi/client/GraphQLContext.tsx +16 -0
  318. package/src/lib/plugins/openapi/client/createServer.ts +2 -0
  319. package/src/lib/plugins/openapi/client/useCreateQuery.ts +18 -0
  320. package/src/lib/plugins/openapi/client/worker.ts +38 -24
  321. package/src/lib/plugins/openapi/graphql/fragment-masking.ts +11 -18
  322. package/src/lib/plugins/openapi/graphql/gql.ts +10 -27
  323. package/src/lib/plugins/openapi/graphql/graphql.ts +233 -665
  324. package/src/lib/plugins/openapi/index.tsx +42 -67
  325. package/src/lib/plugins/openapi/schema/SchemaView.tsx +5 -2
  326. package/src/lib/plugins/openapi/util/generateSchemaExample.ts +28 -42
  327. package/src/lib/plugins/openapi-worker.ts +11 -1
  328. package/src/lib/plugins/redirect/index.tsx +5 -9
  329. package/src/lib/plugins/search-inkeep/index.tsx +2 -2
  330. package/src/lib/ui/ActionButton.tsx +28 -0
  331. package/src/lib/util/useIsomorphicLayoutEffect.ts +5 -0
  332. package/src/lib/util/useOnScreen.ts +32 -0
  333. package/dist/lib/components/DevPortal.js.map +0 -1
  334. package/dist/lib/components/context/ThemeContext.d.ts +0 -2
  335. package/dist/lib/components/context/ThemeContext.js +0 -7
  336. package/dist/lib/components/context/ThemeContext.js.map +0 -1
  337. package/dist/lib/components/context/ThemeProvider.d.ts +0 -4
  338. package/dist/lib/components/context/ThemeProvider.js +0 -23
  339. package/dist/lib/components/context/ThemeProvider.js.map +0 -1
  340. package/dist/lib/core/DevPortalContext.js.map +0 -1
  341. package/dist/lib/plugins/openapi/client/createMemoryClient.d.ts +0 -12
  342. package/dist/lib/plugins/openapi/client/createMemoryClient.js +0 -46
  343. package/dist/lib/plugins/openapi/client/createMemoryClient.js.map +0 -1
  344. package/dist/lib/plugins/openapi/client/createWorkerClient.d.ts +0 -10
  345. package/dist/lib/plugins/openapi/client/createWorkerClient.js +0 -61
  346. package/dist/lib/plugins/openapi/client/createWorkerClient.js.map +0 -1
  347. package/dist/lib/plugins/openapi/client/interfaces.d.ts +0 -4
  348. package/dist/lib/plugins/openapi/client/interfaces.js +0 -2
  349. package/dist/lib/plugins/openapi/client/interfaces.js.map +0 -1
  350. package/dist/lib/themeToggle.d.ts +0 -1
  351. package/dist/lib/themeToggle.js +0 -7
  352. package/dist/lib/themeToggle.js.map +0 -1
  353. package/dist/lib/util/createWaitForNotify.d.ts +0 -1
  354. package/dist/lib/util/createWaitForNotify.js +0 -15
  355. package/dist/lib/util/createWaitForNotify.js.map +0 -1
  356. package/dist/vite/plugin-html-transform.d.ts +0 -2
  357. package/dist/vite/plugin-html-transform.js +0 -15
  358. package/dist/vite/plugin-html-transform.js.map +0 -1
  359. package/lib/AuthenticationPlugin-C9BHGXlE.js +0 -55
  360. package/lib/ClientOnly-CVN6leDu.js.map +0 -1
  361. package/lib/DeveloperHint-DHdLXGHA.js +0 -16
  362. package/lib/DeveloperHint-DHdLXGHA.js.map +0 -1
  363. package/lib/Markdown-BDcCAWwm.js +0 -18059
  364. package/lib/Markdown-BDcCAWwm.js.map +0 -1
  365. package/lib/OperationList-Tj7ubW_t.js +0 -604
  366. package/lib/OperationList-Tj7ubW_t.js.map +0 -1
  367. package/lib/Route-C3DGB6OS.js +0 -13
  368. package/lib/Route-C3DGB6OS.js.map +0 -1
  369. package/lib/Select-Bagt3Bme.js.map +0 -1
  370. package/lib/SlotletProvider-Da7eFgd2.js +0 -241
  371. package/lib/SlotletProvider-Da7eFgd2.js.map +0 -1
  372. package/lib/Spinner-C6zroowC.js.map +0 -1
  373. package/lib/StaggeredRender-DDHSzQKE.js +0 -17
  374. package/lib/StaggeredRender-DDHSzQKE.js.map +0 -1
  375. package/lib/ZudokuContext-BKXGJTmu.js.map +0 -1
  376. package/lib/hook-sn0zMTkE.js.map +0 -1
  377. package/lib/index-AjWCJNGC.js +0 -5690
  378. package/lib/index-AjWCJNGC.js.map +0 -1
  379. package/lib/index-CRo94sKK.js +0 -1783
  380. package/lib/index-CRo94sKK.js.map +0 -1
  381. package/lib/state-CsuHT8ZO.js +0 -183
  382. package/lib/urql-core-KJnLL26g.js +0 -1455
  383. package/lib/urql-core-KJnLL26g.js.map +0 -1
  384. package/lib/useExposedProps-ChOIUaS4.js +0 -9
  385. package/src/lib/components/DevPortal.tsx +0 -111
  386. package/src/lib/components/context/ThemeContext.tsx +0 -8
  387. package/src/lib/components/context/ThemeProvider.tsx +0 -27
  388. package/src/lib/plugins/openapi/client/createMemoryClient.ts +0 -51
  389. package/src/lib/plugins/openapi/client/createWorkerClient.ts +0 -75
  390. package/src/lib/plugins/openapi/client/interfaces.ts +0 -5
  391. package/src/lib/themeToggle.ts +0 -7
  392. package/src/lib/util/createWaitForNotify.ts +0 -18
@@ -1,9 +1,9 @@
1
- import { MoonStarIcon, SunIcon } from "lucide-react";
2
1
  import { memo } from "react";
3
2
  import { Link } from "react-router-dom";
3
+ import { Button } from "zudoku/ui/Button.js";
4
+ import { Skeleton } from "zudoku/ui/Skeleton.js";
4
5
  import { useAuth } from "../authentication/hook.js";
5
6
  import { isProfileMenuPlugin, ProfileNavigationItem } from "../core/plugins.js";
6
- import { Button } from "../ui/Button.js";
7
7
  import {
8
8
  DropdownMenu,
9
9
  DropdownMenuContent,
@@ -16,14 +16,14 @@ import {
16
16
  DropdownMenuSubTrigger,
17
17
  DropdownMenuTrigger,
18
18
  } from "../ui/DropdownMenu.js";
19
- import { cn } from "../util/cn.js";
20
19
  import { joinPath } from "../util/joinPath.js";
21
20
  import { Banner } from "./Banner.js";
22
- import { useTheme } from "./context/ThemeContext.js";
21
+ import { ClientOnly } from "./ClientOnly.js";
23
22
  import { useZudoku } from "./context/ZudokuContext.js";
24
23
  import { MobileTopNavigation } from "./MobileTopNavigation.js";
25
24
  import { Search } from "./Search.js";
26
25
  import { Slotlet } from "./SlotletProvider.js";
26
+ import { ThemeSwitch } from "./ThemeSwitch.js";
27
27
  import { TopNavigation } from "./TopNavigation.js";
28
28
 
29
29
  const RecursiveMenu = ({ item }: { item: ProfileNavigationItem }) => {
@@ -41,14 +41,18 @@ const RecursiveMenu = ({ item }: { item: ProfileNavigationItem }) => {
41
41
  </DropdownMenuSub>
42
42
  ) : (
43
43
  <Link to={item.path ?? ""}>
44
- <DropdownMenuItem key={item.label}>{item.label}</DropdownMenuItem>
44
+ <DropdownMenuItem key={item.label} className="flex gap-2">
45
+ {item.icon && (
46
+ <item.icon size={16} strokeWidth={1} absoluteStrokeWidth />
47
+ )}
48
+ {item.label}
49
+ </DropdownMenuItem>
45
50
  </Link>
46
51
  );
47
52
  };
48
53
 
49
54
  export const Header = memo(function HeaderInner() {
50
55
  const auth = useAuth();
51
- const [isDark, toggleTheme] = useTheme();
52
56
  const { isAuthenticated, profile, isAuthEnabled } = useAuth();
53
57
  const context = useZudoku();
54
58
  const { page, plugins } = context;
@@ -56,9 +60,7 @@ export const Header = memo(function HeaderInner() {
56
60
  const accountItems = plugins
57
61
  .filter((p) => isProfileMenuPlugin(p))
58
62
  .flatMap((p) => p.getProfileMenuItems(context))
59
- .map((i) => <RecursiveMenu key={i.label} item={i} />);
60
-
61
- const ThemeIcon = isDark ? MoonStarIcon : SunIcon;
63
+ .sort((i) => i.weight ?? 0);
62
64
 
63
65
  return (
64
66
  <header className="sticky lg:top-0 z-10 bg-background/80 backdrop-blur w-full">
@@ -81,7 +83,7 @@ export const Header = memo(function HeaderInner() {
81
83
  }
82
84
  alt={page.logo.alt ?? page.pageTitle}
83
85
  style={{ width: page.logo.width }}
84
- className={cn("h-10", isDark && "hidden")}
86
+ className="h-10 dark:hidden"
85
87
  loading="lazy"
86
88
  />
87
89
  <img
@@ -95,7 +97,7 @@ export const Header = memo(function HeaderInner() {
95
97
  }
96
98
  alt={page.logo.alt ?? page.pageTitle}
97
99
  style={{ width: page.logo.width }}
98
- className={cn("h-10", !isDark && "hidden")}
100
+ className="h-10 hidden dark:block"
99
101
  loading="lazy"
100
102
  />
101
103
  </>
@@ -114,36 +116,62 @@ export const Header = memo(function HeaderInner() {
114
116
  <MobileTopNavigation />
115
117
  <div className="hidden lg:flex items-center justify-self-end text-sm gap-2">
116
118
  <Slotlet name="head-navigation-start" />
117
- {isAuthEnabled && !isAuthenticated ? (
118
- <Button variant="ghost" onClick={() => auth.login()}>
119
- Login
120
- </Button>
121
- ) : (
122
- accountItems.length > 0 && (
123
- <DropdownMenu modal={false}>
124
- <DropdownMenuTrigger asChild>
125
- <Button variant="ghost">
126
- {profile?.email ? `${profile.email}` : "My Account"}
127
- </Button>
128
- </DropdownMenuTrigger>
129
- <DropdownMenuContent className="w-56">
130
- <DropdownMenuLabel>My Account</DropdownMenuLabel>
131
- <DropdownMenuSeparator />
132
- {accountItems}
133
- </DropdownMenuContent>
134
- </DropdownMenu>
135
- )
119
+ {isAuthEnabled && (
120
+ <ClientOnly
121
+ fallback={<Skeleton className="rounded h-5 w-24 mr-4" />}
122
+ >
123
+ {!isAuthenticated ? (
124
+ <Button variant="ghost" onClick={() => auth.login()}>
125
+ Login
126
+ </Button>
127
+ ) : (
128
+ Object.values(accountItems).length > 0 && (
129
+ <DropdownMenu modal={false}>
130
+ <DropdownMenuTrigger asChild>
131
+ <Button variant="ghost">
132
+ {profile?.name ? `${profile.name}` : "My Account"}
133
+ </Button>
134
+ </DropdownMenuTrigger>
135
+ <DropdownMenuContent className="w-56">
136
+ <DropdownMenuLabel>
137
+ {profile?.name ? `${profile.name}` : "My Account"}
138
+ {profile?.email && (
139
+ <div className="font-normal text-muted-foreground">
140
+ {profile.email}
141
+ </div>
142
+ )}
143
+ </DropdownMenuLabel>
144
+ {accountItems.filter((i) => i.category === "top")
145
+ .length > 0 && <DropdownMenuSeparator />}
146
+ {accountItems
147
+ .filter((i) => i.category === "top")
148
+ .map((i) => (
149
+ <RecursiveMenu key={i.label} item={i} />
150
+ ))}
151
+ {accountItems.filter(
152
+ (i) => !i.category || i.category === "middle",
153
+ ).length > 0 && <DropdownMenuSeparator />}
154
+ {accountItems
155
+ .filter(
156
+ (i) => !i.category || i.category === "middle",
157
+ )
158
+ .map((i) => (
159
+ <RecursiveMenu key={i.label} item={i} />
160
+ ))}
161
+ {accountItems.filter((i) => i.category === "bottom")
162
+ .length > 0 && <DropdownMenuSeparator />}
163
+ {accountItems
164
+ .filter((i) => i.category === "bottom")
165
+ .map((i) => (
166
+ <RecursiveMenu key={i.label} item={i} />
167
+ ))}
168
+ </DropdownMenuContent>
169
+ </DropdownMenu>
170
+ )
171
+ )}
172
+ </ClientOnly>
136
173
  )}
137
- <button
138
- type="button"
139
- aria-label={
140
- isDark ? "Switch to light mode" : "Switch to dark mode"
141
- }
142
- className="cursor-pointer hover:bg-secondary p-2.5 -m-2.5 rounded-full"
143
- onClick={toggleTheme}
144
- >
145
- <ThemeIcon size={18} />
146
- </button>
174
+ <ThemeSwitch />
147
175
  <Slotlet name="head-navigation-end" />
148
176
  </div>
149
177
  </div>
@@ -1,7 +1,8 @@
1
1
  import { Helmet } from "@zudoku/react-helmet-async";
2
2
  import { PanelLeftIcon } from "lucide-react";
3
3
  import { Suspense, useEffect, useRef, type ReactNode } from "react";
4
- import { Outlet, useLocation } from "react-router-dom";
4
+ import { Outlet, useLocation, useNavigation } from "react-router-dom";
5
+ import { useSpinDelay } from "spin-delay";
5
6
  import { Drawer, DrawerTrigger } from "../ui/Drawer.js";
6
7
  import { cn } from "../util/cn.js";
7
8
  import { useScrollToAnchor } from "../util/useScrollToAnchor.js";
@@ -13,6 +14,12 @@ import { Sidebar } from "./navigation/Sidebar.js";
13
14
  import { Slotlet } from "./SlotletProvider.js";
14
15
  import { Spinner } from "./Spinner.js";
15
16
 
17
+ const LoadingFallback = () => (
18
+ <main className="grid h-[calc(100vh-var(--header-height))] place-items-center">
19
+ <Spinner />
20
+ </main>
21
+ );
22
+
16
23
  export const Layout = ({ children }: { children?: ReactNode }) => {
17
24
  const location = useLocation();
18
25
  const { setActiveAnchor } = useViewportAnchor();
@@ -25,7 +32,7 @@ export const Layout = ({ children }: { children?: ReactNode }) => {
25
32
 
26
33
  useEffect(() => {
27
34
  // Initialize the authentication plugin
28
- authentication?.pageLoad?.();
35
+ authentication?.onPageLoad?.();
29
36
  }, [authentication]);
30
37
 
31
38
  useEffect(() => {
@@ -36,6 +43,13 @@ export const Layout = ({ children }: { children?: ReactNode }) => {
36
43
  previousLocationPath.current = location.pathname;
37
44
  }, [location.pathname, setActiveAnchor]);
38
45
 
46
+ // Page transition is happening: https://reactrouter.com/start/framework/pending-ui#global-pending-navigation
47
+ const isNavigating = Boolean(useNavigation().location);
48
+ const showSpinner = useSpinDelay(isNavigating, {
49
+ delay: 300,
50
+ minDuration: 500,
51
+ });
52
+
39
53
  return (
40
54
  <>
41
55
  {import.meta.env.MODE === "standalone" && (
@@ -52,41 +66,39 @@ export const Layout = ({ children }: { children?: ReactNode }) => {
52
66
  <Slotlet name="layout-after-head" />
53
67
 
54
68
  <div className="w-full max-w-screen-2xl mx-auto px-10 lg:px-12">
55
- <Suspense
56
- fallback={
57
- <main className="grid h-[calc(100vh-var(--header-height))] place-items-center">
58
- <Spinner />
59
- </main>
60
- }
61
- >
62
- <Drawer direction="left">
63
- <Sidebar />
64
- <div
65
- className={cn(
66
- "lg:hidden -mx-10 px-10 py-2 sticky bg-background/80 backdrop-blur z-10 top-0 left-0 right-0 border-b",
67
- "peer-data-[navigation=false]:hidden",
68
- )}
69
- >
70
- <DrawerTrigger className="flex items-center gap-2">
71
- <PanelLeftIcon size={16} strokeWidth={1.5} />
72
- <span className="text-sm">Menu</span>
73
- </DrawerTrigger>
74
- </div>
75
- <main
76
- className={cn(
77
- "h-full dark:border-white/10 translate-x-0",
78
- "lg:overflow-visible",
79
- // This works in tandem with the `SidebarWrapper` component
80
- "lg:peer-data-[navigation=true]:w-[calc(100%-var(--side-nav-width))]",
81
- "lg:peer-data-[navigation=true]:translate-x-[--side-nav-width] lg:peer-data-[navigation=true]:pl-12",
82
- )}
83
- >
84
- <Slotlet name="zudoku-before-content" />
85
- {children ?? <Outlet />}
86
- <Slotlet name="zudoku-after-content" />
87
- </main>
88
- </Drawer>
89
- </Suspense>
69
+ {showSpinner ? (
70
+ <LoadingFallback />
71
+ ) : (
72
+ <Suspense fallback={<LoadingFallback />}>
73
+ <Drawer direction="left">
74
+ <Sidebar />
75
+ <div
76
+ className={cn(
77
+ "lg:hidden -mx-10 px-10 py-2 sticky bg-background/80 backdrop-blur z-10 top-0 left-0 right-0 border-b",
78
+ "peer-data-[navigation=false]:hidden",
79
+ )}
80
+ >
81
+ <DrawerTrigger className="flex items-center gap-2">
82
+ <PanelLeftIcon size={16} strokeWidth={1.5} />
83
+ <span className="text-sm">Menu</span>
84
+ </DrawerTrigger>
85
+ </div>
86
+ <main
87
+ className={cn(
88
+ "h-full dark:border-white/10 translate-x-0",
89
+ "lg:overflow-visible",
90
+ // This works in tandem with the `SidebarWrapper` component
91
+ "lg:peer-data-[navigation=true]:w-[calc(100%-var(--side-nav-width))]",
92
+ "lg:peer-data-[navigation=true]:translate-x-[--side-nav-width] lg:peer-data-[navigation=true]:pl-12",
93
+ )}
94
+ >
95
+ <Slotlet name="zudoku-before-content" />
96
+ {children ?? <Outlet />}
97
+ <Slotlet name="zudoku-after-content" />
98
+ </main>
99
+ </Drawer>
100
+ </Suspense>
101
+ )}
90
102
  </div>
91
103
  </>
92
104
  );
@@ -1,25 +1,29 @@
1
1
  import { VisuallyHidden } from "@radix-ui/react-visually-hidden";
2
- import { cx } from "class-variance-authority";
3
2
  import { MenuIcon } from "lucide-react";
4
- import { NavLink } from "react-router-dom";
3
+ import { useState } from "react";
5
4
  import { useAuth } from "../authentication/hook.js";
6
5
  import {
7
6
  Drawer,
8
- DrawerClose,
9
7
  DrawerContent,
10
8
  DrawerTitle,
11
9
  DrawerTrigger,
12
10
  } from "../ui/Drawer.js";
13
11
  import { useZudoku } from "./context/ZudokuContext.js";
14
12
  import { Search } from "./Search.js";
15
- import { isHiddenItem } from "./TopNavigation.js";
13
+ import { ThemeSwitch } from "./ThemeSwitch.js";
14
+ import { isHiddenItem, TopNavItem } from "./TopNavigation.js";
16
15
 
17
16
  export const MobileTopNavigation = () => {
18
17
  const { topNavigation } = useZudoku();
19
18
  const { isAuthenticated } = useAuth();
19
+ const [drawerOpen, setDrawerOpen] = useState(false);
20
20
 
21
21
  return (
22
- <Drawer direction="right">
22
+ <Drawer
23
+ direction="right"
24
+ open={drawerOpen}
25
+ onOpenChange={(open) => setDrawerOpen(open)}
26
+ >
23
27
  <div className="flex lg:hidden justify-self-end">
24
28
  <DrawerTrigger className="lg:hidden">
25
29
  <MenuIcon size={22} />
@@ -36,21 +40,14 @@ export const MobileTopNavigation = () => {
36
40
  <Search />
37
41
  </div>
38
42
  <ul className="flex flex-col items-center gap-4 p-4">
43
+ <li>
44
+ <ThemeSwitch />
45
+ </li>
39
46
  {topNavigation.filter(isHiddenItem(isAuthenticated)).map((item) => (
40
47
  <li key={item.label}>
41
- <NavLink
42
- className={({ isActive }) =>
43
- cx(
44
- "block font-medium border-b-2",
45
- isActive
46
- ? "border-primary text-foreground"
47
- : "border-transparent text-foreground/75 hover:text-foreground hover:border-accent-foreground/25",
48
- )
49
- }
50
- to={item.id}
51
- >
52
- <DrawerClose>{item.label}</DrawerClose>
53
- </NavLink>
48
+ <button onClick={() => setDrawerOpen(false)}>
49
+ <TopNavItem {...item} />
50
+ </button>
54
51
  </li>
55
52
  ))}
56
53
  </ul>
@@ -33,9 +33,10 @@ void import("prismjs/components/prism-javascript.min.js");
33
33
  // @ts-expect-error This is untyped
34
34
  void import("prismjs/components/prism-typescript.min.js");
35
35
 
36
+ import { useTheme } from "next-themes";
36
37
  import { useState } from "react";
37
38
  import { cn } from "../util/cn.js";
38
- import { useTheme } from "./context/ThemeContext.js";
39
+ import { ClientOnly } from "./ClientOnly.js";
39
40
 
40
41
  type SyntaxHighlightProps = {
41
42
  className?: string;
@@ -55,72 +56,106 @@ export const SyntaxHighlight = ({
55
56
  language = "plain",
56
57
  ...props
57
58
  }: SyntaxHighlightProps) => {
58
- const [isDark] = useTheme();
59
+ const { resolvedTheme } = useTheme();
59
60
  const [isCopied, setIsCopied] = useState(false);
60
61
 
61
62
  if (!props.code) {
62
63
  return null;
63
64
  }
64
65
 
66
+ const highlightTheme =
67
+ resolvedTheme === "dark" ? themes.vsDark : themes.github;
68
+
69
+ // hardcoded values from the themes to avoid color flash in SSR
70
+ const themeColorClasses =
71
+ "bg-[#f6f8fa] text-[#393a34] dark:bg-[#1e1e1e] dark:text-[#9cdcfe]";
72
+
65
73
  return (
66
- <Highlight
67
- theme={isDark ? themes.vsDark : themes.github}
68
- language={remapLang[language] ?? language}
69
- {...props}
70
- >
71
- {({ className, style, tokens, getLineProps, getTokenProps }) => (
74
+ <ClientOnly
75
+ fallback={
72
76
  <div className="relative group">
73
77
  <pre
74
78
  className={cn(
75
79
  "relative scrollbar overflow-x-auto",
76
- className,
77
80
  props.className,
78
- props.noBackground && "!bg-transparent",
81
+ props.noBackground ? "!bg-transparent" : themeColorClasses,
79
82
  props.wrapLines && "whitespace-pre-wrap break-words",
80
83
  )}
81
- style={style}
82
84
  >
83
- {tokens.map((line, i) => (
84
- // eslint-disable-next-line react/no-array-index-key
85
- <div key={i} {...getLineProps({ line })}>
86
- {line.map((token, key) => (
87
- // eslint-disable-next-line react/no-array-index-key
88
- <span key={key} {...getTokenProps({ token })} />
89
- ))}
90
- </div>
91
- ))}
85
+ {props.code}
92
86
  </pre>
93
87
  {props.showLanguageIndicator && (
94
88
  <span className="absolute top-1.5 right-3 text-[11px] font-mono text-muted-foreground transition group-hover:opacity-0">
95
89
  {language}
96
90
  </span>
97
91
  )}
98
- {copyable && (
99
- <button
100
- type="button"
101
- aria-label="Copy code"
102
- title="Copy code"
103
- 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"
104
- disabled={isCopied}
105
- onClick={() => {
106
- setIsCopied(true);
107
- void navigator.clipboard.writeText(
108
- tokens
109
- .map((line) => line.map(({ content }) => content).join(""))
110
- .join("\n"),
111
- );
112
- setTimeout(() => setIsCopied(false), 2000);
113
- }}
114
- >
115
- {isCopied ? (
116
- <CheckIcon className="text-emerald-600" size={16} />
117
- ) : (
118
- <CopyIcon size={16} />
119
- )}
120
- </button>
121
- )}
122
92
  </div>
123
- )}
124
- </Highlight>
93
+ }
94
+ >
95
+ <Highlight
96
+ theme={highlightTheme}
97
+ language={remapLang[language] ?? language}
98
+ {...props}
99
+ >
100
+ {({ className, style, tokens, getLineProps, getTokenProps }) => (
101
+ <div className="relative group">
102
+ <pre
103
+ className={cn(
104
+ "relative scrollbar overflow-x-auto",
105
+ className,
106
+ props.className,
107
+ props.noBackground && "!bg-transparent",
108
+ props.wrapLines && "whitespace-pre-wrap break-words",
109
+ )}
110
+ style={style}
111
+ >
112
+ {tokens.map((line, i) => (
113
+ // eslint-disable-next-line react/no-array-index-key
114
+ <div key={i} {...getLineProps({ line })}>
115
+ {line.map((token, key) => (
116
+ // eslint-disable-next-line react/no-array-index-key
117
+ <span key={key} {...getTokenProps({ token })} />
118
+ ))}
119
+ </div>
120
+ ))}
121
+ </pre>
122
+ {props.showLanguageIndicator && (
123
+ <span className="absolute top-1.5 right-3 text-[11px] font-mono text-muted-foreground transition group-hover:opacity-0">
124
+ {language}
125
+ </span>
126
+ )}
127
+ {copyable && (
128
+ <button
129
+ type="button"
130
+ aria-label="Copy code"
131
+ title="Copy code"
132
+ 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"
133
+ disabled={isCopied}
134
+ onClick={() => {
135
+ setIsCopied(true);
136
+ void navigator.clipboard.writeText(
137
+ tokens
138
+ .map((l) => l.map(({ content }) => content).join(""))
139
+ .join("\n"),
140
+ );
141
+ setTimeout(() => setIsCopied(false), 2000);
142
+ }}
143
+ >
144
+ {isCopied ? (
145
+ <CheckIcon
146
+ className="text-emerald-600"
147
+ size={16}
148
+ strokeWidth={2.5}
149
+ absoluteStrokeWidth
150
+ />
151
+ ) : (
152
+ <CopyIcon size={16} />
153
+ )}
154
+ </button>
155
+ )}
156
+ </div>
157
+ )}
158
+ </Highlight>
159
+ </ClientOnly>
125
160
  );
126
161
  };
@@ -0,0 +1,26 @@
1
+ import { MoonStarIcon, SunIcon } from "lucide-react";
2
+ import { useTheme } from "next-themes";
3
+ import { Button } from "zudoku/ui/Button.js";
4
+ import { ClientOnly } from "./ClientOnly.js";
5
+
6
+ export const ThemeSwitch = () => {
7
+ const { resolvedTheme, setTheme } = useTheme();
8
+ const ThemeIcon = resolvedTheme === "dark" ? MoonStarIcon : SunIcon;
9
+
10
+ return (
11
+ <ClientOnly>
12
+ <Button
13
+ variant="ghost"
14
+ aria-label={
15
+ resolvedTheme === "dark"
16
+ ? "Switch to light mode"
17
+ : "Switch to dark mode"
18
+ }
19
+ className="p-2.5 -m-2.5 rounded-full"
20
+ onClick={() => setTheme(resolvedTheme === "dark" ? "light" : "dark")}
21
+ >
22
+ <ThemeIcon size={18} />
23
+ </Button>
24
+ </ClientOnly>
25
+ );
26
+ };
@@ -1,8 +1,9 @@
1
1
  import { cx } from "class-variance-authority";
2
2
  import { Suspense } from "react";
3
- import { Link } from "react-router-dom";
4
- import { useAuth } from "../authentication/hook.js";
3
+ import { NavLink, useNavigation } from "react-router-dom";
5
4
  import { TopNavigationItem } from "../../config/validators/validate.js";
5
+ import { useAuth } from "../authentication/hook.js";
6
+ import { ZudokuError } from "../util/invariant.js";
6
7
  import { joinPath } from "../util/joinPath.js";
7
8
  import { useCurrentNavigation, useZudoku } from "./context/ZudokuContext.js";
8
9
  import { traverseSidebar } from "./navigation/utils.js";
@@ -32,7 +33,7 @@ export const TopNavigation = () => {
32
33
  <nav className="hidden lg:block border-b text-sm px-12 h-[--top-nav-height]">
33
34
  <ul className="flex flex-row items-center gap-8">
34
35
  {topNavigation.filter(isHiddenItem(isAuthenticated)).map((item) => (
35
- <li key={item.id}>
36
+ <li key={item.id}>
36
37
  <TopNavItem {...item} />
37
38
  </li>
38
39
  ))}
@@ -42,10 +43,16 @@ export const TopNavigation = () => {
42
43
  );
43
44
  };
44
45
 
45
- const TopNavItem = ({ id, label, default: defaultLink }: TopNavigationItem) => {
46
+ export const TopNavItem = ({
47
+ id,
48
+ label,
49
+ default: defaultLink,
50
+ }: TopNavigationItem) => {
46
51
  const { sidebars } = useZudoku();
47
- const nav = useCurrentNavigation();
48
52
  const currentSidebar = sidebars[id];
53
+ const currentNav = useCurrentNavigation();
54
+ const isNavigating = Boolean(useNavigation().location);
55
+ const isActive = currentNav.topNavItem?.id === id && !isNavigating;
49
56
 
50
57
  // TODO: This is a bit of a hack to get the first link in the sidebar
51
58
  // We should really process this when we load the config so we can validate
@@ -60,25 +67,26 @@ const TopNavItem = ({ id, label, default: defaultLink }: TopNavigationItem) => {
60
67
  : joinPath(id));
61
68
 
62
69
  if (!first) {
63
- throw new Error(
64
- `No links found in top navigation for top navigation '${id}'. Check that the sidebar isn't empty or that a default link set.`,
65
- );
70
+ throw new ZudokuError("Page not found.", {
71
+ developerHint: `No links found in top navigation for '${id}'. Check that the sidebar isn't empty or that a default link is set.`,
72
+ });
66
73
  }
67
74
 
68
- // Manually set the active sidebar based on our logic of what is active
69
- const isActive = nav.data.topNavItem?.id === id;
70
-
71
75
  return (
72
- <Link
73
- className={cx(
74
- "block py-3.5 font-medium -mb-px border-b-2",
75
- isActive
76
- ? "border-primary text-foreground"
77
- : "border-transparent text-foreground/75 hover:text-foreground hover:border-accent-foreground/25",
78
- )}
76
+ // We don't use isActive here because it has to be inside the sidebar,
77
+ // the top nav id doesn't necessarily start with the sidebar id
78
+ <NavLink
79
+ className={({ isPending }) =>
80
+ cx(
81
+ "block lg:py-3.5 font-medium -mb-px border-b-2",
82
+ isActive || isPending
83
+ ? "border-primary text-foreground"
84
+ : "border-transparent text-foreground/75 hover:text-foreground hover:border-accent-foreground/25",
85
+ )
86
+ }
79
87
  to={first}
80
88
  >
81
89
  {label}
82
- </Link>
90
+ </NavLink>
83
91
  );
84
92
  };