zudoku 0.0.2-dev.0
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.
- package/cli.js +1 -0
- package/dist/app/DevPortal.d.ts +26 -0
- package/dist/app/DevPortal.js +41 -0
- package/dist/app/DevPortal.js.map +1 -0
- package/dist/app/Heading.d.ts +9 -0
- package/dist/app/Heading.js +27 -0
- package/dist/app/Heading.js.map +1 -0
- package/dist/app/app.d.ts +2 -0
- package/dist/app/app.js +69 -0
- package/dist/app/app.js.map +1 -0
- package/dist/app/authentication/authentication.d.ts +13 -0
- package/dist/app/authentication/authentication.js +2 -0
- package/dist/app/authentication/authentication.js.map +1 -0
- package/dist/app/authentication/clerk.d.ts +5 -0
- package/dist/app/authentication/clerk.js +36 -0
- package/dist/app/authentication/clerk.js.map +1 -0
- package/dist/app/authentication/openid.d.ts +11 -0
- package/dist/app/authentication/openid.js +118 -0
- package/dist/app/authentication/openid.js.map +1 -0
- package/dist/app/components/AnchorLink.d.ts +5 -0
- package/dist/app/components/AnchorLink.js +17 -0
- package/dist/app/components/AnchorLink.js.map +1 -0
- package/dist/app/components/CategoryHeading.d.ts +5 -0
- package/dist/app/components/CategoryHeading.js +6 -0
- package/dist/app/components/CategoryHeading.js.map +1 -0
- package/dist/app/components/DynamicIcon.d.ts +6 -0
- package/dist/app/components/DynamicIcon.js +6 -0
- package/dist/app/components/DynamicIcon.js.map +1 -0
- package/dist/app/components/Header.d.ts +2 -0
- package/dist/app/components/Header.js +15 -0
- package/dist/app/components/Header.js.map +1 -0
- package/dist/app/components/Layout.d.ts +4 -0
- package/dist/app/components/Layout.js +31 -0
- package/dist/app/components/Layout.js.map +1 -0
- package/dist/app/components/Markdown.d.ts +5 -0
- package/dist/app/components/Markdown.js +20 -0
- package/dist/app/components/Markdown.js.map +1 -0
- package/dist/app/components/SyntaxHighlight.d.ts +9 -0
- package/dist/app/components/SyntaxHighlight.js +31 -0
- package/dist/app/components/SyntaxHighlight.js.map +1 -0
- package/dist/app/components/TopNavigation.d.ts +1 -0
- package/dist/app/components/TopNavigation.js +11 -0
- package/dist/app/components/TopNavigation.js.map +1 -0
- package/dist/app/components/context/ComponentsContext.d.ts +10 -0
- package/dist/app/components/context/ComponentsContext.js +11 -0
- package/dist/app/components/context/ComponentsContext.js.map +1 -0
- package/dist/app/components/context/DevPortalProvider.d.ts +10 -0
- package/dist/app/components/context/DevPortalProvider.js +39 -0
- package/dist/app/components/context/DevPortalProvider.js.map +1 -0
- package/dist/app/components/context/PluginSystem.d.ts +1 -0
- package/dist/app/components/context/PluginSystem.js +2 -0
- package/dist/app/components/context/PluginSystem.js.map +1 -0
- package/dist/app/components/context/ThemeContext.d.ts +5 -0
- package/dist/app/components/context/ThemeContext.js +33 -0
- package/dist/app/components/context/ThemeContext.js.map +1 -0
- package/dist/app/components/context/ViewportAnchorContext.d.ts +15 -0
- package/dist/app/components/context/ViewportAnchorContext.js +89 -0
- package/dist/app/components/context/ViewportAnchorContext.js.map +1 -0
- package/dist/app/components/navigation/SideNavigation.d.ts +1 -0
- package/dist/app/components/navigation/SideNavigation.js +11 -0
- package/dist/app/components/navigation/SideNavigation.js.map +1 -0
- package/dist/app/components/navigation/SideNavigationCategory.d.ts +4 -0
- package/dist/app/components/navigation/SideNavigationCategory.js +26 -0
- package/dist/app/components/navigation/SideNavigationCategory.js.map +1 -0
- package/dist/app/components/navigation/SideNavigationItem.d.ts +12 -0
- package/dist/app/components/navigation/SideNavigationItem.js +38 -0
- package/dist/app/components/navigation/SideNavigationItem.js.map +1 -0
- package/dist/app/components/navigation/SideNavigationWrapper.d.ts +4 -0
- package/dist/app/components/navigation/SideNavigationWrapper.js +6 -0
- package/dist/app/components/navigation/SideNavigationWrapper.js.map +1 -0
- package/dist/app/components/navigation/useNavigationCollapsibleState.d.ts +7 -0
- package/dist/app/components/navigation/useNavigationCollapsibleState.js +16 -0
- package/dist/app/components/navigation/useNavigationCollapsibleState.js.map +1 -0
- package/dist/app/components/navigation/util.d.ts +8 -0
- package/dist/app/components/navigation/util.js +15 -0
- package/dist/app/components/navigation/util.js.map +1 -0
- package/dist/app/config.d.ts +3 -0
- package/dist/app/config.js +9 -0
- package/dist/app/config.js.map +1 -0
- package/dist/app/core/DevPortalContext.d.ts +80 -0
- package/dist/app/core/DevPortalContext.js +68 -0
- package/dist/app/core/DevPortalContext.js.map +1 -0
- package/dist/app/core/helmet.d.ts +4 -0
- package/dist/app/core/helmet.js +5 -0
- package/dist/app/core/helmet.js.map +1 -0
- package/dist/app/core/icons.d.ts +1 -0
- package/dist/app/core/icons.js +2 -0
- package/dist/app/core/icons.js.map +1 -0
- package/dist/app/core/plugins.d.ts +24 -0
- package/dist/app/core/plugins.js +4 -0
- package/dist/app/core/plugins.js.map +1 -0
- package/dist/app/core/router.d.ts +1 -0
- package/dist/app/core/router.js +2 -0
- package/dist/app/core/router.js.map +1 -0
- package/dist/app/core/types/combine.d.ts +4 -0
- package/dist/app/core/types/combine.js +2 -0
- package/dist/app/core/types/combine.js.map +1 -0
- package/dist/app/main.d.ts +1 -0
- package/dist/app/main.js +18 -0
- package/dist/app/main.js.map +1 -0
- package/dist/app/markdowns.d.ts +3 -0
- package/dist/app/markdowns.js +5 -0
- package/dist/app/markdowns.js.map +1 -0
- package/dist/app/oas/graphql/index.d.ts +12 -0
- package/dist/app/oas/graphql/index.js +290 -0
- package/dist/app/oas/graphql/index.js.map +1 -0
- package/dist/app/oas/graphql/server.d.ts +1 -0
- package/dist/app/oas/graphql/server.js +8 -0
- package/dist/app/oas/graphql/server.js.map +1 -0
- package/dist/app/oas/parser/dereference/index.d.ts +5 -0
- package/dist/app/oas/parser/dereference/index.js +43 -0
- package/dist/app/oas/parser/dereference/index.js.map +1 -0
- package/dist/app/oas/parser/dereference/resolveRef.d.ts +5 -0
- package/dist/app/oas/parser/dereference/resolveRef.js +26 -0
- package/dist/app/oas/parser/dereference/resolveRef.js.map +1 -0
- package/dist/app/oas/parser/index.d.ts +21 -0
- package/dist/app/oas/parser/index.js +58 -0
- package/dist/app/oas/parser/index.js.map +1 -0
- package/dist/app/oas/parser/schemas/v3.0.json +1489 -0
- package/dist/app/oas/parser/schemas/v3.1.json +1298 -0
- package/dist/app/oas/parser/upgrade/index.d.ts +9 -0
- package/dist/app/oas/parser/upgrade/index.js +90 -0
- package/dist/app/oas/parser/upgrade/index.js.map +1 -0
- package/dist/app/plugins/api-key/SettingsApiKeys.d.ts +4 -0
- package/dist/app/plugins/api-key/SettingsApiKeys.js +7 -0
- package/dist/app/plugins/api-key/SettingsApiKeys.js.map +1 -0
- package/dist/app/plugins/api-key/index.d.ts +32 -0
- package/dist/app/plugins/api-key/index.js +55 -0
- package/dist/app/plugins/api-key/index.js.map +1 -0
- package/dist/app/plugins/markdown/MdxPage.d.ts +3 -0
- package/dist/app/plugins/markdown/MdxPage.js +55 -0
- package/dist/app/plugins/markdown/MdxPage.js.map +1 -0
- package/dist/app/plugins/markdown/Toc.d.ts +4 -0
- package/dist/app/plugins/markdown/Toc.js +40 -0
- package/dist/app/plugins/markdown/Toc.js.map +1 -0
- package/dist/app/plugins/markdown/generateRoutes.d.ts +3 -0
- package/dist/app/plugins/markdown/generateRoutes.js +50 -0
- package/dist/app/plugins/markdown/generateRoutes.js.map +1 -0
- package/dist/app/plugins/markdown/index.d.ts +19 -0
- package/dist/app/plugins/markdown/index.js +9 -0
- package/dist/app/plugins/markdown/index.js.map +1 -0
- package/dist/app/plugins/openapi/ColorizedParam.d.ts +8 -0
- package/dist/app/plugins/openapi/ColorizedParam.js +40 -0
- package/dist/app/plugins/openapi/ColorizedParam.js.map +1 -0
- package/dist/app/plugins/openapi/MakeRequest.d.ts +4 -0
- package/dist/app/plugins/openapi/MakeRequest.js +11 -0
- package/dist/app/plugins/openapi/MakeRequest.js.map +1 -0
- package/dist/app/plugins/openapi/MethodBadge.d.ts +13 -0
- package/dist/app/plugins/openapi/MethodBadge.js +26 -0
- package/dist/app/plugins/openapi/MethodBadge.js.map +1 -0
- package/dist/app/plugins/openapi/OperationList.d.ts +47 -0
- package/dist/app/plugins/openapi/OperationList.js +82 -0
- package/dist/app/plugins/openapi/OperationList.js.map +1 -0
- package/dist/app/plugins/openapi/OperationListItem.d.ts +7 -0
- package/dist/app/plugins/openapi/OperationListItem.js +15 -0
- package/dist/app/plugins/openapi/OperationListItem.js.map +1 -0
- package/dist/app/plugins/openapi/ParameterList.d.ts +7 -0
- package/dist/app/plugins/openapi/ParameterList.js +5 -0
- package/dist/app/plugins/openapi/ParameterList.js.map +1 -0
- package/dist/app/plugins/openapi/ParameterListItem.d.ts +8 -0
- package/dist/app/plugins/openapi/ParameterListItem.js +13 -0
- package/dist/app/plugins/openapi/ParameterListItem.js.map +1 -0
- package/dist/app/plugins/openapi/RequestBodySidecarBox.d.ts +6 -0
- package/dist/app/plugins/openapi/RequestBodySidecarBox.js +19 -0
- package/dist/app/plugins/openapi/RequestBodySidecarBox.js.map +1 -0
- package/dist/app/plugins/openapi/ResponsesSidecarBox.d.ts +6 -0
- package/dist/app/plugins/openapi/ResponsesSidecarBox.js +15 -0
- package/dist/app/plugins/openapi/ResponsesSidecarBox.js.map +1 -0
- package/dist/app/plugins/openapi/Select.d.ts +9 -0
- package/dist/app/plugins/openapi/Select.js +5 -0
- package/dist/app/plugins/openapi/Select.js.map +1 -0
- package/dist/app/plugins/openapi/Sidecar.d.ts +4 -0
- package/dist/app/plugins/openapi/Sidecar.js +39 -0
- package/dist/app/plugins/openapi/Sidecar.js.map +1 -0
- package/dist/app/plugins/openapi/SidecarBox.d.ts +10 -0
- package/dist/app/plugins/openapi/SidecarBox.js +8 -0
- package/dist/app/plugins/openapi/SidecarBox.js.map +1 -0
- package/dist/app/plugins/openapi/graphql/index.d.ts +836 -0
- package/dist/app/plugins/openapi/graphql/index.js +4 -0
- package/dist/app/plugins/openapi/graphql/index.js.map +1 -0
- package/dist/app/plugins/openapi/index.d.ts +22 -0
- package/dist/app/plugins/openapi/index.js +91 -0
- package/dist/app/plugins/openapi/index.js.map +1 -0
- package/dist/app/plugins/openapi/util/generateSchemaExample.d.ts +3 -0
- package/dist/app/plugins/openapi/util/generateSchemaExample.js +52 -0
- package/dist/app/plugins/openapi/util/generateSchemaExample.js.map +1 -0
- package/dist/app/plugins/openapi/util/getCode.d.ts +2 -0
- package/dist/app/plugins/openapi/util/getCode.js +54 -0
- package/dist/app/plugins/openapi/util/getCode.js.map +1 -0
- package/dist/app/plugins/openapi/util/urql.d.ts +8 -0
- package/dist/app/plugins/openapi/util/urql.js +8 -0
- package/dist/app/plugins/openapi/util/urql.js.map +1 -0
- package/dist/app/plugins/openapi/worker/createSharedWorkerClient.d.ts +5 -0
- package/dist/app/plugins/openapi/worker/createSharedWorkerClient.js +47 -0
- package/dist/app/plugins/openapi/worker/createSharedWorkerClient.js.map +1 -0
- package/dist/app/plugins/openapi/worker/worker.d.ts +1 -0
- package/dist/app/plugins/openapi/worker/worker.js +20 -0
- package/dist/app/plugins/openapi/worker/worker.js.map +1 -0
- package/dist/app/plugins/redirect/index.d.ts +10 -0
- package/dist/app/plugins/redirect/index.js +11 -0
- package/dist/app/plugins/redirect/index.js.map +1 -0
- package/dist/app/tailwind.d.ts +3 -0
- package/dist/app/tailwind.js +69 -0
- package/dist/app/tailwind.js.map +1 -0
- package/dist/app/ui/Callout.d.ts +51 -0
- package/dist/app/ui/Callout.js +50 -0
- package/dist/app/ui/Callout.js.map +1 -0
- package/dist/app/ui/Card.d.ts +8 -0
- package/dist/app/ui/Card.js +17 -0
- package/dist/app/ui/Card.js.map +1 -0
- package/dist/app/ui/Note.d.ts +8 -0
- package/dist/app/ui/Note.js +23 -0
- package/dist/app/ui/Note.js.map +1 -0
- package/dist/app/util/MdxComponents.d.ts +27 -0
- package/dist/app/util/MdxComponents.js +40 -0
- package/dist/app/util/MdxComponents.js.map +1 -0
- package/dist/app/util/cn.d.ts +2 -0
- package/dist/app/util/cn.js +6 -0
- package/dist/app/util/cn.js.map +1 -0
- package/dist/app/util/createWaitForNotify.d.ts +1 -0
- package/dist/app/util/createWaitForNotify.js +15 -0
- package/dist/app/util/createWaitForNotify.js.map +1 -0
- package/dist/app/util/groupBy.d.ts +6 -0
- package/dist/app/util/groupBy.js +9 -0
- package/dist/app/util/groupBy.js.map +1 -0
- package/dist/app/util/joinPath.d.ts +1 -0
- package/dist/app/util/joinPath.js +8 -0
- package/dist/app/util/joinPath.js.map +1 -0
- package/dist/app/util/pastellize.d.ts +4 -0
- package/dist/app/util/pastellize.js +14 -0
- package/dist/app/util/pastellize.js.map +1 -0
- package/dist/app/util/slugify.d.ts +3 -0
- package/dist/app/util/slugify.js +3 -0
- package/dist/app/util/slugify.js.map +1 -0
- package/dist/app/util/traverseNavigation.d.ts +6 -0
- package/dist/app/util/traverseNavigation.js +30 -0
- package/dist/app/util/traverseNavigation.js.map +1 -0
- package/dist/app/util/useScrollToAnchor.d.ts +1 -0
- package/dist/app/util/useScrollToAnchor.js +33 -0
- package/dist/app/util/useScrollToAnchor.js.map +1 -0
- package/dist/app/util/useScrollToTop.d.ts +1 -0
- package/dist/app/util/useScrollToTop.js +13 -0
- package/dist/app/util/useScrollToTop.js.map +1 -0
- package/dist/auth.d.ts +2 -0
- package/dist/auth.js +3 -0
- package/dist/auth.js.map +1 -0
- package/dist/cli/build/handler.d.ts +4 -0
- package/dist/cli/build/handler.js +9 -0
- package/dist/cli/build/handler.js.map +1 -0
- package/dist/cli/cli.d.ts +1 -0
- package/dist/cli/cli.js +64 -0
- package/dist/cli/cli.js.map +1 -0
- package/dist/cli/cmds/build.d.ts +8 -0
- package/dist/cli/cmds/build.js +23 -0
- package/dist/cli/cmds/build.js.map +1 -0
- package/dist/cli/cmds/dev.d.ts +8 -0
- package/dist/cli/cmds/dev.js +29 -0
- package/dist/cli/cmds/dev.js.map +1 -0
- package/dist/cli/common/analytics/lib.d.ts +17 -0
- package/dist/cli/common/analytics/lib.js +53 -0
- package/dist/cli/common/analytics/lib.js.map +1 -0
- package/dist/cli/common/constants.d.ts +5 -0
- package/dist/cli/common/constants.js +9 -0
- package/dist/cli/common/constants.js.map +1 -0
- package/dist/cli/common/logger.d.ts +2 -0
- package/dist/cli/common/logger.js +14 -0
- package/dist/cli/common/logger.js.map +1 -0
- package/dist/cli/common/machine-id/lib.d.ts +1 -0
- package/dist/cli/common/machine-id/lib.js +74 -0
- package/dist/cli/common/machine-id/lib.js.map +1 -0
- package/dist/cli/common/outdated.d.ts +1 -0
- package/dist/cli/common/outdated.js +70 -0
- package/dist/cli/common/outdated.js.map +1 -0
- package/dist/cli/common/output.d.ts +9 -0
- package/dist/cli/common/output.js +65 -0
- package/dist/cli/common/output.js.map +1 -0
- package/dist/cli/common/utils/box.d.ts +33 -0
- package/dist/cli/common/utils/box.js +81 -0
- package/dist/cli/common/utils/box.js.map +1 -0
- package/dist/cli/common/utils/ports.d.ts +1 -0
- package/dist/cli/common/utils/ports.js +18 -0
- package/dist/cli/common/utils/ports.js.map +1 -0
- package/dist/cli/common/validators/lib.d.ts +20 -0
- package/dist/cli/common/validators/lib.js +31 -0
- package/dist/cli/common/validators/lib.js.map +1 -0
- package/dist/cli/common/xdg/lib.d.ts +6 -0
- package/dist/cli/common/xdg/lib.js +18 -0
- package/dist/cli/common/xdg/lib.js.map +1 -0
- package/dist/cli/dev/handler.d.ts +5 -0
- package/dist/cli/dev/handler.js +22 -0
- package/dist/cli/dev/handler.js.map +1 -0
- package/dist/config/config.d.ts +37 -0
- package/dist/config/config.js +2 -0
- package/dist/config/config.js.map +1 -0
- package/dist/index.d.ts +7 -0
- package/dist/index.js +6 -0
- package/dist/index.js.map +1 -0
- package/dist/plugins.d.ts +4 -0
- package/dist/plugins.js +6 -0
- package/dist/plugins.js.map +1 -0
- package/dist/vite/build.d.ts +3 -0
- package/dist/vite/build.js +29 -0
- package/dist/vite/build.js.map +1 -0
- package/dist/vite/config.d.ts +6 -0
- package/dist/vite/config.js +74 -0
- package/dist/vite/config.js.map +1 -0
- package/dist/vite/dev-server.d.ts +10 -0
- package/dist/vite/dev-server.js +53 -0
- package/dist/vite/dev-server.js.map +1 -0
- package/dist/vite/html.d.ts +5 -0
- package/dist/vite/html.js +32 -0
- package/dist/vite/html.js.map +1 -0
- package/dist/vite/import-auth-plugin.d.ts +3 -0
- package/dist/vite/import-auth-plugin.js +28 -0
- package/dist/vite/import-auth-plugin.js.map +1 -0
- package/dist/vite/plugin.d.ts +7 -0
- package/dist/vite/plugin.js +109 -0
- package/dist/vite/plugin.js.map +1 -0
- package/package.json +118 -0
- package/src/app/DevPortal.tsx +115 -0
- package/src/app/Heading.tsx +60 -0
- package/src/app/app.tsx +85 -0
- package/src/app/authentication/authentication.ts +18 -0
- package/src/app/authentication/clerk.ts +47 -0
- package/src/app/authentication/openid.ts +192 -0
- package/src/app/components/AnchorLink.tsx +19 -0
- package/src/app/components/CategoryHeading.tsx +16 -0
- package/src/app/components/DynamicIcon.tsx +60 -0
- package/src/app/components/Header.tsx +69 -0
- package/src/app/components/Layout.tsx +56 -0
- package/src/app/components/Markdown.tsx +37 -0
- package/src/app/components/SyntaxHighlight.tsx +92 -0
- package/src/app/components/TopNavigation.tsx +32 -0
- package/src/app/components/context/ComponentsContext.tsx +24 -0
- package/src/app/components/context/DevPortalProvider.ts +54 -0
- package/src/app/components/context/PluginSystem.ts +0 -0
- package/src/app/components/context/ThemeContext.tsx +46 -0
- package/src/app/components/context/ViewportAnchorContext.tsx +139 -0
- package/src/app/components/navigation/SideNavigation.tsx +18 -0
- package/src/app/components/navigation/SideNavigationCategory.tsx +74 -0
- package/src/app/components/navigation/SideNavigationItem.tsx +143 -0
- package/src/app/components/navigation/SideNavigationWrapper.tsx +15 -0
- package/src/app/components/navigation/useNavigationCollapsibleState.ts +27 -0
- package/src/app/components/navigation/util.ts +38 -0
- package/src/app/config.ts +20 -0
- package/src/app/core/DevPortalContext.ts +164 -0
- package/src/app/core/helmet.ts +5 -0
- package/src/app/core/icons.tsx +1 -0
- package/src/app/core/plugins.ts +43 -0
- package/src/app/core/router.tsx +1 -0
- package/src/app/core/types/combine.ts +16 -0
- package/src/app/main.css +137 -0
- package/src/app/main.tsx +22 -0
- package/src/app/markdowns.ts +7 -0
- package/src/app/oas/graphql/index.ts +422 -0
- package/src/app/oas/graphql/server.ts +10 -0
- package/src/app/oas/parser/dereference/index.ts +59 -0
- package/src/app/oas/parser/dereference/resolveRef.ts +32 -0
- package/src/app/oas/parser/index.ts +94 -0
- package/src/app/oas/parser/schemas/v3.0.json +1489 -0
- package/src/app/oas/parser/schemas/v3.1.json +1298 -0
- package/src/app/oas/parser/upgrade/index.ts +108 -0
- package/src/app/plugins/api-key/SettingsApiKeys.tsx +22 -0
- package/src/app/plugins/api-key/index.tsx +123 -0
- package/src/app/plugins/markdown/MdxPage.tsx +128 -0
- package/src/app/plugins/markdown/Toc.tsx +122 -0
- package/src/app/plugins/markdown/generateRoutes.tsx +72 -0
- package/src/app/plugins/markdown/index.tsx +31 -0
- package/src/app/plugins/openapi/ColorizedParam.tsx +73 -0
- package/src/app/plugins/openapi/MakeRequest.tsx +30 -0
- package/src/app/plugins/openapi/MethodBadge.tsx +36 -0
- package/src/app/plugins/openapi/OperationList.tsx +119 -0
- package/src/app/plugins/openapi/OperationListItem.tsx +55 -0
- package/src/app/plugins/openapi/ParameterList.tsx +32 -0
- package/src/app/plugins/openapi/ParameterListItem.tsx +60 -0
- package/src/app/plugins/openapi/RequestBodySidecarBox.tsx +48 -0
- package/src/app/plugins/openapi/ResponsesSidecarBox.tsx +60 -0
- package/src/app/plugins/openapi/Select.tsx +35 -0
- package/src/app/plugins/openapi/Sidecar.tsx +99 -0
- package/src/app/plugins/openapi/SidecarBox.tsx +35 -0
- package/src/app/plugins/openapi/graphql/env.d.ts +48 -0
- package/src/app/plugins/openapi/graphql/index.ts +13 -0
- package/src/app/plugins/openapi/index.tsx +142 -0
- package/src/app/plugins/openapi/util/generateSchemaExample.ts +59 -0
- package/src/app/plugins/openapi/util/getCode.tsx +69 -0
- package/src/app/plugins/openapi/util/urql.ts +8 -0
- package/src/app/plugins/openapi/worker/createSharedWorkerClient.ts +60 -0
- package/src/app/plugins/openapi/worker/worker.ts +30 -0
- package/src/app/plugins/redirect/index.tsx +20 -0
- package/src/app/tailwind.ts +72 -0
- package/src/app/ui/Callout.tsx +87 -0
- package/src/app/ui/Card.tsx +82 -0
- package/src/app/ui/Note.tsx +58 -0
- package/src/app/util/MdxComponents.tsx +70 -0
- package/src/app/util/cn.ts +6 -0
- package/src/app/util/createWaitForNotify.ts +18 -0
- package/src/app/util/groupBy.ts +24 -0
- package/src/app/util/joinPath.tsx +10 -0
- package/src/app/util/pastellize.ts +25 -0
- package/src/app/util/slugify.ts +3 -0
- package/src/app/util/traverseNavigation.ts +55 -0
- package/src/app/util/useScrollToAnchor.ts +38 -0
- package/src/app/util/useScrollToTop.ts +13 -0
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import { type ReactNode } from "react";
|
|
2
|
+
import { useRegisterAnchorElement } from "./components/context/ViewportAnchorContext.js";
|
|
3
|
+
import { cn } from "./util/cn.js";
|
|
4
|
+
|
|
5
|
+
const getComponent = (level: number) => {
|
|
6
|
+
switch (level) {
|
|
7
|
+
case 1:
|
|
8
|
+
return "h1";
|
|
9
|
+
case 2:
|
|
10
|
+
return "h2";
|
|
11
|
+
case 3:
|
|
12
|
+
return "h3";
|
|
13
|
+
case 4:
|
|
14
|
+
return "h4";
|
|
15
|
+
case 5:
|
|
16
|
+
return "h5";
|
|
17
|
+
case 6:
|
|
18
|
+
return "h6";
|
|
19
|
+
default:
|
|
20
|
+
return "h1";
|
|
21
|
+
}
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
export type HeadingProps = {
|
|
25
|
+
children: ReactNode;
|
|
26
|
+
className?: string;
|
|
27
|
+
id?: string;
|
|
28
|
+
level?: 1 | 2 | 3 | 4 | 5 | 6;
|
|
29
|
+
registerSidebarAnchor?: boolean;
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
export const Heading = ({
|
|
33
|
+
level,
|
|
34
|
+
children,
|
|
35
|
+
id,
|
|
36
|
+
className,
|
|
37
|
+
registerSidebarAnchor,
|
|
38
|
+
}: HeadingProps) => {
|
|
39
|
+
const Component = getComponent(level ?? 1);
|
|
40
|
+
const { ref } = useRegisterAnchorElement();
|
|
41
|
+
|
|
42
|
+
return (
|
|
43
|
+
<Component
|
|
44
|
+
className={cn("group relative", className)}
|
|
45
|
+
ref={registerSidebarAnchor ? ref : undefined}
|
|
46
|
+
id={id}
|
|
47
|
+
>
|
|
48
|
+
{id && (
|
|
49
|
+
<a
|
|
50
|
+
href={`#${id}`}
|
|
51
|
+
className="no-underline absolute text-primary -left-[0.8em] pr-2.5 opacity-0 group-hover:opacity-50 hover:!opacity-100 transition-opacity duration-200"
|
|
52
|
+
aria-label={`Link to ${id}`}
|
|
53
|
+
>
|
|
54
|
+
#
|
|
55
|
+
</a>
|
|
56
|
+
)}
|
|
57
|
+
{children}
|
|
58
|
+
</Component>
|
|
59
|
+
);
|
|
60
|
+
};
|
package/src/app/app.tsx
ADDED
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
import "./main.css";
|
|
2
|
+
|
|
3
|
+
import DevPortal from "./DevPortal.js";
|
|
4
|
+
import { markdownPlugin } from "./plugins/markdown/index.js";
|
|
5
|
+
import { openApiPlugin } from "./plugins/openapi/index.js";
|
|
6
|
+
|
|
7
|
+
import config from "./config.js";
|
|
8
|
+
|
|
9
|
+
// async function getAuthProvider(authConfig: AuthenticationConfig) {
|
|
10
|
+
// if (authConfig.type === "clerk") {
|
|
11
|
+
// const clerkProvider = await import("./authentication/clerk.js");
|
|
12
|
+
// return clerkProvider(authConfig);
|
|
13
|
+
// } else {
|
|
14
|
+
// throw new Error(
|
|
15
|
+
// `The authentication type "${authConfig.type}" is not supported.`,
|
|
16
|
+
// );
|
|
17
|
+
// }
|
|
18
|
+
// //openIdAuth({
|
|
19
|
+
// // clientId: oauth.client_id,
|
|
20
|
+
// // authorizationEndpoint: oauth.authorize_url,
|
|
21
|
+
// // tokenEndpoint: oauth.token_fetch_url,
|
|
22
|
+
// // })
|
|
23
|
+
// }
|
|
24
|
+
|
|
25
|
+
export default function App() {
|
|
26
|
+
return (
|
|
27
|
+
<DevPortal
|
|
28
|
+
meta={{
|
|
29
|
+
headerTitle: config?.ui?.headerTitle ?? "Developer Portal",
|
|
30
|
+
pageTitle: config?.ui?.pageTitle ?? "%s | Dev Portal",
|
|
31
|
+
logo: config?.ui?.logo ?? "https://cdn.zuplo.com/www/favicon.png",
|
|
32
|
+
favicon:
|
|
33
|
+
config?.ui?.metadata?.favicon ??
|
|
34
|
+
"https://cdn.zuplo.com/www/favicon.png",
|
|
35
|
+
}}
|
|
36
|
+
navigation={config.navigation ?? []}
|
|
37
|
+
// authentication={
|
|
38
|
+
// config.authentication
|
|
39
|
+
// ? getAuthProvider(config.authentication)
|
|
40
|
+
// : undefined
|
|
41
|
+
// }
|
|
42
|
+
plugins={[
|
|
43
|
+
...(config.docs
|
|
44
|
+
? Array.isArray(config.docs)
|
|
45
|
+
? config.docs
|
|
46
|
+
: [config.docs]
|
|
47
|
+
: []
|
|
48
|
+
).map((docs) =>
|
|
49
|
+
markdownPlugin({
|
|
50
|
+
markdownFiles: docs?.files ?? {},
|
|
51
|
+
}),
|
|
52
|
+
),
|
|
53
|
+
...(config.apis
|
|
54
|
+
? Array.isArray(config.apis)
|
|
55
|
+
? config.apis
|
|
56
|
+
: [config.apis]
|
|
57
|
+
: []
|
|
58
|
+
).map((api) => openApiPlugin(api)),
|
|
59
|
+
|
|
60
|
+
// apiKeyPlugin({
|
|
61
|
+
// // consumerEndpoint:
|
|
62
|
+
// // "https://zudoku-customer-main-b36fa2f.d2.zuplo.dev/v1/developer/api-keys",
|
|
63
|
+
// getConsumers: async (ctx) => {
|
|
64
|
+
// const accessToken = await ctx.authentication?.getToken?.(ctx);
|
|
65
|
+
|
|
66
|
+
// if (!accessToken) {
|
|
67
|
+
// return;
|
|
68
|
+
// }
|
|
69
|
+
|
|
70
|
+
// const consumers = await fetch(
|
|
71
|
+
// "https://zudoku-customer-main-b36fa2f.d2.zuplo.dev/v1/developer/api-keys",
|
|
72
|
+
// {
|
|
73
|
+
// headers: {
|
|
74
|
+
// Authorization: `Bearer ${accessToken}`,
|
|
75
|
+
// },
|
|
76
|
+
// },
|
|
77
|
+
// );
|
|
78
|
+
|
|
79
|
+
// return { consumers: [await consumers.json()] };
|
|
80
|
+
// },
|
|
81
|
+
// }),
|
|
82
|
+
]}
|
|
83
|
+
/>
|
|
84
|
+
);
|
|
85
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { DevPortalContext } from "../core/DevPortalContext.js";
|
|
2
|
+
|
|
3
|
+
export interface AuthProvider {
|
|
4
|
+
initialize(context: DevPortalContext): Promise<unknown>;
|
|
5
|
+
login(context: DevPortalContext): Promise<unknown>;
|
|
6
|
+
getToken?: (context: DevPortalContext) => Promise<string | undefined>;
|
|
7
|
+
handleAuthenticationResponse?: (
|
|
8
|
+
path: Path,
|
|
9
|
+
context: DevPortalContext,
|
|
10
|
+
) => Promise<unknown>;
|
|
11
|
+
signOut(context: DevPortalContext): void;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export type Path = {
|
|
15
|
+
pathname: string;
|
|
16
|
+
search: string;
|
|
17
|
+
hash: string;
|
|
18
|
+
};
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { Clerk } from "@clerk/clerk-js";
|
|
2
|
+
import { type AuthProvider } from "./authentication.js";
|
|
3
|
+
|
|
4
|
+
const clerkProvider = ({
|
|
5
|
+
clerkPubKey,
|
|
6
|
+
}: {
|
|
7
|
+
clerkPubKey: string;
|
|
8
|
+
}): AuthProvider => {
|
|
9
|
+
const clerkApi = new Clerk(clerkPubKey);
|
|
10
|
+
|
|
11
|
+
const clerkIsLoaded = clerkApi.load({});
|
|
12
|
+
|
|
13
|
+
return {
|
|
14
|
+
initialize: async (context) => {
|
|
15
|
+
await clerkIsLoaded;
|
|
16
|
+
|
|
17
|
+
if (clerkApi.session) {
|
|
18
|
+
await context.setUserProfile({
|
|
19
|
+
isLoggedIn: true,
|
|
20
|
+
name: clerkApi.session.user.fullName ?? undefined,
|
|
21
|
+
email:
|
|
22
|
+
clerkApi.session.user.emailAddresses.at(0)?.emailAddress ??
|
|
23
|
+
undefined,
|
|
24
|
+
});
|
|
25
|
+
} else {
|
|
26
|
+
await context.setUserProfile({
|
|
27
|
+
isLoggedIn: false,
|
|
28
|
+
});
|
|
29
|
+
}
|
|
30
|
+
},
|
|
31
|
+
|
|
32
|
+
getToken: async () => {
|
|
33
|
+
await clerkIsLoaded;
|
|
34
|
+
const token = await clerkApi.session?.getToken();
|
|
35
|
+
return token ?? undefined;
|
|
36
|
+
},
|
|
37
|
+
|
|
38
|
+
signOut() {
|
|
39
|
+
clerkApi.signOut();
|
|
40
|
+
},
|
|
41
|
+
login: async () => {
|
|
42
|
+
await clerkApi.redirectToSignIn();
|
|
43
|
+
},
|
|
44
|
+
};
|
|
45
|
+
};
|
|
46
|
+
|
|
47
|
+
export default clerkProvider;
|
|
@@ -0,0 +1,192 @@
|
|
|
1
|
+
import * as oauth from "oauth4webapi";
|
|
2
|
+
import { DevPortalContext } from "../core/DevPortalContext.js";
|
|
3
|
+
import { type AuthProvider } from "./authentication.js";
|
|
4
|
+
const algorithm = "oauth2";
|
|
5
|
+
|
|
6
|
+
const getAuthServerByIssuer = async (issuer: string) => {
|
|
7
|
+
const authorizationServer = await oauth
|
|
8
|
+
.discoveryRequest(new URL(issuer), { algorithm })
|
|
9
|
+
.then((response) =>
|
|
10
|
+
oauth.processDiscoveryResponse(new URL(issuer), response),
|
|
11
|
+
);
|
|
12
|
+
|
|
13
|
+
return authorizationServer;
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
export type AuthServerOption = {
|
|
17
|
+
issuer?: string;
|
|
18
|
+
authorizationEndpoint?: string;
|
|
19
|
+
tokenEndpoint?: string;
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
const getAuthServer = async ({
|
|
23
|
+
issuer,
|
|
24
|
+
authorizationEndpoint,
|
|
25
|
+
tokenEndpoint,
|
|
26
|
+
}: AuthServerOption) => {
|
|
27
|
+
return issuer
|
|
28
|
+
? await getAuthServerByIssuer(issuer)
|
|
29
|
+
: ({
|
|
30
|
+
issuer: new URL(authorizationEndpoint!).origin,
|
|
31
|
+
authorization_endpoint: authorizationEndpoint,
|
|
32
|
+
token_endpoint: tokenEndpoint,
|
|
33
|
+
code_challenge_methods_supported: [],
|
|
34
|
+
} satisfies oauth.AuthorizationServer);
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
export const openIdAuth = ({
|
|
38
|
+
clientId,
|
|
39
|
+
clientSecret,
|
|
40
|
+
issuer,
|
|
41
|
+
authorizationEndpoint,
|
|
42
|
+
tokenEndpoint,
|
|
43
|
+
}: {
|
|
44
|
+
clientId: string;
|
|
45
|
+
clientSecret?: string;
|
|
46
|
+
audience?: string;
|
|
47
|
+
} & AuthServerOption): AuthProvider => {
|
|
48
|
+
const client: oauth.Client = {
|
|
49
|
+
client_id: clientId,
|
|
50
|
+
client_secret: clientSecret,
|
|
51
|
+
token_endpoint_auth_method: "none",
|
|
52
|
+
};
|
|
53
|
+
|
|
54
|
+
const redirect_uri = "http://localhost:5173/oauth/callback";
|
|
55
|
+
|
|
56
|
+
return {
|
|
57
|
+
initialize() {
|
|
58
|
+
return Promise.resolve();
|
|
59
|
+
},
|
|
60
|
+
signOut() {},
|
|
61
|
+
login: async (context: DevPortalContext) => {
|
|
62
|
+
const code_challenge_method = "S256";
|
|
63
|
+
const authorizationServer = await getAuthServer({
|
|
64
|
+
issuer,
|
|
65
|
+
authorizationEndpoint,
|
|
66
|
+
tokenEndpoint,
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
if (!authorizationServer.authorization_endpoint) {
|
|
70
|
+
throw new Error("No authorization endpoint");
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
/**
|
|
74
|
+
* The following MUST be generated for every redirect to the authorization_endpoint. You must store
|
|
75
|
+
* the codeVerifier and nonce in the end-user session such that it can be recovered as the user
|
|
76
|
+
* gets redirected from the authorization server back to your application.
|
|
77
|
+
*/
|
|
78
|
+
const codeVerifier = oauth.generateRandomCodeVerifier();
|
|
79
|
+
const codeChallenge =
|
|
80
|
+
await oauth.calculatePKCECodeChallenge(codeVerifier);
|
|
81
|
+
|
|
82
|
+
await context.sessionStorage.set("codeVerifier", codeVerifier);
|
|
83
|
+
|
|
84
|
+
// redirect user to as.authorization_endpoint
|
|
85
|
+
const authorizationUrl = new URL(
|
|
86
|
+
authorizationServer.authorization_endpoint,
|
|
87
|
+
);
|
|
88
|
+
authorizationUrl.searchParams.set("client_id", client.client_id);
|
|
89
|
+
authorizationUrl.searchParams.set("redirect_uri", redirect_uri);
|
|
90
|
+
authorizationUrl.searchParams.set("response_type", "code");
|
|
91
|
+
// authorizationUrl.searchParams.set("scope", "api:read");
|
|
92
|
+
authorizationUrl.searchParams.set("code_challenge", codeChallenge);
|
|
93
|
+
authorizationUrl.searchParams.set(
|
|
94
|
+
"code_challenge_method",
|
|
95
|
+
code_challenge_method,
|
|
96
|
+
);
|
|
97
|
+
|
|
98
|
+
/**
|
|
99
|
+
* We cannot be sure the AS supports PKCE so we're going to use state too. Use of PKCE is
|
|
100
|
+
* backwards compatible even if the AS doesn't support it which is why we're using it regardless.
|
|
101
|
+
*/
|
|
102
|
+
if (
|
|
103
|
+
authorizationServer.code_challenge_methods_supported?.includes(
|
|
104
|
+
"S256",
|
|
105
|
+
) !== true
|
|
106
|
+
) {
|
|
107
|
+
const state = oauth.generateRandomState();
|
|
108
|
+
authorizationUrl.searchParams.set("state", state);
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
// now redirect the user to authorizationUrl.href
|
|
112
|
+
location.href = authorizationUrl.href;
|
|
113
|
+
},
|
|
114
|
+
|
|
115
|
+
handleAuthenticationResponse: async ({ search }, { sessionStorage }) => {
|
|
116
|
+
const searchParams = new URLSearchParams(search);
|
|
117
|
+
const state = searchParams.get("state");
|
|
118
|
+
if (!state) {
|
|
119
|
+
return;
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
// one eternity later, the user lands back on the redirect_uri
|
|
123
|
+
// Authorization Code Grant Request & Response
|
|
124
|
+
const codeVerifier = await sessionStorage.get("codeVerifier");
|
|
125
|
+
|
|
126
|
+
if (!codeVerifier) {
|
|
127
|
+
return;
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
const as = await getAuthServer({
|
|
131
|
+
issuer,
|
|
132
|
+
authorizationEndpoint,
|
|
133
|
+
tokenEndpoint,
|
|
134
|
+
});
|
|
135
|
+
|
|
136
|
+
const params = oauth.validateAuthResponse(
|
|
137
|
+
as,
|
|
138
|
+
client,
|
|
139
|
+
searchParams,
|
|
140
|
+
state,
|
|
141
|
+
);
|
|
142
|
+
if (oauth.isOAuth2Error(params)) {
|
|
143
|
+
console.error("Error Response", params);
|
|
144
|
+
throw new Error(); // Handle OAuth 2.0 redirect error
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
const response = await oauth.authorizationCodeGrantRequest(
|
|
148
|
+
as,
|
|
149
|
+
client,
|
|
150
|
+
params,
|
|
151
|
+
redirect_uri,
|
|
152
|
+
codeVerifier,
|
|
153
|
+
);
|
|
154
|
+
|
|
155
|
+
// @todo do we need to do these
|
|
156
|
+
// const challenges = oauth.parseWwwAuthenticateChallenges(response);
|
|
157
|
+
// if (challenges) {
|
|
158
|
+
// for (const challenge of challenges) {
|
|
159
|
+
// console.error("WWW-Authenticate Challenge", challenge);
|
|
160
|
+
// }
|
|
161
|
+
// throw new Error(); // Handle WWW-Authenticate Challenges as needed
|
|
162
|
+
// }
|
|
163
|
+
|
|
164
|
+
const oauthResult = await oauth.processAuthorizationCodeOpenIDResponse(
|
|
165
|
+
as,
|
|
166
|
+
client,
|
|
167
|
+
response,
|
|
168
|
+
);
|
|
169
|
+
if (oauth.isOAuth2Error(oauthResult)) {
|
|
170
|
+
console.error("Error Response", oauthResult);
|
|
171
|
+
throw new Error(oauthResult.error);
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
const userInfoResponse = await oauth.userInfoRequest(
|
|
175
|
+
as,
|
|
176
|
+
client,
|
|
177
|
+
oauthResult.access_token,
|
|
178
|
+
);
|
|
179
|
+
const userInfo = await userInfoResponse.json();
|
|
180
|
+
|
|
181
|
+
// void storage.setProfile({
|
|
182
|
+
// sub: userInfo.sub,
|
|
183
|
+
// email: userInfo.email,
|
|
184
|
+
// name: userInfo.name,
|
|
185
|
+
// email_verified: userInfo.email_verified ?? false,
|
|
186
|
+
// picture: userInfo.picture,
|
|
187
|
+
// id_token: oauthResult.id_token,
|
|
188
|
+
// access_token: oauthResult.access_token,
|
|
189
|
+
// });
|
|
190
|
+
},
|
|
191
|
+
};
|
|
192
|
+
};
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import { Link, type LinkProps, useLocation } from "react-router-dom";
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Link that scrolls to anchor even if the hash is already set in the URL.
|
|
6
|
+
*/
|
|
7
|
+
export const AnchorLink = (props: LinkProps) => {
|
|
8
|
+
const location = useLocation();
|
|
9
|
+
const hash = typeof props.to === "string" ? props.to : props.to.hash;
|
|
10
|
+
|
|
11
|
+
const handleClick = (event: React.MouseEvent<HTMLAnchorElement>) => {
|
|
12
|
+
if (!hash?.startsWith("#") || hash !== location.hash) return;
|
|
13
|
+
|
|
14
|
+
event.preventDefault();
|
|
15
|
+
document.getElementById(hash.slice(1))?.scrollIntoView();
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
return <Link onClick={handleClick} {...props} />;
|
|
19
|
+
};
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { ReactNode } from "react";
|
|
2
|
+
import { cx } from "class-variance-authority";
|
|
3
|
+
|
|
4
|
+
export const CategoryHeading = ({
|
|
5
|
+
children,
|
|
6
|
+
className,
|
|
7
|
+
}: {
|
|
8
|
+
children: ReactNode;
|
|
9
|
+
className?: string;
|
|
10
|
+
}) => {
|
|
11
|
+
return (
|
|
12
|
+
<div className={cx("text-sm font-semibold text-primary mb-2", className)}>
|
|
13
|
+
{children}
|
|
14
|
+
</div>
|
|
15
|
+
);
|
|
16
|
+
};
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
// import { type LucideProps } from "lucide-react";
|
|
2
|
+
// import dynamicIconImports from "lucide-react/dynamicIconImports.js";
|
|
3
|
+
// import { Suspense, lazy, memo } from "react";
|
|
4
|
+
// import { cn } from "../util/cn.js";
|
|
5
|
+
|
|
6
|
+
// export type IconName = keyof typeof dynamicIconImports;
|
|
7
|
+
|
|
8
|
+
// const IconNames = Object.keys(dynamicIconImports) as IconName[];
|
|
9
|
+
|
|
10
|
+
// export const isValidIcon = (name: unknown): name is IconName =>
|
|
11
|
+
// typeof name === "string" && IconNames.includes(name as IconName);
|
|
12
|
+
|
|
13
|
+
// type IconProps = Omit<LucideProps, "ref"> & {
|
|
14
|
+
// name: IconName;
|
|
15
|
+
// inline?: boolean;
|
|
16
|
+
// };
|
|
17
|
+
|
|
18
|
+
// const Fallback = ({
|
|
19
|
+
// inline,
|
|
20
|
+
// size,
|
|
21
|
+
// }: {
|
|
22
|
+
// inline?: boolean;
|
|
23
|
+
// size?: string | number;
|
|
24
|
+
// }) => (
|
|
25
|
+
// <span
|
|
26
|
+
// className={cn(inline ? "inline-block" : "block", "bg-background")}
|
|
27
|
+
// style={{ height: size, width: size }}
|
|
28
|
+
// role="presentation"
|
|
29
|
+
// />
|
|
30
|
+
// );
|
|
31
|
+
|
|
32
|
+
// export const DynamicIcon = memo(function ({
|
|
33
|
+
// name,
|
|
34
|
+
// inline,
|
|
35
|
+
// className,
|
|
36
|
+
// size = 16,
|
|
37
|
+
// ...props
|
|
38
|
+
// }: IconProps) {
|
|
39
|
+
// const LucideIcon = lazy(dynamicIconImports[name]);
|
|
40
|
+
|
|
41
|
+
// return (
|
|
42
|
+
// <Suspense fallback={<Fallback inline={inline} size={size} />}>
|
|
43
|
+
// <LucideIcon
|
|
44
|
+
// {...props}
|
|
45
|
+
// size={size}
|
|
46
|
+
// className={cn(inline && "inline-block align-[-0.125em]", className)}
|
|
47
|
+
// />
|
|
48
|
+
// </Suspense>
|
|
49
|
+
// );
|
|
50
|
+
// });
|
|
51
|
+
|
|
52
|
+
export type IconName = string;
|
|
53
|
+
|
|
54
|
+
export function isValidIcon(name: unknown): name is IconName {
|
|
55
|
+
return true;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
export const DynamicIcon = (props: { name: string; size?: number }) => (
|
|
59
|
+
<div></div>
|
|
60
|
+
);
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import { MoonStarIcon, SearchIcon, SunIcon } from "lucide-react";
|
|
2
|
+
import { memo } from "react";
|
|
3
|
+
import { useDevPortalState } from "../core/DevPortalContext.js";
|
|
4
|
+
import { TopNavigation } from "./TopNavigation.js";
|
|
5
|
+
import { useDevPortal } from "./context/DevPortalProvider.js";
|
|
6
|
+
import { useTheme } from "./context/ThemeContext.js";
|
|
7
|
+
|
|
8
|
+
export const Header = memo(() => {
|
|
9
|
+
const [isDark, toggleTheme] = useTheme();
|
|
10
|
+
const { isLoggedIn, email } = useDevPortalState();
|
|
11
|
+
const { login, logout, meta } = useDevPortal();
|
|
12
|
+
|
|
13
|
+
const ThemeIcon = isDark ? MoonStarIcon : SunIcon;
|
|
14
|
+
|
|
15
|
+
return (
|
|
16
|
+
<header className="fixed top-0 w-full z-10 bg-background/80 backdrop-blur">
|
|
17
|
+
<div className="max-w-screen-2xl mx-auto">
|
|
18
|
+
<div className="grid grid-cols-[calc(var(--side-nav-width))_1fr] lg:gap-12 items-center border-b border-border px-12 h-[--top-header-height]">
|
|
19
|
+
<div className="flex items-center gap-3.5">
|
|
20
|
+
{meta?.logo && (
|
|
21
|
+
<img src={meta.logo} alt="My Dev Portal" className="h-10" />
|
|
22
|
+
)}
|
|
23
|
+
<span className="font-bold text-2xl text-foreground/85 tracking-wide">
|
|
24
|
+
{meta?.headerTitle}
|
|
25
|
+
</span>
|
|
26
|
+
</div>
|
|
27
|
+
<div className="grid grid-cols-[--sidecar-grid-cols] items-center gap-8">
|
|
28
|
+
<div className="w-full max-w-prose mx-auto">
|
|
29
|
+
<button className="flex items-center border border-input hover:bg-accent hover:text-accent-foreground p-4 relative h-8 justify-start rounded-lg bg-background text-sm text-muted-foreground shadow-none w-40 sm:w-72">
|
|
30
|
+
<div className="flex items-center gap-2 flex-grow">
|
|
31
|
+
<SearchIcon size={14} />
|
|
32
|
+
Search
|
|
33
|
+
</div>
|
|
34
|
+
<kbd className="absolute right-[0.3rem] top-[0.3rem] hidden h-5 select-none items-center gap-1 rounded border border-border bg-muted px-1.5 font-mono text-[11px] font-medium opacity-100 sm:flex">
|
|
35
|
+
⌘K
|
|
36
|
+
</kbd>
|
|
37
|
+
</button>
|
|
38
|
+
</div>
|
|
39
|
+
<div className="items-center justify-self-end text-sm hidden lg:flex">
|
|
40
|
+
{!isLoggedIn ? (
|
|
41
|
+
<button
|
|
42
|
+
className="cursor-pointer hover:bg-secondary p-1 px-2 mx-2 rounded"
|
|
43
|
+
onClick={logout}
|
|
44
|
+
>
|
|
45
|
+
Logout {email ? `(${email})` : null}
|
|
46
|
+
</button>
|
|
47
|
+
) : (
|
|
48
|
+
<button
|
|
49
|
+
className="cursor-pointer hover:bg-secondary p-1 px-2 mx-2 rounded"
|
|
50
|
+
onClick={login}
|
|
51
|
+
>
|
|
52
|
+
Login
|
|
53
|
+
</button>
|
|
54
|
+
)}
|
|
55
|
+
|
|
56
|
+
<button
|
|
57
|
+
className="cursor-pointer hover:bg-secondary p-2.5 -m-2.5 rounded-full"
|
|
58
|
+
onClick={toggleTheme}
|
|
59
|
+
>
|
|
60
|
+
<ThemeIcon size={18} />
|
|
61
|
+
</button>
|
|
62
|
+
</div>
|
|
63
|
+
</div>
|
|
64
|
+
</div>
|
|
65
|
+
<TopNavigation />
|
|
66
|
+
</div>
|
|
67
|
+
</header>
|
|
68
|
+
);
|
|
69
|
+
});
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import { Suspense, useEffect, useRef, type ReactNode } from "react";
|
|
2
|
+
import { Outlet, useLocation } from "react-router-dom";
|
|
3
|
+
import { Helmet } from "../core/helmet.js";
|
|
4
|
+
import { useScrollToAnchor } from "../util/useScrollToAnchor.js";
|
|
5
|
+
import { useScrollToTop } from "../util/useScrollToTop.js";
|
|
6
|
+
import { Header } from "./Header.js";
|
|
7
|
+
import { useDevPortal } from "./context/DevPortalProvider.js";
|
|
8
|
+
import { useViewportAnchor } from "./context/ViewportAnchorContext.js";
|
|
9
|
+
import { SideNavigation } from "./navigation/SideNavigation.js";
|
|
10
|
+
import { SideNavigationWrapper } from "./navigation/SideNavigationWrapper.js";
|
|
11
|
+
|
|
12
|
+
export const Layout = ({ children }: { children?: ReactNode }) => {
|
|
13
|
+
const location = useLocation();
|
|
14
|
+
const { setActiveAnchor } = useViewportAnchor();
|
|
15
|
+
const { meta, handleAuthenticationResponse } = useDevPortal();
|
|
16
|
+
|
|
17
|
+
useEffect(() => {
|
|
18
|
+
void handleAuthenticationResponse(location);
|
|
19
|
+
}, [handleAuthenticationResponse, location]);
|
|
20
|
+
|
|
21
|
+
useScrollToAnchor();
|
|
22
|
+
useScrollToTop();
|
|
23
|
+
|
|
24
|
+
const previousLocationPath = useRef(location.pathname);
|
|
25
|
+
|
|
26
|
+
useEffect(() => {
|
|
27
|
+
// always reset on location change
|
|
28
|
+
if (location.pathname !== previousLocationPath.current) {
|
|
29
|
+
setActiveAnchor("");
|
|
30
|
+
}
|
|
31
|
+
previousLocationPath.current = location.pathname;
|
|
32
|
+
}, [location.pathname, setActiveAnchor]);
|
|
33
|
+
|
|
34
|
+
return (
|
|
35
|
+
<>
|
|
36
|
+
<Helmet titleTemplate={meta?.pageTitle}>
|
|
37
|
+
<title>Home</title>
|
|
38
|
+
{meta?.description && (
|
|
39
|
+
<meta name="description" content={meta.description} />
|
|
40
|
+
)}
|
|
41
|
+
{meta?.favicon && <link rel="icon" href={meta.favicon} />}
|
|
42
|
+
</Helmet>
|
|
43
|
+
<Header />
|
|
44
|
+
<div className="max-w-screen-2xl mx-auto pt-[--header-height] px-10 lg:px-12">
|
|
45
|
+
<Suspense
|
|
46
|
+
fallback={<SideNavigationWrapper>Loading...</SideNavigationWrapper>}
|
|
47
|
+
>
|
|
48
|
+
<SideNavigation />
|
|
49
|
+
</Suspense>
|
|
50
|
+
<main className="dark:border-white/10 lg:overflow-visible translate-x-0 lg:w-[calc(100%-var(--side-nav-width))] lg:translate-x-[--side-nav-width] pl-12">
|
|
51
|
+
{children ?? <Outlet />}
|
|
52
|
+
</main>
|
|
53
|
+
</div>
|
|
54
|
+
</>
|
|
55
|
+
);
|
|
56
|
+
};
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import ReactMarkdown from "react-markdown";
|
|
2
|
+
import remarkGfm from "remark-gfm";
|
|
3
|
+
import { visit } from "unist-util-visit";
|
|
4
|
+
import { MdxComponents } from "../util/MdxComponents.js";
|
|
5
|
+
|
|
6
|
+
// same as in packages/dev-portal/framework/vite.ts
|
|
7
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
8
|
+
const rehypeCodeBlockPlugin = () => (tree: any) => {
|
|
9
|
+
visit(tree, "element", (node, _index, parent) => {
|
|
10
|
+
if (node.tagName === "code") {
|
|
11
|
+
node.properties.inline = parent?.tagName !== "pre";
|
|
12
|
+
}
|
|
13
|
+
});
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
const remarkPlugins = [remarkGfm];
|
|
17
|
+
const rehypePlugins = [rehypeCodeBlockPlugin];
|
|
18
|
+
|
|
19
|
+
// other styles are defined in main.css .prose
|
|
20
|
+
export const ProseClasses = "prose dark:prose-invert prose-neutral";
|
|
21
|
+
|
|
22
|
+
export const Markdown = ({
|
|
23
|
+
content,
|
|
24
|
+
className,
|
|
25
|
+
}: {
|
|
26
|
+
content: string;
|
|
27
|
+
className?: string;
|
|
28
|
+
}) => (
|
|
29
|
+
<ReactMarkdown
|
|
30
|
+
remarkPlugins={remarkPlugins}
|
|
31
|
+
rehypePlugins={rehypePlugins}
|
|
32
|
+
components={MdxComponents}
|
|
33
|
+
className={className}
|
|
34
|
+
>
|
|
35
|
+
{content}
|
|
36
|
+
</ReactMarkdown>
|
|
37
|
+
);
|