From 3dc2f160eaf8cd6030e0dfa9d82e8681dd2697f5 Mon Sep 17 00:00:00 2001 From: fentas Date: Fri, 8 Aug 2025 00:24:52 +0200 Subject: [PATCH] feat: initialize documentation site with UI components and theme customization --- .bin/b.yaml | 7 +- .envrc | 2 +- .github/workflows/docs.yml | 67 + README.md | 13 +- logo.svg | 6 + pkg/binaries/argsh/argsh.go | 2 +- pkg/cli/cli.go | 4 +- pkg/cli/init.go | 11 +- pkg/cli/install.go | 10 +- pkg/cli/shared.go | 4 +- pkg/cli/version_test.go | 22 +- pkg/state/config.go | 20 +- pkg/state/types.go | 39 +- test/TESTING_PLAN.md | 2 +- test/e2e/main_test.go | 13 +- test/testutil/helpers.go | 2 +- www/.eslintrc.js | 10 + www/.gitignore | 11 + www/.prettierrc | 8 + www/.yarnrc.yml | 1 + www/README.md | 11 + www/apps/docs/.content.eslintrc.js | 6 + www/apps/docs/.env.sample | 10 + www/apps/docs/.eslintrc.js | 8 + www/apps/docs/.gitignore | 29 + www/apps/docs/README.md | 13 + www/apps/docs/announcement.json | 1 + www/apps/docs/babel.config.js | 4 + www/apps/docs/content/about.md | 47 + www/apps/docs/content/b/overview.mdx | 94 + .../docs/content/b/subcommands/completion.mdx | 129 + www/apps/docs/content/b/subcommands/init.mdx | 89 + .../docs/content/b/subcommands/install.mdx | 85 + www/apps/docs/content/b/subcommands/list.mdx | 73 + .../docs/content/b/subcommands/request.mdx | 52 + .../docs/content/b/subcommands/search.mdx | 44 + .../docs/content/b/subcommands/update.mdx | 84 + .../docs/content/b/subcommands/version.mdx | 113 + www/apps/docs/content/contribution/b.md | 75 + www/apps/docs/content/contribution/docs.md | 492 + www/apps/docs/content/getting-started.mdx | 137 + www/apps/docs/content/glossary.mdx | 71 + www/apps/docs/content/homepage.mdx | 103 + www/apps/docs/content/troubleshooting.mdx | 262 + www/apps/docs/docusaurus.config.js | 283 + www/apps/docs/package.json | 83 + www/apps/docs/sidebars.js | 184 + .../src/components/BorderedIcon/index.tsx | 33 + .../src/components/CloudinaryImage/index.tsx | 106 + .../docs/src/components/DetailsList/index.tsx | 34 + .../components/Diagram2CodeSpecs/index.tsx | 54 + .../components/DocSidebarItemIcon/index.tsx | 48 + .../docs/src/components/Feedback/index.tsx | 28 + .../components/Footer/SocialLinks/index.tsx | 44 + .../docs/src/components/Glossary/index.tsx | 50 + .../docs/src/components/LargeCard/index.tsx | 98 + .../src/components/LargeCardList/index.tsx | 30 + .../docs/src/components/MobileLogo/index.tsx | 79 + .../src/components/Navbar/Actions/index.tsx | 80 + .../components/ParameterTypes/Items/index.tsx | 291 + .../src/components/ParameterTypes/index.tsx | 45 + .../docs/src/components/QueryNote/index.tsx | 29 + .../components/StructuredData/HowTo/index.tsx | 44 + www/apps/docs/src/components/UiIcon/index.tsx | 27 + www/apps/docs/src/css/_docusaurus.css | 287 + www/apps/docs/src/css/_variables.css | 144 + www/apps/docs/src/css/components/sidebar.css | 156 + www/apps/docs/src/css/components/toc.css | 60 + www/apps/docs/src/css/components/tooltip.css | 10 + www/apps/docs/src/css/custom.css | 149 + .../index.js | 118 + .../src/providers/DocsProviders/index.tsx | 38 + .../docs/src/providers/LearningPath/index.tsx | 256 + www/apps/docs/src/providers/Search/index.tsx | 73 + www/apps/docs/src/providers/Sidebar/index.tsx | 102 + .../docs/src/theme/Admonition/Icon/Danger.tsx | 19 + .../docs/src/theme/Admonition/Icon/Info.tsx | 7 + .../docs/src/theme/Admonition/Icon/Note.tsx | 19 + .../docs/src/theme/Admonition/Icon/Tip.tsx | 7 + .../src/theme/Admonition/Icon/Warning.tsx | 7 + .../src/theme/Admonition/Layout/index.tsx | 86 + .../src/theme/Admonition/Type/Caution.tsx | 34 + .../docs/src/theme/Admonition/Type/Danger.tsx | 32 + .../docs/src/theme/Admonition/Type/Info.tsx | 32 + .../docs/src/theme/Admonition/Type/Note.tsx | 32 + .../docs/src/theme/Admonition/Type/Tip.tsx | 32 + .../src/theme/Admonition/Type/Warning.tsx | 32 + .../AnnouncementBar/CloseButton/index.tsx | 33 + .../theme/AnnouncementBar/Content/index.tsx | 29 + .../docs/src/theme/AnnouncementBar/index.tsx | 52 + .../docs/src/theme/BackToTopButton/index.tsx | 33 + .../src/theme/CodeBlock/Content/String.tsx | 153 + www/apps/docs/src/theme/CodeBlock/index.tsx | 101 + www/apps/docs/src/theme/Details/index.tsx | 26 + www/apps/docs/src/theme/DocCard/index.tsx | 245 + www/apps/docs/src/theme/DocCardList/index.tsx | 39 + .../docs/src/theme/DocItem/Content/index.tsx | 66 + .../docs/src/theme/DocItem/Footer/index.tsx | 28 + .../docs/src/theme/DocItem/Layout/index.tsx | 77 + .../src/theme/DocRoot/Layout/Main/index.tsx | 32 + .../theme/DocRoot/Layout/Sidebar/index.tsx | 105 + .../docs/src/theme/DocRoot/Layout/index.tsx | 35 + www/apps/docs/src/theme/DocRoot/index.tsx | 33 + .../src/theme/DocSidebar/Desktop/index.tsx | 95 + .../theme/DocSidebarItem/Category/index.tsx | 244 + .../src/theme/DocSidebarItem/Html/index.tsx | 67 + .../src/theme/DocSidebarItem/Link/index.tsx | 85 + www/apps/docs/src/theme/DocsRoot/index.tsx | 21 + .../docs/src/theme/EditThisPage/index.tsx | 27 + .../docs/src/theme/Footer/Layout/index.tsx | 51 + www/apps/docs/src/theme/Icon/Beaker/index.tsx | 27 + .../src/theme/Icon/CircleDottedLine/index.tsx | 62 + www/apps/docs/src/theme/Icon/Close/index.tsx | 9 + www/apps/docs/src/theme/Icon/Copy/index.tsx | 9 + .../docs/src/theme/Icon/DarkMode/index.tsx | 9 + .../docs/src/theme/Icon/Discord/index.tsx | 24 + .../src/theme/Icon/ExternalLink/index.tsx | 9 + .../docs/src/theme/Icon/FlagMini/index.tsx | 27 + www/apps/docs/src/theme/Icon/GitHub/index.tsx | 26 + .../docs/src/theme/Icon/LightMode/index.tsx | 9 + .../docs/src/theme/Icon/LinkedIn/index.tsx | 24 + www/apps/docs/src/theme/Icon/Nextjs/index.tsx | 28 + .../docs/src/theme/Icon/PuzzleSolid/index.tsx | 24 + .../docs/src/theme/Icon/Twitter/index.tsx | 24 + www/apps/docs/src/theme/Icon/index.tsx | 222 + www/apps/docs/src/theme/Layout/index.tsx | 75 + www/apps/docs/src/theme/MDXComponents/A.tsx | 48 + .../docs/src/theme/MDXComponents/Code.tsx | 17 + .../docs/src/theme/MDXComponents/Details.tsx | 27 + www/apps/docs/src/theme/MDXComponents/H1.tsx | 28 + .../docs/src/theme/MDXComponents/index.tsx | 25 + .../theme/Navbar/ColorModeToggle/index.tsx | 25 + .../docs/src/theme/Navbar/Content/index.tsx | 167 + .../docs/src/theme/Navbar/Layout/index.tsx | 44 + www/apps/docs/src/theme/Navbar/Logo/index.tsx | 20 + .../Navbar/MobileSidebar/Header/index.tsx | 43 + .../Navbar/MobileSidebar/Layout/index.tsx | 23 + .../Navbar/MobileSidebar/Toggle/index.tsx | 25 + .../docs/src/theme/Navbar/Search/index.tsx | 10 + .../src/theme/NavbarItem/NavbarNavLink.tsx | 55 + .../src/theme/NavbarItem/SearchNavbarItem.tsx | 17 + .../docs/src/theme/NotFound/Content/index.tsx | 47 + www/apps/docs/src/theme/NotFound/index.tsx | 21 + www/apps/docs/src/theme/SearchBar/index.tsx | 51 + .../src/theme/SearchTranslations/index.ts | 12 + www/apps/docs/src/theme/TOCItems/index.tsx | 22 + www/apps/docs/src/theme/Tabs/index.tsx | 280 + www/apps/docs/src/types/global.d.ts | 6 + www/apps/docs/src/types/index.d.ts | 217 + .../src/utils/createLatestReleaseRedirects.js | 63 + www/apps/docs/src/utils/decode-str.ts | 8 + .../docs/src/utils/exclude-sidebar-results.js | 17 + www/apps/docs/src/utils/filter-list-items.ts | 33 + .../docs/src/utils/get-first-category-item.ts | 25 + www/apps/docs/src/utils/get-os-shortcut.ts | 8 + www/apps/docs/src/utils/glossary.ts | 17 + www/apps/docs/src/utils/is-in-view.ts | 10 + www/apps/docs/src/utils/reverse-sidebar.js | 27 + www/apps/docs/src/utils/specs.ts | 1 + www/apps/docs/static/.nojekyll | 0 .../docs/static/android-chrome-192x192.png | Bin 0 -> 9351 bytes .../docs/static/android-chrome-512x512.png | Bin 0 -> 29826 bytes www/apps/docs/static/apple-touch-icon.png | Bin 0 -> 8527 bytes www/apps/docs/static/favicon.ico | Bin 0 -> 8254 bytes www/apps/docs/static/icon.svg | 6 + .../docs/static/img/.bak/admin-icon-dark.svg | 3 + www/apps/docs/static/img/.bak/admin-icon.svg | 3 + .../docs/static/img/.bak/announcement-bg.svg | 15 + www/apps/docs/static/img/.bak/bell-dark.png | Bin 0 -> 1540 bytes .../docs/static/img/.bak/cart-icon-dark.svg | 6 + www/apps/docs/static/img/.bak/cart-icon.svg | 6 + .../static/img/.bak/dev-env-icon-dark.svg | 3 + .../docs/static/img/.bak/dev-env-icon.svg | 3 + www/apps/docs/static/img/.bak/docs-meta.jpg | Bin 0 -> 260101 bytes .../img/.bak/fast-delivery-icon-dark.svg | 8 + .../static/img/.bak/fast-delivery-icon.svg | 8 + www/apps/docs/static/img/.bak/favicon.ico | Bin 0 -> 103548 bytes .../docs/static/img/.bak/gatsby-icon-dark.svg | 3 + www/apps/docs/static/img/.bak/gatsby-icon.svg | 3 + .../static/img/.bak/learning-path-img.png | Bin 0 -> 1842 bytes www/apps/docs/static/img/.bak/light-beam.png | Bin 0 -> 34642 bytes .../docs/static/img/.bak/link-icon-light.svg | 4 + www/apps/docs/static/img/.bak/link-icon.svg | 4 + .../docs/static/img/.bak/logo-icon-dark.png | Bin 0 -> 570 bytes www/apps/docs/static/img/.bak/logo-icon.png | Bin 0 -> 921 bytes .../docs/static/img/.bak/logo-mobile-dark.png | Bin 0 -> 6945 bytes www/apps/docs/static/img/.bak/logo-mobile.png | Bin 0 -> 8186 bytes .../static/img/.bak/magnifying-glass-dark.svg | 5 + .../docs/static/img/.bak/magnifying-glass.svg | 5 + .../docs/static/img/.bak/nextjs-icon-dark.svg | 3 + www/apps/docs/static/img/.bak/nextjs-icon.svg | 3 + .../img/.bak/payment-accepted-icon-dark.svg | 6 + .../static/img/.bak/payment-accepted-icon.svg | 6 + .../img/.bak/search-hit-arrow-light.svg | 4 + .../docs/static/img/.bak/search-hit-arrow.svg | 4 + .../docs/static/img/.bak/search-hit-light.svg | 5 + www/apps/docs/static/img/.bak/search-hit.png | Bin 0 -> 774 bytes www/apps/docs/static/img/.bak/search-hit.svg | 5 + .../img/.bak/search-no-result-light.svg | 5 + .../docs/static/img/.bak/search-no-result.svg | 5 + .../docs/static/img/.bak/server-icon-dark.svg | 3 + www/apps/docs/static/img/.bak/server-icon.svg | 3 + www/apps/docs/static/img/.bak/stardust.png | Bin 0 -> 2089 bytes .../docs/static/img/.bak/stripe-icon-dark.svg | 3 + www/apps/docs/static/img/.bak/stripe-icon.svg | 3 + .../docs/static/img/.bak/tee-icon-dark.svg | 5 + www/apps/docs/static/img/.bak/tee-icon.svg | 5 + .../static/img/.bak/terminal-icon-dark.svg | 6 + .../docs/static/img/.bak/terminal-icon.svg | 6 + .../docs/static/img/.bak/user-guide-dark.svg | 3 + www/apps/docs/static/img/.bak/user-guide.svg | 3 + www/apps/docs/static/img/diagrams-bg.png | Bin 0 -> 2620 bytes www/apps/docs/static/img/logo-icon-dark.svg | 6 + www/apps/docs/static/img/logo-icon.svg | 7 + www/apps/docs/static/img/side-menu-light.svg | 3 + www/apps/docs/static/img/side-menu.svg | 3 + .../static/img/small-squares-bg-light.svg | 47 + www/apps/docs/static/img/small-squares-bg.svg | 47 + www/apps/docs/static/img/squares-bg-light.svg | 32 + www/apps/docs/static/img/squares-bg.svg | 32 + www/apps/docs/static/manifest.webmanifest | 14 + www/apps/docs/static/robots.txt | 4 + www/apps/docs/tailwind.config.js | 30 + www/ignore-build-script.sh | 22 + www/package.json | 34 + www/packages/docs-ui/.eslintrc.js | 10 + www/packages/docs-ui/.gitignore | 2 + www/packages/docs-ui/package.json | 74 + www/packages/docs-ui/postcss.config.js | 1 + .../docs-ui/src/components/Badge/index.tsx | 41 + .../docs-ui/src/components/Bordered/index.tsx | 21 + .../src/components/BorderedIcon/index.tsx | 51 + .../docs-ui/src/components/Button/index.tsx | 79 + .../docs-ui/src/components/Card/index.tsx | 50 + .../src/components/CodeBlock/index.tsx | 124 + .../docs-ui/src/components/CodeMdx/index.tsx | 29 + .../docs-ui/src/components/CodeTabs/index.tsx | 129 + .../src/components/CopyButton/index.tsx | 44 + .../src/components/Details/Summary/index.tsx | 71 + .../docs-ui/src/components/Details/index.tsx | 131 + .../src/components/ExpandableNotice/index.tsx | 34 + .../components/FeatureFlagNotice/index.tsx | 40 + .../components/Feedback/Solutions/index.tsx | 92 + .../docs-ui/src/components/Feedback/index.tsx | 268 + .../components/Icons/QuestionMark/index.tsx | 23 + .../src/components/Icons/ThumbDown/index.tsx | 23 + .../src/components/Icons/ThumbUp/index.tsx | 23 + .../docs-ui/src/components/Icons/index.tsx | 3 + .../src/components/InlineCode/index.tsx | 30 + .../src/components/Input/Text/index.tsx | 40 + .../docs-ui/src/components/Kbd/index.tsx | 23 + .../docs-ui/src/components/Label/index.tsx | 19 + .../docs-ui/src/components/Link/index.tsx | 23 + .../src/components/Loading/Dots/index.tsx | 16 + .../src/components/Loading/Spinner/index.tsx | 19 + .../docs-ui/src/components/Loading/index.tsx | 43 + .../src/components/MarkdownContent/index.tsx | 105 + .../src/components/Modal/Footer/index.tsx | 31 + .../src/components/Modal/Header/index.tsx | 31 + .../docs-ui/src/components/Modal/index.tsx | 123 + .../Navbar/ColorModeToggle/index.tsx | 23 + .../components/Navbar/IconButton/index.tsx | 24 + .../src/components/Navbar/Link/index.tsx | 45 + .../src/components/Navbar/Logo/index.tsx | 34 + .../Navbar/MobileMenu/Button/index.tsx | 35 + .../components/Navbar/MobileMenu/index.tsx | 54 + .../Navbar/SearchModalOpener/index.tsx | 17 + .../docs-ui/src/components/Navbar/index.tsx | 67 + .../docs-ui/src/components/NextLink/index.tsx | 26 + .../Item/Layout/Default/index.tsx | 84 + .../components/Notification/Item/index.tsx | 63 + .../src/components/Notification/index.tsx | 71 + .../docs-ui/src/components/Rating/index.tsx | 130 + .../Search/EmptyQueryBoundary/index.tsx | 22 + .../Search/Hits/GroupName/index.tsx | 20 + .../src/components/Search/Hits/index.tsx | 226 + .../components/Search/ModalOpener/index.tsx | 91 + .../src/components/Search/NoResults/index.tsx | 19 + .../Search/Suggestions/Item/index.tsx | 32 + .../components/Search/Suggestions/index.tsx | 64 + .../docs-ui/src/components/Search/index.tsx | 215 + .../src/components/Select/Badge/index.tsx | 127 + .../src/components/Select/Dropdown/index.tsx | 144 + .../src/components/Select/Input/index.tsx | 123 + .../docs-ui/src/components/Select/index.ts | 13 + .../src/components/Sidebar/Item/index.tsx | 122 + .../docs-ui/src/components/Sidebar/index.tsx | 63 + .../docs-ui/src/components/TextArea/index.tsx | 30 + .../docs-ui/src/components/Tooltip/index.tsx | 59 + www/packages/docs-ui/src/components/index.ts | 54 + www/packages/docs-ui/src/constants.ts | 2 + www/packages/docs-ui/src/hooks/index.tsx | 6 + .../docs-ui/src/hooks/use-copy/index.tsx | 26 + .../src/hooks/use-keyboard-shortcut/index.tsx | 72 + .../src/hooks/use-scroll-utils/index.tsx | 287 + .../src/hooks/use-search-navigation/index.ts | 144 + .../docs-ui/src/hooks/use-select/index.tsx | 91 + .../docs-ui/src/hooks/use-tabs/index.tsx | 92 + www/packages/docs-ui/src/index.ts | 7 + www/packages/docs-ui/src/main.css | 0 .../docs-ui/src/providers/Analytics/index.tsx | 147 + .../docs-ui/src/providers/ColorMode/index.tsx | 74 + .../docs-ui/src/providers/Mobile/index.tsx | 63 + .../docs-ui/src/providers/Modal/index.tsx | 53 + .../docs-ui/src/providers/Navbar/index.tsx | 55 + .../src/providers/Notification/index.tsx | 137 + .../src/providers/PageLoading/index.tsx | 39 + .../docs-ui/src/providers/Search/index.tsx | 173 + .../docs-ui/src/providers/Sidebar/index.tsx | 326 + www/packages/docs-ui/src/providers/index.ts | 9 + www/packages/docs-ui/src/types/index.ts | 3 + .../docs-ui/src/utils/array-same-elms.ts | 10 + www/packages/docs-ui/src/utils/capitalize.ts | 3 + .../utils/check-sidebar-item-visibility.ts | 21 + www/packages/docs-ui/src/utils/dom-utils.ts | 29 + .../docs-ui/src/utils/format-report-link.ts | 17 + .../docs-ui/src/utils/get-scrolled-top.ts | 8 + www/packages/docs-ui/src/utils/index.ts | 8 + .../docs-ui/src/utils/is-elm-window.ts | 3 + www/packages/docs-ui/src/utils/swr-fetcher.ts | 7 + www/packages/docs-ui/tailwind.config.js | 7 + www/packages/docs-ui/tsconfig.cjs.json | 12 + www/packages/docs-ui/tsconfig.esm.json | 12 + www/packages/docs-ui/tsconfig.json | 29 + www/packages/eslint-config-docs/base.js | 136 + www/packages/eslint-config-docs/content.js | 111 + www/packages/eslint-config-docs/docusaurus.js | 14 + www/packages/eslint-config-docs/next.js | 21 + www/packages/eslint-config-docs/package.json | 24 + www/packages/tailwind/.eslintrc.js | 9 + www/packages/tailwind/base.tailwind.config.js | 755 + .../tailwind/modified.tailwind.config.js | 33 + www/packages/tailwind/package.json | 24 + www/packages/tailwind/postcss.config.js | 6 + www/packages/tailwind/tailwind.config.js | 12 + www/packages/tailwind/theme-presets.js | 194 + www/packages/tsconfig/base.json | 29 + www/packages/tsconfig/docusaurus.json | 14 + www/packages/tsconfig/nextjs.json | 13 + www/packages/tsconfig/package.json | 12 + www/tsconfig.json | 6 + www/turbo.json | 31 + www/vale/get-files.sh | 23 + www/vale/run-vale.sh | 28 + .../config/vocabularies/Base/accept.txt | 5 + .../config/vocabularies/Base/reject.txt | 0 www/vale/styles/docs/Acronyms.yml | 80 + www/vale/styles/docs/ComplexWords.yml | 120 + www/vale/styles/docs/Contractions.yml | 49 + www/vale/styles/docs/FirstPerson.yml | 16 + www/vale/styles/docs/Foreign.yml | 11 + www/vale/styles/docs/Gender.yml | 7 + www/vale/styles/docs/HeadingColons.yml | 8 + www/vale/styles/docs/HeadingPunctuation.yml | 13 + www/vale/styles/docs/Npm2Yarn.yml | 8 + www/vale/styles/docs/NpmCommands.yml | 11 + www/vale/styles/docs/NpmGlobal.yml | 8 + www/vale/styles/docs/Numbers.yml | 14 + www/vale/styles/docs/Ordinal.yml | 12 + www/vale/styles/docs/Our.yml | 7 + www/vale/styles/docs/OxfordComma.yml | 8 + www/vale/styles/docs/Passive.yml | 183 + www/vale/styles/docs/Percentages.yml | 7 + www/vale/styles/docs/SentenceLength.yml | 7 + www/vale/styles/docs/Spacing.yml | 7 + www/vale/styles/docs/Terms.yml | 8 + www/vale/styles/docs/TypeScript.yml | 7 + www/vale/styles/docs/We.yml | 10 + www/vale/styles/docs/Wordiness.yml | 122 + www/vale/styles/docs/WritingLevel.yml | 9 + www/vale/styles/write-good/Cliches.yml | 702 + www/vale/styles/write-good/E-Prime.yml | 32 + www/vale/styles/write-good/Illusions.yml | 11 + www/vale/styles/write-good/Passive.yml | 183 + www/vale/styles/write-good/README.md | 27 + www/vale/styles/write-good/So.yml | 5 + www/vale/styles/write-good/ThereIs.yml | 6 + www/vale/styles/write-good/TooWordy.yml | 220 + www/vale/styles/write-good/Weasel.yml | 207 + www/vale/styles/write-good/meta.json | 4 + www/yarn.lock | 17050 ++++++++++++++++ 381 files changed, 36417 insertions(+), 61 deletions(-) create mode 100644 .github/workflows/docs.yml create mode 100644 logo.svg create mode 100644 www/.eslintrc.js create mode 100644 www/.gitignore create mode 100644 www/.prettierrc create mode 100644 www/.yarnrc.yml create mode 100644 www/README.md create mode 100644 www/apps/docs/.content.eslintrc.js create mode 100644 www/apps/docs/.env.sample create mode 100644 www/apps/docs/.eslintrc.js create mode 100644 www/apps/docs/.gitignore create mode 100644 www/apps/docs/README.md create mode 100644 www/apps/docs/announcement.json create mode 100644 www/apps/docs/babel.config.js create mode 100644 www/apps/docs/content/about.md create mode 100644 www/apps/docs/content/b/overview.mdx create mode 100644 www/apps/docs/content/b/subcommands/completion.mdx create mode 100644 www/apps/docs/content/b/subcommands/init.mdx create mode 100644 www/apps/docs/content/b/subcommands/install.mdx create mode 100644 www/apps/docs/content/b/subcommands/list.mdx create mode 100644 www/apps/docs/content/b/subcommands/request.mdx create mode 100644 www/apps/docs/content/b/subcommands/search.mdx create mode 100644 www/apps/docs/content/b/subcommands/update.mdx create mode 100644 www/apps/docs/content/b/subcommands/version.mdx create mode 100644 www/apps/docs/content/contribution/b.md create mode 100644 www/apps/docs/content/contribution/docs.md create mode 100644 www/apps/docs/content/getting-started.mdx create mode 100644 www/apps/docs/content/glossary.mdx create mode 100644 www/apps/docs/content/homepage.mdx create mode 100644 www/apps/docs/content/troubleshooting.mdx create mode 100644 www/apps/docs/docusaurus.config.js create mode 100644 www/apps/docs/package.json create mode 100644 www/apps/docs/sidebars.js create mode 100644 www/apps/docs/src/components/BorderedIcon/index.tsx create mode 100644 www/apps/docs/src/components/CloudinaryImage/index.tsx create mode 100644 www/apps/docs/src/components/DetailsList/index.tsx create mode 100644 www/apps/docs/src/components/Diagram2CodeSpecs/index.tsx create mode 100644 www/apps/docs/src/components/DocSidebarItemIcon/index.tsx create mode 100644 www/apps/docs/src/components/Feedback/index.tsx create mode 100644 www/apps/docs/src/components/Footer/SocialLinks/index.tsx create mode 100644 www/apps/docs/src/components/Glossary/index.tsx create mode 100644 www/apps/docs/src/components/LargeCard/index.tsx create mode 100644 www/apps/docs/src/components/LargeCardList/index.tsx create mode 100644 www/apps/docs/src/components/MobileLogo/index.tsx create mode 100644 www/apps/docs/src/components/Navbar/Actions/index.tsx create mode 100644 www/apps/docs/src/components/ParameterTypes/Items/index.tsx create mode 100644 www/apps/docs/src/components/ParameterTypes/index.tsx create mode 100644 www/apps/docs/src/components/QueryNote/index.tsx create mode 100644 www/apps/docs/src/components/StructuredData/HowTo/index.tsx create mode 100644 www/apps/docs/src/components/UiIcon/index.tsx create mode 100644 www/apps/docs/src/css/_docusaurus.css create mode 100644 www/apps/docs/src/css/_variables.css create mode 100644 www/apps/docs/src/css/components/sidebar.css create mode 100644 www/apps/docs/src/css/components/toc.css create mode 100644 www/apps/docs/src/css/components/tooltip.css create mode 100644 www/apps/docs/src/css/custom.css create mode 100644 www/apps/docs/src/plugins/docusaurus-plugin-diagram2code-showcase/index.js create mode 100644 www/apps/docs/src/providers/DocsProviders/index.tsx create mode 100644 www/apps/docs/src/providers/LearningPath/index.tsx create mode 100644 www/apps/docs/src/providers/Search/index.tsx create mode 100644 www/apps/docs/src/providers/Sidebar/index.tsx create mode 100644 www/apps/docs/src/theme/Admonition/Icon/Danger.tsx create mode 100644 www/apps/docs/src/theme/Admonition/Icon/Info.tsx create mode 100644 www/apps/docs/src/theme/Admonition/Icon/Note.tsx create mode 100644 www/apps/docs/src/theme/Admonition/Icon/Tip.tsx create mode 100644 www/apps/docs/src/theme/Admonition/Icon/Warning.tsx create mode 100644 www/apps/docs/src/theme/Admonition/Layout/index.tsx create mode 100644 www/apps/docs/src/theme/Admonition/Type/Caution.tsx create mode 100644 www/apps/docs/src/theme/Admonition/Type/Danger.tsx create mode 100644 www/apps/docs/src/theme/Admonition/Type/Info.tsx create mode 100644 www/apps/docs/src/theme/Admonition/Type/Note.tsx create mode 100644 www/apps/docs/src/theme/Admonition/Type/Tip.tsx create mode 100644 www/apps/docs/src/theme/Admonition/Type/Warning.tsx create mode 100644 www/apps/docs/src/theme/AnnouncementBar/CloseButton/index.tsx create mode 100644 www/apps/docs/src/theme/AnnouncementBar/Content/index.tsx create mode 100644 www/apps/docs/src/theme/AnnouncementBar/index.tsx create mode 100644 www/apps/docs/src/theme/BackToTopButton/index.tsx create mode 100644 www/apps/docs/src/theme/CodeBlock/Content/String.tsx create mode 100644 www/apps/docs/src/theme/CodeBlock/index.tsx create mode 100644 www/apps/docs/src/theme/Details/index.tsx create mode 100644 www/apps/docs/src/theme/DocCard/index.tsx create mode 100644 www/apps/docs/src/theme/DocCardList/index.tsx create mode 100644 www/apps/docs/src/theme/DocItem/Content/index.tsx create mode 100644 www/apps/docs/src/theme/DocItem/Footer/index.tsx create mode 100644 www/apps/docs/src/theme/DocItem/Layout/index.tsx create mode 100644 www/apps/docs/src/theme/DocRoot/Layout/Main/index.tsx create mode 100644 www/apps/docs/src/theme/DocRoot/Layout/Sidebar/index.tsx create mode 100644 www/apps/docs/src/theme/DocRoot/Layout/index.tsx create mode 100644 www/apps/docs/src/theme/DocRoot/index.tsx create mode 100644 www/apps/docs/src/theme/DocSidebar/Desktop/index.tsx create mode 100644 www/apps/docs/src/theme/DocSidebarItem/Category/index.tsx create mode 100644 www/apps/docs/src/theme/DocSidebarItem/Html/index.tsx create mode 100644 www/apps/docs/src/theme/DocSidebarItem/Link/index.tsx create mode 100644 www/apps/docs/src/theme/DocsRoot/index.tsx create mode 100644 www/apps/docs/src/theme/EditThisPage/index.tsx create mode 100644 www/apps/docs/src/theme/Footer/Layout/index.tsx create mode 100644 www/apps/docs/src/theme/Icon/Beaker/index.tsx create mode 100644 www/apps/docs/src/theme/Icon/CircleDottedLine/index.tsx create mode 100644 www/apps/docs/src/theme/Icon/Close/index.tsx create mode 100644 www/apps/docs/src/theme/Icon/Copy/index.tsx create mode 100644 www/apps/docs/src/theme/Icon/DarkMode/index.tsx create mode 100644 www/apps/docs/src/theme/Icon/Discord/index.tsx create mode 100644 www/apps/docs/src/theme/Icon/ExternalLink/index.tsx create mode 100644 www/apps/docs/src/theme/Icon/FlagMini/index.tsx create mode 100644 www/apps/docs/src/theme/Icon/GitHub/index.tsx create mode 100644 www/apps/docs/src/theme/Icon/LightMode/index.tsx create mode 100644 www/apps/docs/src/theme/Icon/LinkedIn/index.tsx create mode 100644 www/apps/docs/src/theme/Icon/Nextjs/index.tsx create mode 100644 www/apps/docs/src/theme/Icon/PuzzleSolid/index.tsx create mode 100644 www/apps/docs/src/theme/Icon/Twitter/index.tsx create mode 100644 www/apps/docs/src/theme/Icon/index.tsx create mode 100644 www/apps/docs/src/theme/Layout/index.tsx create mode 100644 www/apps/docs/src/theme/MDXComponents/A.tsx create mode 100644 www/apps/docs/src/theme/MDXComponents/Code.tsx create mode 100644 www/apps/docs/src/theme/MDXComponents/Details.tsx create mode 100644 www/apps/docs/src/theme/MDXComponents/H1.tsx create mode 100644 www/apps/docs/src/theme/MDXComponents/index.tsx create mode 100644 www/apps/docs/src/theme/Navbar/ColorModeToggle/index.tsx create mode 100644 www/apps/docs/src/theme/Navbar/Content/index.tsx create mode 100644 www/apps/docs/src/theme/Navbar/Layout/index.tsx create mode 100644 www/apps/docs/src/theme/Navbar/Logo/index.tsx create mode 100644 www/apps/docs/src/theme/Navbar/MobileSidebar/Header/index.tsx create mode 100644 www/apps/docs/src/theme/Navbar/MobileSidebar/Layout/index.tsx create mode 100644 www/apps/docs/src/theme/Navbar/MobileSidebar/Toggle/index.tsx create mode 100644 www/apps/docs/src/theme/Navbar/Search/index.tsx create mode 100644 www/apps/docs/src/theme/NavbarItem/NavbarNavLink.tsx create mode 100644 www/apps/docs/src/theme/NavbarItem/SearchNavbarItem.tsx create mode 100644 www/apps/docs/src/theme/NotFound/Content/index.tsx create mode 100644 www/apps/docs/src/theme/NotFound/index.tsx create mode 100644 www/apps/docs/src/theme/SearchBar/index.tsx create mode 100644 www/apps/docs/src/theme/SearchTranslations/index.ts create mode 100644 www/apps/docs/src/theme/TOCItems/index.tsx create mode 100644 www/apps/docs/src/theme/Tabs/index.tsx create mode 100644 www/apps/docs/src/types/global.d.ts create mode 100644 www/apps/docs/src/types/index.d.ts create mode 100644 www/apps/docs/src/utils/createLatestReleaseRedirects.js create mode 100644 www/apps/docs/src/utils/decode-str.ts create mode 100644 www/apps/docs/src/utils/exclude-sidebar-results.js create mode 100644 www/apps/docs/src/utils/filter-list-items.ts create mode 100644 www/apps/docs/src/utils/get-first-category-item.ts create mode 100644 www/apps/docs/src/utils/get-os-shortcut.ts create mode 100644 www/apps/docs/src/utils/glossary.ts create mode 100644 www/apps/docs/src/utils/is-in-view.ts create mode 100644 www/apps/docs/src/utils/reverse-sidebar.js create mode 100644 www/apps/docs/src/utils/specs.ts create mode 100644 www/apps/docs/static/.nojekyll create mode 100644 www/apps/docs/static/android-chrome-192x192.png create mode 100644 www/apps/docs/static/android-chrome-512x512.png create mode 100644 www/apps/docs/static/apple-touch-icon.png create mode 100644 www/apps/docs/static/favicon.ico create mode 100644 www/apps/docs/static/icon.svg create mode 100644 www/apps/docs/static/img/.bak/admin-icon-dark.svg create mode 100644 www/apps/docs/static/img/.bak/admin-icon.svg create mode 100644 www/apps/docs/static/img/.bak/announcement-bg.svg create mode 100644 www/apps/docs/static/img/.bak/bell-dark.png create mode 100644 www/apps/docs/static/img/.bak/cart-icon-dark.svg create mode 100644 www/apps/docs/static/img/.bak/cart-icon.svg create mode 100644 www/apps/docs/static/img/.bak/dev-env-icon-dark.svg create mode 100644 www/apps/docs/static/img/.bak/dev-env-icon.svg create mode 100644 www/apps/docs/static/img/.bak/docs-meta.jpg create mode 100644 www/apps/docs/static/img/.bak/fast-delivery-icon-dark.svg create mode 100644 www/apps/docs/static/img/.bak/fast-delivery-icon.svg create mode 100644 www/apps/docs/static/img/.bak/favicon.ico create mode 100644 www/apps/docs/static/img/.bak/gatsby-icon-dark.svg create mode 100644 www/apps/docs/static/img/.bak/gatsby-icon.svg create mode 100644 www/apps/docs/static/img/.bak/learning-path-img.png create mode 100644 www/apps/docs/static/img/.bak/light-beam.png create mode 100644 www/apps/docs/static/img/.bak/link-icon-light.svg create mode 100644 www/apps/docs/static/img/.bak/link-icon.svg create mode 100644 www/apps/docs/static/img/.bak/logo-icon-dark.png create mode 100644 www/apps/docs/static/img/.bak/logo-icon.png create mode 100644 www/apps/docs/static/img/.bak/logo-mobile-dark.png create mode 100644 www/apps/docs/static/img/.bak/logo-mobile.png create mode 100644 www/apps/docs/static/img/.bak/magnifying-glass-dark.svg create mode 100644 www/apps/docs/static/img/.bak/magnifying-glass.svg create mode 100644 www/apps/docs/static/img/.bak/nextjs-icon-dark.svg create mode 100644 www/apps/docs/static/img/.bak/nextjs-icon.svg create mode 100644 www/apps/docs/static/img/.bak/payment-accepted-icon-dark.svg create mode 100644 www/apps/docs/static/img/.bak/payment-accepted-icon.svg create mode 100644 www/apps/docs/static/img/.bak/search-hit-arrow-light.svg create mode 100644 www/apps/docs/static/img/.bak/search-hit-arrow.svg create mode 100644 www/apps/docs/static/img/.bak/search-hit-light.svg create mode 100644 www/apps/docs/static/img/.bak/search-hit.png create mode 100644 www/apps/docs/static/img/.bak/search-hit.svg create mode 100644 www/apps/docs/static/img/.bak/search-no-result-light.svg create mode 100644 www/apps/docs/static/img/.bak/search-no-result.svg create mode 100644 www/apps/docs/static/img/.bak/server-icon-dark.svg create mode 100644 www/apps/docs/static/img/.bak/server-icon.svg create mode 100644 www/apps/docs/static/img/.bak/stardust.png create mode 100644 www/apps/docs/static/img/.bak/stripe-icon-dark.svg create mode 100644 www/apps/docs/static/img/.bak/stripe-icon.svg create mode 100644 www/apps/docs/static/img/.bak/tee-icon-dark.svg create mode 100644 www/apps/docs/static/img/.bak/tee-icon.svg create mode 100644 www/apps/docs/static/img/.bak/terminal-icon-dark.svg create mode 100644 www/apps/docs/static/img/.bak/terminal-icon.svg create mode 100644 www/apps/docs/static/img/.bak/user-guide-dark.svg create mode 100644 www/apps/docs/static/img/.bak/user-guide.svg create mode 100644 www/apps/docs/static/img/diagrams-bg.png create mode 100644 www/apps/docs/static/img/logo-icon-dark.svg create mode 100644 www/apps/docs/static/img/logo-icon.svg create mode 100644 www/apps/docs/static/img/side-menu-light.svg create mode 100644 www/apps/docs/static/img/side-menu.svg create mode 100644 www/apps/docs/static/img/small-squares-bg-light.svg create mode 100644 www/apps/docs/static/img/small-squares-bg.svg create mode 100644 www/apps/docs/static/img/squares-bg-light.svg create mode 100644 www/apps/docs/static/img/squares-bg.svg create mode 100644 www/apps/docs/static/manifest.webmanifest create mode 100644 www/apps/docs/static/robots.txt create mode 100644 www/apps/docs/tailwind.config.js create mode 100644 www/ignore-build-script.sh create mode 100644 www/package.json create mode 100644 www/packages/docs-ui/.eslintrc.js create mode 100644 www/packages/docs-ui/.gitignore create mode 100644 www/packages/docs-ui/package.json create mode 100644 www/packages/docs-ui/postcss.config.js create mode 100644 www/packages/docs-ui/src/components/Badge/index.tsx create mode 100644 www/packages/docs-ui/src/components/Bordered/index.tsx create mode 100644 www/packages/docs-ui/src/components/BorderedIcon/index.tsx create mode 100644 www/packages/docs-ui/src/components/Button/index.tsx create mode 100644 www/packages/docs-ui/src/components/Card/index.tsx create mode 100644 www/packages/docs-ui/src/components/CodeBlock/index.tsx create mode 100644 www/packages/docs-ui/src/components/CodeMdx/index.tsx create mode 100644 www/packages/docs-ui/src/components/CodeTabs/index.tsx create mode 100644 www/packages/docs-ui/src/components/CopyButton/index.tsx create mode 100644 www/packages/docs-ui/src/components/Details/Summary/index.tsx create mode 100644 www/packages/docs-ui/src/components/Details/index.tsx create mode 100644 www/packages/docs-ui/src/components/ExpandableNotice/index.tsx create mode 100644 www/packages/docs-ui/src/components/FeatureFlagNotice/index.tsx create mode 100644 www/packages/docs-ui/src/components/Feedback/Solutions/index.tsx create mode 100644 www/packages/docs-ui/src/components/Feedback/index.tsx create mode 100644 www/packages/docs-ui/src/components/Icons/QuestionMark/index.tsx create mode 100644 www/packages/docs-ui/src/components/Icons/ThumbDown/index.tsx create mode 100644 www/packages/docs-ui/src/components/Icons/ThumbUp/index.tsx create mode 100644 www/packages/docs-ui/src/components/Icons/index.tsx create mode 100644 www/packages/docs-ui/src/components/InlineCode/index.tsx create mode 100644 www/packages/docs-ui/src/components/Input/Text/index.tsx create mode 100644 www/packages/docs-ui/src/components/Kbd/index.tsx create mode 100644 www/packages/docs-ui/src/components/Label/index.tsx create mode 100644 www/packages/docs-ui/src/components/Link/index.tsx create mode 100644 www/packages/docs-ui/src/components/Loading/Dots/index.tsx create mode 100644 www/packages/docs-ui/src/components/Loading/Spinner/index.tsx create mode 100644 www/packages/docs-ui/src/components/Loading/index.tsx create mode 100644 www/packages/docs-ui/src/components/MarkdownContent/index.tsx create mode 100644 www/packages/docs-ui/src/components/Modal/Footer/index.tsx create mode 100644 www/packages/docs-ui/src/components/Modal/Header/index.tsx create mode 100644 www/packages/docs-ui/src/components/Modal/index.tsx create mode 100644 www/packages/docs-ui/src/components/Navbar/ColorModeToggle/index.tsx create mode 100644 www/packages/docs-ui/src/components/Navbar/IconButton/index.tsx create mode 100644 www/packages/docs-ui/src/components/Navbar/Link/index.tsx create mode 100644 www/packages/docs-ui/src/components/Navbar/Logo/index.tsx create mode 100644 www/packages/docs-ui/src/components/Navbar/MobileMenu/Button/index.tsx create mode 100644 www/packages/docs-ui/src/components/Navbar/MobileMenu/index.tsx create mode 100644 www/packages/docs-ui/src/components/Navbar/SearchModalOpener/index.tsx create mode 100644 www/packages/docs-ui/src/components/Navbar/index.tsx create mode 100644 www/packages/docs-ui/src/components/NextLink/index.tsx create mode 100644 www/packages/docs-ui/src/components/Notification/Item/Layout/Default/index.tsx create mode 100644 www/packages/docs-ui/src/components/Notification/Item/index.tsx create mode 100644 www/packages/docs-ui/src/components/Notification/index.tsx create mode 100644 www/packages/docs-ui/src/components/Rating/index.tsx create mode 100644 www/packages/docs-ui/src/components/Search/EmptyQueryBoundary/index.tsx create mode 100644 www/packages/docs-ui/src/components/Search/Hits/GroupName/index.tsx create mode 100644 www/packages/docs-ui/src/components/Search/Hits/index.tsx create mode 100644 www/packages/docs-ui/src/components/Search/ModalOpener/index.tsx create mode 100644 www/packages/docs-ui/src/components/Search/NoResults/index.tsx create mode 100644 www/packages/docs-ui/src/components/Search/Suggestions/Item/index.tsx create mode 100644 www/packages/docs-ui/src/components/Search/Suggestions/index.tsx create mode 100644 www/packages/docs-ui/src/components/Search/index.tsx create mode 100644 www/packages/docs-ui/src/components/Select/Badge/index.tsx create mode 100644 www/packages/docs-ui/src/components/Select/Dropdown/index.tsx create mode 100644 www/packages/docs-ui/src/components/Select/Input/index.tsx create mode 100644 www/packages/docs-ui/src/components/Select/index.ts create mode 100644 www/packages/docs-ui/src/components/Sidebar/Item/index.tsx create mode 100644 www/packages/docs-ui/src/components/Sidebar/index.tsx create mode 100644 www/packages/docs-ui/src/components/TextArea/index.tsx create mode 100644 www/packages/docs-ui/src/components/Tooltip/index.tsx create mode 100644 www/packages/docs-ui/src/components/index.ts create mode 100644 www/packages/docs-ui/src/constants.ts create mode 100644 www/packages/docs-ui/src/hooks/index.tsx create mode 100644 www/packages/docs-ui/src/hooks/use-copy/index.tsx create mode 100644 www/packages/docs-ui/src/hooks/use-keyboard-shortcut/index.tsx create mode 100644 www/packages/docs-ui/src/hooks/use-scroll-utils/index.tsx create mode 100644 www/packages/docs-ui/src/hooks/use-search-navigation/index.ts create mode 100644 www/packages/docs-ui/src/hooks/use-select/index.tsx create mode 100644 www/packages/docs-ui/src/hooks/use-tabs/index.tsx create mode 100644 www/packages/docs-ui/src/index.ts create mode 100644 www/packages/docs-ui/src/main.css create mode 100644 www/packages/docs-ui/src/providers/Analytics/index.tsx create mode 100644 www/packages/docs-ui/src/providers/ColorMode/index.tsx create mode 100644 www/packages/docs-ui/src/providers/Mobile/index.tsx create mode 100644 www/packages/docs-ui/src/providers/Modal/index.tsx create mode 100644 www/packages/docs-ui/src/providers/Navbar/index.tsx create mode 100644 www/packages/docs-ui/src/providers/Notification/index.tsx create mode 100644 www/packages/docs-ui/src/providers/PageLoading/index.tsx create mode 100644 www/packages/docs-ui/src/providers/Search/index.tsx create mode 100644 www/packages/docs-ui/src/providers/Sidebar/index.tsx create mode 100644 www/packages/docs-ui/src/providers/index.ts create mode 100644 www/packages/docs-ui/src/types/index.ts create mode 100644 www/packages/docs-ui/src/utils/array-same-elms.ts create mode 100644 www/packages/docs-ui/src/utils/capitalize.ts create mode 100644 www/packages/docs-ui/src/utils/check-sidebar-item-visibility.ts create mode 100644 www/packages/docs-ui/src/utils/dom-utils.ts create mode 100644 www/packages/docs-ui/src/utils/format-report-link.ts create mode 100644 www/packages/docs-ui/src/utils/get-scrolled-top.ts create mode 100644 www/packages/docs-ui/src/utils/index.ts create mode 100644 www/packages/docs-ui/src/utils/is-elm-window.ts create mode 100644 www/packages/docs-ui/src/utils/swr-fetcher.ts create mode 100644 www/packages/docs-ui/tailwind.config.js create mode 100644 www/packages/docs-ui/tsconfig.cjs.json create mode 100644 www/packages/docs-ui/tsconfig.esm.json create mode 100644 www/packages/docs-ui/tsconfig.json create mode 100644 www/packages/eslint-config-docs/base.js create mode 100644 www/packages/eslint-config-docs/content.js create mode 100644 www/packages/eslint-config-docs/docusaurus.js create mode 100644 www/packages/eslint-config-docs/next.js create mode 100644 www/packages/eslint-config-docs/package.json create mode 100644 www/packages/tailwind/.eslintrc.js create mode 100644 www/packages/tailwind/base.tailwind.config.js create mode 100644 www/packages/tailwind/modified.tailwind.config.js create mode 100644 www/packages/tailwind/package.json create mode 100644 www/packages/tailwind/postcss.config.js create mode 100644 www/packages/tailwind/tailwind.config.js create mode 100644 www/packages/tailwind/theme-presets.js create mode 100644 www/packages/tsconfig/base.json create mode 100644 www/packages/tsconfig/docusaurus.json create mode 100644 www/packages/tsconfig/nextjs.json create mode 100644 www/packages/tsconfig/package.json create mode 100644 www/tsconfig.json create mode 100644 www/turbo.json create mode 100644 www/vale/get-files.sh create mode 100644 www/vale/run-vale.sh create mode 100644 www/vale/styles/config/vocabularies/Base/accept.txt create mode 100644 www/vale/styles/config/vocabularies/Base/reject.txt create mode 100644 www/vale/styles/docs/Acronyms.yml create mode 100644 www/vale/styles/docs/ComplexWords.yml create mode 100644 www/vale/styles/docs/Contractions.yml create mode 100644 www/vale/styles/docs/FirstPerson.yml create mode 100644 www/vale/styles/docs/Foreign.yml create mode 100644 www/vale/styles/docs/Gender.yml create mode 100644 www/vale/styles/docs/HeadingColons.yml create mode 100644 www/vale/styles/docs/HeadingPunctuation.yml create mode 100644 www/vale/styles/docs/Npm2Yarn.yml create mode 100644 www/vale/styles/docs/NpmCommands.yml create mode 100644 www/vale/styles/docs/NpmGlobal.yml create mode 100644 www/vale/styles/docs/Numbers.yml create mode 100644 www/vale/styles/docs/Ordinal.yml create mode 100644 www/vale/styles/docs/Our.yml create mode 100644 www/vale/styles/docs/OxfordComma.yml create mode 100644 www/vale/styles/docs/Passive.yml create mode 100644 www/vale/styles/docs/Percentages.yml create mode 100644 www/vale/styles/docs/SentenceLength.yml create mode 100644 www/vale/styles/docs/Spacing.yml create mode 100644 www/vale/styles/docs/Terms.yml create mode 100644 www/vale/styles/docs/TypeScript.yml create mode 100644 www/vale/styles/docs/We.yml create mode 100644 www/vale/styles/docs/Wordiness.yml create mode 100644 www/vale/styles/docs/WritingLevel.yml create mode 100644 www/vale/styles/write-good/Cliches.yml create mode 100644 www/vale/styles/write-good/E-Prime.yml create mode 100644 www/vale/styles/write-good/Illusions.yml create mode 100644 www/vale/styles/write-good/Passive.yml create mode 100644 www/vale/styles/write-good/README.md create mode 100644 www/vale/styles/write-good/So.yml create mode 100644 www/vale/styles/write-good/ThereIs.yml create mode 100644 www/vale/styles/write-good/TooWordy.yml create mode 100644 www/vale/styles/write-good/Weasel.yml create mode 100644 www/vale/styles/write-good/meta.json create mode 100644 www/yarn.lock diff --git a/.bin/b.yaml b/.bin/b.yaml index 1efdecb..b373784 100644 --- a/.bin/b.yaml +++ b/.bin/b.yaml @@ -1,2 +1,5 @@ -b: -jq: \ No newline at end of file + +binaries: + jq: + version: jq-1.7 + kubectl: {} \ No newline at end of file diff --git a/.envrc b/.envrc index 0ca6f46..2510a91 100644 --- a/.envrc +++ b/.envrc @@ -1,6 +1,6 @@ #!/usr/bin/env bash # Template form: -# https://github.com/arg-sh/argsh +# https://github.com/fentas/b # curl -sfLS https://envrc.arg.sh > .envrc # This is an example of a .envrc file for use with direnv. # It sets up the environment for the project. diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml new file mode 100644 index 0000000..f61c2d4 --- /dev/null +++ b/.github/workflows/docs.yml @@ -0,0 +1,67 @@ +name: Deploy Documentation + +on: + push: + branches: [ main ] + paths: + - 'www/apps/docs/**' + - '.github/workflows/docs.yml' + pull_request: + branches: [ main ] + paths: + - 'www/apps/docs/**' + +permissions: + contents: read + pages: write + id-token: write + +concurrency: + group: "pages" + cancel-in-progress: false + +jobs: + build: + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Setup Node.js + uses: actions/setup-node@v4 + with: + node-version: '22' + cache: 'yarn' + cache-dependency-path: www/yarn.lock + + - name: Install dependencies + run: | + cd www + yarn install + + - name: Build Docusaurus site + run: | + cd www + yarn run build + + - name: Setup Pages + if: github.ref == 'refs/heads/main' + uses: actions/configure-pages@v4 + + - name: Upload artifact + if: github.ref == 'refs/heads/main' + uses: actions/upload-pages-artifact@v3 + with: + path: www/apps/docs/build + + deploy: + if: github.ref == 'refs/heads/main' + environment: + name: github-pages + url: ${{ steps.deployment.outputs.page_url }} + runs-on: ubuntu-latest + needs: build + steps: + - name: Deploy to GitHub Pages + id: deployment + uses: actions/deploy-pages@v4 diff --git a/README.md b/README.md index 5e81f88..0ede20f 100644 --- a/README.md +++ b/README.md @@ -73,11 +73,12 @@ If none of these are set, `b` will fail. To properly use the `--all` flag, you should create a `b.yaml` file in the binary directory. This file should contain a list of binaries you want to manage. Here is an example: ```yaml -jq: - # pin version - version: jq-1.8.1 -kind: -tilt: +binaries: + jq: + # pin version + version: jq-1.8.1 + kind: + tilt: ``` This will ensure that `jq`, `kind`, and `tilt` are installed and at the correct version. If you don't specify a version, `b` will install the latest version. @@ -119,7 +120,7 @@ Have a look at [pkg/binary](./pkg/binary/) for more details. Have a look at [pkg/binaries](./pkg/binaries/) for prepackaged binaries. -- [argsh](https://github.com/arg-sh/argsh) - Utilities for Bash script quality +- [argsh](https://github.com/fentas/b) - Utilities for Bash script quality - `b` - (Selfupdate) Manage and execute binary files - [cilium](https://github.com/cilium/cilium-cli) - Providing, securing, and observing network connectivity between workloads - [clusterctl](https://github.com/kubernetes-sigs/cluster-api) - Kubernetes cluster lifecycle management diff --git a/logo.svg b/logo.svg new file mode 100644 index 0000000..beefd6c --- /dev/null +++ b/logo.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/pkg/binaries/argsh/argsh.go b/pkg/binaries/argsh/argsh.go index 63b171d..5f22029 100644 --- a/pkg/binaries/argsh/argsh.go +++ b/pkg/binaries/argsh/argsh.go @@ -20,7 +20,7 @@ func Binary(options *binaries.BinaryOptions) *binary.Binary { Tracker: options.Tracker, Version: options.Version, Name: "argsh", - GitHubRepo: "arg-sh/argsh", + GitHubRepo: "fentas/b", GitHubFile: "argsh", VersionF: binary.GithubLatest, VersionLocalF: func(b *binary.Binary) (string, error) { diff --git a/pkg/cli/cli.go b/pkg/cli/cli.go index d9cddc4..c0f1785 100644 --- a/pkg/cli/cli.go +++ b/pkg/cli/cli.go @@ -21,7 +21,7 @@ type CmdBinaryOptions struct { IO *streams.IO Binaries []*binary.Binary NoConfig bool - config *state.BinaryList + config *state.State // Flags all bool @@ -152,7 +152,7 @@ func (o *CmdBinaryOptions) Complete(cmd *cobra.Command, args []string) error { } if o.config != nil { - for _, lb := range *o.config { + for _, lb := range o.config.Binaries { for b, do := range o.ensure { if lb.Name == b.Name { b.Version = lb.Version diff --git a/pkg/cli/init.go b/pkg/cli/init.go index 848a0f2..2b50bac 100644 --- a/pkg/cli/init.go +++ b/pkg/cli/init.go @@ -9,7 +9,6 @@ import ( "github.com/fentas/goodies/templates" "github.com/spf13/cobra" - "github.com/fentas/b/pkg/binary" "github.com/fentas/b/pkg/path" "github.com/fentas/b/pkg/state" ) @@ -96,15 +95,7 @@ func (o *InitOptions) createConfigWithSelfReference(configPath string) error { if err := os.MkdirAll(dir, 0755); err != nil { return err } - - // Create config with self-reference to 'b' - config := &state.BinaryList{ - &binary.LocalBinary{ - Name: "b", - }, - } - - return state.SaveConfig(config, configPath) + return state.CreateDefaultConfig(configPath) } // createProjectFiles creates additional project files (.gitignore, .envrc) if needed diff --git a/pkg/cli/install.go b/pkg/cli/install.go index 0dcada1..d308455 100644 --- a/pkg/cli/install.go +++ b/pkg/cli/install.go @@ -187,20 +187,20 @@ func (o *InstallOptions) addToConfig(binaries []*binary.Binary) error { // Load existing config or create new one config := o.Config if config == nil { - config = &state.BinaryList{} + config = &state.State{} } // Add binaries to config for _, b := range binaries { // Check if already exists found := false - for i, existing := range *config { + for i, existing := range config.Binaries { if existing.Name == b.Name { // Update version only if we have a specific version if b.Version != "" && b.Version != "latest" { - (*config)[i].Version = b.Version + config.Binaries[i].Version = b.Version if o.Fix { - (*config)[i].Enforced = b.Version + config.Binaries[i].Enforced = b.Version } } found = true @@ -219,7 +219,7 @@ func (o *InstallOptions) addToConfig(binaries []*binary.Binary) error { entry.Enforced = b.Version } } - *config = append(*config, entry) + config.Binaries = append(config.Binaries, entry) } } diff --git a/pkg/cli/shared.go b/pkg/cli/shared.go index 7c99f46..f72738f 100644 --- a/pkg/cli/shared.go +++ b/pkg/cli/shared.go @@ -13,7 +13,7 @@ import ( type SharedOptions struct { IO *streams.IO Binaries []*binary.Binary - Config *state.BinaryList + Config *state.State // Global flags ConfigPath string @@ -75,7 +75,7 @@ func (o *SharedOptions) GetBinariesFromConfig() []*binary.Binary { } var result []*binary.Binary - for _, lb := range *o.Config { + for _, lb := range o.Config.Binaries { if b, ok := o.lookup[lb.Name]; ok { // Set version from config b.Version = lb.Version diff --git a/pkg/cli/version_test.go b/pkg/cli/version_test.go index 38fab8a..dd4d33a 100644 --- a/pkg/cli/version_test.go +++ b/pkg/cli/version_test.go @@ -97,7 +97,7 @@ func TestVersionOptions_Validate(t *testing.T) { func TestVersionOptions_Run(t *testing.T) { tests := []struct { name string - config *state.BinaryList + config *state.State local bool check bool quiet bool @@ -106,10 +106,12 @@ func TestVersionOptions_Run(t *testing.T) { }{ { name: "run with config", - config: &state.BinaryList{ - &binary.LocalBinary{ - Name: "jq", - Version: "1.7", + config: &state.State{ + Binaries: state.BinaryList{ + &binary.LocalBinary{ + Name: "jq", + Version: "1.7", + }, }, }, local: false, @@ -118,10 +120,12 @@ func TestVersionOptions_Run(t *testing.T) { }, { name: "run local only", - config: &state.BinaryList{ - &binary.LocalBinary{ - Name: "jq", - Version: "1.7", + config: &state.State{ + Binaries: state.BinaryList{ + &binary.LocalBinary{ + Name: "jq", + Version: "1.7", + }, }, }, local: true, diff --git a/pkg/state/config.go b/pkg/state/config.go index b0f6415..bf378da 100644 --- a/pkg/state/config.go +++ b/pkg/state/config.go @@ -10,7 +10,7 @@ import ( ) // LoadConfigFromPath loads configuration from a specific path -func LoadConfigFromPath(configPath string) (*BinaryList, error) { +func LoadConfigFromPath(configPath string) (*State, error) { if _, err := os.Stat(configPath); err != nil { return nil, err } @@ -20,16 +20,16 @@ func LoadConfigFromPath(configPath string) (*BinaryList, error) { return nil, err } - var list BinaryList - if err := yaml.Unmarshal(config, &list); err != nil { + var state State + if err := yaml.Unmarshal(config, &state); err != nil { return nil, err } - return &list, nil + return &state, nil } // LoadConfig loads configuration with automatic discovery -func LoadConfig() (*BinaryList, error) { +func LoadConfig() (*State, error) { configPath, err := path.FindConfigFile() if err != nil { return nil, err @@ -43,7 +43,7 @@ func LoadConfig() (*BinaryList, error) { } // SaveConfig saves the configuration to the specified path -func SaveConfig(config *BinaryList, configPath string) error { +func SaveConfig(config *State, configPath string) error { // Ensure directory exists dir := filepath.Dir(configPath) if err := os.MkdirAll(dir, 0755); err != nil { @@ -60,9 +60,11 @@ func SaveConfig(config *BinaryList, configPath string) error { // CreateDefaultConfig creates a default b.yaml configuration file func CreateDefaultConfig(configPath string) error { - defaultConfig := BinaryList{ - &binary.LocalBinary{ - Name: "b", + defaultConfig := State{ + Binaries: BinaryList{ + &binary.LocalBinary{ + Name: "b", + }, }, } return SaveConfig(&defaultConfig, configPath) diff --git a/pkg/state/types.go b/pkg/state/types.go index a350dae..4ed69d8 100644 --- a/pkg/state/types.go +++ b/pkg/state/types.go @@ -1,9 +1,39 @@ +// Package state provides state management for b package state import ( "github.com/fentas/b/pkg/binary" ) +type State struct { + Binaries BinaryList `yaml:"binaries"` +} + +// MarshalYAML implements the yaml.Marshaler interface for State +func (s *State) MarshalYAML() (interface{}, error) { + binaries, err := s.Binaries.MarshalYAML() + if err != nil { + return nil, err + } + + return map[string]interface{}{ + "binaries": binaries, + }, nil +} + +// UnmarshalYAML implements the yaml.Unmarshaler interface for State +func (s *State) UnmarshalYAML(unmarshal func(interface{}) error) error { + type Alias State + var aux Alias + + if err := unmarshal(&aux); err != nil { + return err + } + + *s = State(aux) + return nil +} + type BinaryList []*binary.LocalBinary func (list *BinaryList) UnmarshalYAML(unmarshal func(interface{}) error) error { @@ -27,15 +57,12 @@ func (list *BinaryList) MarshalYAML() (interface{}, error) { result := make(map[string]interface{}) for _, b := range *list { if b.Name != "" { - // Only include version if it's set and not empty - if b.Version != "" && b.Version != "latest" { - // Create a simple map with only the version field + if b.Enforced != "" { result[b.Name] = map[string]string{ - "version": b.Version, + "version": b.Enforced, } } else { - // Just the key with no value (null) - result[b.Name] = nil + result[b.Name] = &struct{}{} } } } diff --git a/test/TESTING_PLAN.md b/test/TESTING_PLAN.md index 68e0897..270a2b4 100644 --- a/test/TESTING_PLAN.md +++ b/test/TESTING_PLAN.md @@ -1,4 +1,4 @@ -# Testing Plan for B CLI Tool +# Testing Plan for b CLI Tool ## Overview diff --git a/test/e2e/main_test.go b/test/e2e/main_test.go index 46aa8b9..29f16f1 100644 --- a/test/e2e/main_test.go +++ b/test/e2e/main_test.go @@ -99,7 +99,7 @@ func TestE2E_InitWorkflow(t *testing.T) { } configStr := string(configContent) - if !strings.Contains(configStr, "b: null") { + if !strings.Contains(configStr, "b: {}") { t.Error("Config file does not contain self-reference to 'b' binary") } @@ -129,10 +129,11 @@ func TestE2E_ConfigDiscovery(t *testing.T) { } configPath := filepath.Join(configDir, "b.yaml") - configContent := []byte(`jq: - version: "1.7" -kubectl: - version: "latest" + configContent := []byte(` +binaries: + jq: + version: "jq-1.7" + kubectl: {} `) err = os.WriteFile(configPath, configContent, 0644) if err != nil { @@ -140,7 +141,7 @@ kubectl: } // Build the CLI - binaryPath := filepath.Join(os.TempDir(), "b-e2e-test") + binaryPath := filepath.Join(tempDir, "b-e2e-test") defer os.Remove(binaryPath) cmd := exec.Command("go", "build", "-o", binaryPath, "./cmd/b") diff --git a/test/testutil/helpers.go b/test/testutil/helpers.go index 2b964ce..c35febc 100644 --- a/test/testutil/helpers.go +++ b/test/testutil/helpers.go @@ -170,7 +170,7 @@ func ChangeDir(t *testing.T, dir string) { } // CreateTestProject creates a test project structure -func CreateTestProject(t *testing.T, config *state.BinaryList) string { +func CreateTestProject(t *testing.T, config *state.State) string { t.Helper() dir := TempDir(t) diff --git a/www/.eslintrc.js b/www/.eslintrc.js new file mode 100644 index 0000000..7850080 --- /dev/null +++ b/www/.eslintrc.js @@ -0,0 +1,10 @@ +module.exports = { + root: true, + // This tells ESLint to load the config from the package `eslint-config-docs` + extends: ["docs"], + settings: { + next: { + rootDir: ["apps/*/"], + }, + }, +}; \ No newline at end of file diff --git a/www/.gitignore b/www/.gitignore new file mode 100644 index 0000000..8e0d006 --- /dev/null +++ b/www/.gitignore @@ -0,0 +1,11 @@ +.vercel +build +node_modules +.yarn/* +.yarn/install-state.gz +!.yarn/patches +!.yarn/plugins +!.yarn/releases +!.yarn/sdks +!.yarn/versions +.turbo diff --git a/www/.prettierrc b/www/.prettierrc new file mode 100644 index 0000000..aa4d695 --- /dev/null +++ b/www/.prettierrc @@ -0,0 +1,8 @@ +{ + "endOfLine": "auto", + "semi": false, + "singleQuote": false, + "tabWidth": 2, + "trailingComma": "es5", + "arrowParens": "always" +} diff --git a/www/.yarnrc.yml b/www/.yarnrc.yml new file mode 100644 index 0000000..1b1262b --- /dev/null +++ b/www/.yarnrc.yml @@ -0,0 +1 @@ +nmMode: hardlinks-local \ No newline at end of file diff --git a/www/README.md b/www/README.md new file mode 100644 index 0000000..004d40c --- /dev/null +++ b/www/README.md @@ -0,0 +1,11 @@ +# Web precense + +This is based on https://github.com/fentas/b/tree/develop/www ❤️ + +## Documentation Resources + +This directory holds the code and content of both the [documentation](https://arg.sh/) and [API reference](https://arg.sh/api/admin). + +## docs Directory + +The `docs` directory holds the code and content of the documentation website. The website is built with [Docusaurus v2](https://docusaurus.io/). \ No newline at end of file diff --git a/www/apps/docs/.content.eslintrc.js b/www/apps/docs/.content.eslintrc.js new file mode 100644 index 0000000..fc843a3 --- /dev/null +++ b/www/apps/docs/.content.eslintrc.js @@ -0,0 +1,6 @@ +module.exports = { + root: true, + extends: [ + "docs/content" + ], +} diff --git a/www/apps/docs/.env.sample b/www/apps/docs/.env.sample new file mode 100644 index 0000000..c681af3 --- /dev/null +++ b/www/apps/docs/.env.sample @@ -0,0 +1,10 @@ +API_URL= +DOCS_ALGOLIA_INDEX_NAME= +API_ALGOLIA_INDEX_NAME= +ALGOLIA_API_KEY= +ALGOLIA_APP_ID= +AI_ASSISTANT_URL= +AI_API_ASSISTANT_TOKEN= +AI_WEBSITE_ID= +AI_API_ASSISTANT_RECAPTCHA_SITE_KEY= +CLOUDINARY_CLOUD_NAME= \ No newline at end of file diff --git a/www/apps/docs/.eslintrc.js b/www/apps/docs/.eslintrc.js new file mode 100644 index 0000000..a910013 --- /dev/null +++ b/www/apps/docs/.eslintrc.js @@ -0,0 +1,8 @@ +module.exports = { + root: true, + extends: ["docs/docusaurus"], + parserOptions: { + project: true, + tsconfigRootDir: __dirname, + }, +} diff --git a/www/apps/docs/.gitignore b/www/apps/docs/.gitignore new file mode 100644 index 0000000..bfab69e --- /dev/null +++ b/www/apps/docs/.gitignore @@ -0,0 +1,29 @@ +# Dependencies +/node_modules + +# Production +/build + +# Generated files +.docusaurus +.cache-loader + +# Misc +.DS_Store +.env.local +.env.development.local +.env.test.local +.env.production.local + +npm-debug.log* +yarn-debug.log* +yarn-error.log* +.yarn/* +.yarn/install-state.gz +!.yarn/patches +!.yarn/plugins +!.yarn/releases +!.yarn/sdks +!.yarn/versions + +.turbo \ No newline at end of file diff --git a/www/apps/docs/README.md b/www/apps/docs/README.md new file mode 100644 index 0000000..df6bed7 --- /dev/null +++ b/www/apps/docs/README.md @@ -0,0 +1,13 @@ +# Medusa Documentation + +The Medusa documentation website is built with Docusaurus v2. You can learn more about contributing [here](https://arg.sh/contribution-guidelines). + +## Components and Theme + +### Extended Theme Components + +Components that extend themes from Docusaurus or other plugins are placed under `src/theme`. + +### Medusa Docs Components + +Components created specifically for the Medusa Docs are placed under the `src/componenets` directory. diff --git a/www/apps/docs/announcement.json b/www/apps/docs/announcement.json new file mode 100644 index 0000000..9e26dfe --- /dev/null +++ b/www/apps/docs/announcement.json @@ -0,0 +1 @@ +{} \ No newline at end of file diff --git a/www/apps/docs/babel.config.js b/www/apps/docs/babel.config.js new file mode 100644 index 0000000..62aaab6 --- /dev/null +++ b/www/apps/docs/babel.config.js @@ -0,0 +1,4 @@ +module.exports = { + presets: [require.resolve("@docusaurus/core/lib/babel/preset")], + plugins: [['@babel/plugin-proposal-decorators', { legacy: true }]], +} diff --git a/www/apps/docs/content/about.md b/www/apps/docs/content/about.md new file mode 100644 index 0000000..7d4a970 --- /dev/null +++ b/www/apps/docs/content/about.md @@ -0,0 +1,47 @@ +# About b + + + + + +**b** is a modern binary manager designed to simplify how developers install, manage, and version their command-line tools. + +## Purpose + +`b` was created to solve the common problems developers face when managing development tools across different projects and environments: + +- **Version Conflicts**: Different projects requiring different tool versions +- **Environment Setup**: Complex installation and PATH management +- **Team Consistency**: Ensuring all team members use the same tool versions +- **CI/CD Integration**: Reproducible builds with exact tool dependencies + +## Open Source + +`b` is an open-source project available on [GitHub](https://github.com/fentas/b). We welcome contributions from the community. + +This documentation is built with [Docusaurus](https://docusaurus.io/) and uses design elements inspired by the [Medusa](https://github.com/medusajs/medusa) project. + +## Project Information + +- **Repository**: [github.com/fentas/b](https://github.com/fentas/b) +- **License**: MIT License +- **Language**: Go +- **Maintainer**: fentas + +## Contributing + +We welcome contributions! Please see our [contribution guidelines](./contribution/docs) for more information on how to get involved. + +## Support + +If you encounter issues or have questions: + +- Check our [troubleshooting guide](./troubleshooting) +- Open an issue on [GitHub](https://github.com/fentas/b/issues) +- Join our community discussions + +email: jan.guth@gmail.com + + + + diff --git a/www/apps/docs/content/b/overview.mdx b/www/apps/docs/content/b/overview.mdx new file mode 100644 index 0000000..f2bb24e --- /dev/null +++ b/www/apps/docs/content/b/overview.mdx @@ -0,0 +1,94 @@ +--- +description: "Complete command reference for b" +hide_table_of_contents: true +--- + +import DocCardList from '@theme/DocCardList'; +import Icons from '@theme/Icon'; + +# b reference + +**b** provides a comprehensive set of commands for managing binary dependencies in your projects. This reference covers all available commands, options, and usage patterns. + +## Core + +**b** is built around a subcommand architecture that provides intuitive and powerful binary management capabilities. + +## Quick reference + +Get started quickly with the most common commands: + +```bash +b init # Initialize a new project +b install jq # Install a specific binary +b install --add jq@jq-1.6 # Install and add to b.yaml +b list # List installed binaries +b update # Update all binaries +b search kubectl # Search for available binaries +``` + + \ No newline at end of file diff --git a/www/apps/docs/content/b/subcommands/completion.mdx b/www/apps/docs/content/b/subcommands/completion.mdx new file mode 100644 index 0000000..86b977f --- /dev/null +++ b/www/apps/docs/content/b/subcommands/completion.mdx @@ -0,0 +1,129 @@ +--- +description: "Generate shell completion scripts for b CLI" +--- + +# b completion + +The `b completion` command generates shell completion scripts for the b CLI, enabling tab completion for commands, flags, and arguments in your shell. + +## Synopsis + +```bash +# Generate completion script for your shell +b completion [bash|zsh|fish|powershell] + +# Source the completion script in your current shell session +source <(b completion bash) # for bash +``` + +## Description + +The `completion` command generates shell completion scripts that provide command-line completion for b CLI. This allows you to use the Tab key to automatically complete commands, subcommands, flags, and arguments, making the CLI more user-friendly and efficient. + +## Available Shells + +Completion is available for the following shells: + +- **bash**: For Bash shell users +- **zsh**: For Zsh shell users +- **fish**: For Fish shell users +- **powershell**: For PowerShell users + +## Installation + +### Bash + +Add the following to your `~/.bashrc` or `~/.bash_profile`: + +```bash +# Bash completion for b CLI +source <(b completion bash) +``` + +### Zsh + +Add the following to your `~/.zshrc`: + +```zsh +# Zsh completion for b CLI +if [ $commands[b] ]; then + source <(b completion zsh) +fi +``` + +### Fish + +Save the completion script to your Fish completions directory: + +```bash +# Create completions directory if it doesn't exist +mkdir -p ~/.config/fish/completions + +# Generate and save completion script +b completion fish > ~/.config/fish/completions/b.fish +``` + +### PowerShell + +Add the following to your PowerShell profile (`$PROFILE`): + +```powershell +# PowerShell completion for b CLI +b completion powershell | Out-String | Invoke-Expression +``` + +## Examples + +### Generate Completion Script + +```bash +# Generate bash completion script +b completion bash > /etc/bash_completion.d/b + +# Generate zsh completion script +b completion zsh > "${fpath[1]}/_b" + +# Generate fish completion script +b completion fish > ~/.config/fish/completions/b.fish + +# Generate PowerShell completion script +b completion powershell > ~/.b-completion.ps1 +``` + +### One-time Completion + +For a single session without modifying your shell configuration: + +```bash +# Bash/Zsh +source <(b completion bash) + +# Fish +b completion fish | source +``` + +## Completion Features + +- **Command Completion**: Tab-complete all available commands +- **Flag Completion**: Complete flags for each command +- **Argument Completion**: Context-aware completion for arguments +- **Flag Value Completion**: Smart completion for flag values +- **Descriptions**: Show help text for completions (in supported shells) + +## Shell-Specific Notes + +### Bash + +For better completion experience with bash, consider installing the `bash-completion` package: + +```bash +# On macOS with Homebrew +brew install bash-completion + +# On Ubuntu/Debian +sudo apt-get install bash-completion +``` + +### Zsh + +If you're using Oh My Zsh, the completion should work out of the box after installation. diff --git a/www/apps/docs/content/b/subcommands/init.mdx b/www/apps/docs/content/b/subcommands/init.mdx new file mode 100644 index 0000000..d571c3d --- /dev/null +++ b/www/apps/docs/content/b/subcommands/init.mdx @@ -0,0 +1,89 @@ +--- +description: "Initialize a new project with b" +--- + +# b init + +The `b init` command initializes a new project with **b** configuration, creating the necessary **b.yaml** file and setting up the project structure. + +## Synopsis + +```bash +b init [options] +``` + +## Description + +The `init` command creates a new **b.yaml** configuration file in the current directory and optionally sets up additional project files like `.gitignore` and shell integration scripts. + +## Options + +- `--quiet, -q`: Run in quiet mode with minimal output +- `--help, -h`: Show help information + +## Examples + +### Basic Initialization + +```bash +# Initialize b in current directory +b init +``` + +This creates a basic **b.yaml** file: + +```yaml +version: v1 +binaries: + b: {} +``` + +### Project Structure + +After initialization, your project will have: + +``` +project/ +├── .bin +│ ├── .gitignore +│ └── b.yaml +└── .envrc +``` + +## Configuration File + +The generated **b.yaml** file serves as the central configuration for your project's binary dependencies: + +```yaml +binaries: + # Binary dependencies will be added here + # Example: + # jq: + # version: "1.6" + # kubectl: + # version: "1.28.0" +``` + +## Best Practices + +1. **Version Control**: Always commit the **b.yaml** file to version control +2. **Team Collaboration**: Initialize **b** in shared project repositories +3. **CI/CD**: Use `b init` in CI/CD pipelines before installing dependencies +4. **Documentation**: Document your binary requirements in the project README + +## Integration with Git + +The `init` command automatically creates or updates `.gitignore` to exclude: + +```gitignore +# b +.bin/ +``` + +## Error Handling + +Common issues and solutions: + +- **Permission denied**: Ensure write permissions in the current directory +- **File exists**: The command will not overwrite existing **b.yaml** files +- **Invalid directory**: Run from a valid project directory diff --git a/www/apps/docs/content/b/subcommands/install.mdx b/www/apps/docs/content/b/subcommands/install.mdx new file mode 100644 index 0000000..d594bc8 --- /dev/null +++ b/www/apps/docs/content/b/subcommands/install.mdx @@ -0,0 +1,85 @@ +--- +description: "Install and manage binaries with b CLI" +--- + +# b install + +The `b install` command downloads and installs binaries, managing their versions and updating your project configuration. + +## Synopsis + +```bash +b install [options] [binary[@version]...] +``` + +## Description + +The `install` command downloads binaries from GitHub releases and makes them available in your project. It can install specific versions, update existing installations, and automatically manage your `b.yaml` configuration. + +## Options + +- `--add, -a`: Add installed binaries to b.yaml configuration +- `--force, -f`: Force reinstallation even if already installed +- `--quiet, -q`: Run in quiet mode with minimal output +- `--help, -h`: Show help information + +## Examples + +### Install Specific Binaries + +```bash +# Install latest version +b install jq + +# Install specific version +b install jq@1.6 + +# Install multiple binaries +b install jq kubectl terraform +``` + +### Install and Add to Configuration + +```bash +# Install and add to b.yaml +b install --add jq@1.6 + +# Install multiple with specific versions +b install --add jq@1.6 kubectl@1.28.0 +``` + +### Install from Configuration + +```bash +# Install all binaries from b.yaml +b install + +# Force reinstall all +b install --force +``` + +## Version Resolution + +The install command supports flexible version specifications: + +- `latest`: Always installs the most recent version +- `1.6`: Installs exactly version 1.6 +- `1.6.0`: Installs exactly version 1.6.0 + +## Installation Process + +1. **Version Resolution**: Determines the exact version to install +2. **Download**: Fetches the binary from GitHub releases +3. **Verification**: Validates the downloaded binary +4. **Installation**: Places the binary in the managed directory +5. **PATH Management**: Ensures the binary is available in PATH +6. **Configuration Update**: Updates b.yaml if `--add` is specified + +## Error Handling + +Common issues and solutions: + +- **Version not found**: Check available versions with `b search ` +- **Download failed**: Verify internet connection and GitHub access +- **Permission denied**: Ensure write permissions to installation directory +- **Binary not executable**: The install command automatically sets execute permissions \ No newline at end of file diff --git a/www/apps/docs/content/b/subcommands/list.mdx b/www/apps/docs/content/b/subcommands/list.mdx new file mode 100644 index 0000000..148122f --- /dev/null +++ b/www/apps/docs/content/b/subcommands/list.mdx @@ -0,0 +1,73 @@ +--- +description: "List installed binaries and their versions" +--- + +# b list + +The `b list` command displays all installed binaries and their current versions. + +## Synopsis + +```bash +b list [options] [binary...] +``` + +## Description + +The `list` command shows information about installed binaries, including their versions, installation paths, and configuration status. + +## Options + +- `--quiet, -q`: Show only binary names and versions +- `--help, -h`: Show help information + +## Examples + +### List All Binaries + +```bash +# List all installed binaries +b list +``` + +Output: +``` +jq 1.6 ~/.local/share/b/bin/jq +kubectl 1.28.0 ~/.local/share/b/bin/kubectl +terraform 1.5.7 ~/.local/share/b/bin/terraform +``` + +### List Specific Binaries + +```bash +# List specific binaries +b list jq kubectl +``` + +### Quiet Mode + +```bash +# Show only names and versions +b list --quiet +``` + +Output: +``` +jq 1.6 +kubectl 1.28.0 +terraform 1.5.7 +``` + +## Output Format + +The default output includes: +- **Binary Name**: The name of the installed binary +- **Version**: The currently installed version +- **Path**: The full path to the binary + +## Configuration Status + +The list command shows which binaries are: +- ✅ **Configured**: Listed in b.yaml +- ⚠️ **Installed but not configured**: Installed but not in b.yaml +- ❌ **Configured but not installed**: Listed in b.yaml but not installed diff --git a/www/apps/docs/content/b/subcommands/request.mdx b/www/apps/docs/content/b/subcommands/request.mdx new file mode 100644 index 0000000..dcf2e08 --- /dev/null +++ b/www/apps/docs/content/b/subcommands/request.mdx @@ -0,0 +1,52 @@ +--- +description: "Request new binaries to be added to b CLI" +--- + +# b request + +The `b request` command helps users request new binaries to be added to the b CLI ecosystem by creating GitHub issues with the appropriate template. + +## Synopsis + +```bash +b request [options] +``` + +## Description + +The `request` command streamlines the process of requesting new binaries to be added to the b CLI. It opens your default web browser to create a new GitHub issue with a pre-filled template, making it easy to request new tools. + +## Options + +- `--help, -h`: Show help information + +## Examples + +### Basic Usage + +```bash +# Request a new binary to be added +b request my-cool-tool +``` + +## Request Process + +When you submit a request: + +1. The command collects information about your system +2. Opens a new issue in the b CLI GitHub repository +3. Pre-fills a template with: + - Requested binary name + - Your system information + - Any additional notes you provided + - Version of b CLI you're using + +## Request Guidelines + +For the best chance of your request being accepted: + +1. **Check existing issues** first to avoid duplicates +2. **Provide a clear use case** for the binary +3. **Include relevant links** to the project's homepage +4. **Mention any alternatives** you've considered +5. **Be specific** about versions or features needed \ No newline at end of file diff --git a/www/apps/docs/content/b/subcommands/search.mdx b/www/apps/docs/content/b/subcommands/search.mdx new file mode 100644 index 0000000..19d640d --- /dev/null +++ b/www/apps/docs/content/b/subcommands/search.mdx @@ -0,0 +1,44 @@ +--- +description: "Search for available binaries in the b CLI ecosystem" +--- + +# b search + +The `b search` command helps you discover binaries available in the b CLI ecosystem, showing detailed information about each package including versions, descriptions, and installation commands. + +## Synopsis + +```bash +b search [options] [query] +``` + +## Description + +The `search` command queries the b CLI package registry to find binaries matching your search criteria. It's the best way to discover new tools and check available versions before installation. + +## Options + +- `--output, -o`: Output format (json, yaml, table) +- `--help, -h`: Show help information + +## Examples + +### Basic Search + +```bash +# Search for a specific binary +b search jq + +# Search with partial match +b search py +``` + +### Advanced Search + +```bash +# Show all available packages +b search + +# Get results in JSON format +b search --output json jq +``` diff --git a/www/apps/docs/content/b/subcommands/update.mdx b/www/apps/docs/content/b/subcommands/update.mdx new file mode 100644 index 0000000..8f4fcdc --- /dev/null +++ b/www/apps/docs/content/b/subcommands/update.mdx @@ -0,0 +1,84 @@ +--- +description: "Update installed binaries to their latest versions" +--- + +# b update + +The `b update` command checks for and installs newer versions of previously installed binaries, ensuring your tools stay up-to-date. + +## Synopsis + +```bash +b update [options] [binary...] +``` + +## Description + +The `update` command checks GitHub releases for newer versions of your installed binaries and updates them if available. It respects version constraints in your `b.yaml` configuration while updating to the latest compatible version. + +## Options + +- `--all, -a`: Update all installed binaries +- `--force, -f`: Force update even if already at latest version +- `--quiet, -q`: Run in quiet mode with minimal output +- `--check, -c`: Check for updates without installing +- `--help, -h`: Show help information + +## Examples + +### Check for Updates + +```bash +# Check for updates without installing +b update --check + +# Check specific binaries +b update --check jq kubectl +``` + +### Update Binaries + +```bash +# Update all installed binaries +b update --all + +# Update specific binaries +b update jq kubectl + +# Force update even if at latest version +b update --force jq +``` + +### Update Configuration + +```bash +# Update binaries and save versions to b.yaml +b update --all --save +``` + +## Version Constraints + +When updating, the command respects version constraints in your `b.yaml`: + +- `^1.2.3`: Updates to the latest 1.x.x version +- `~1.2.3`: Updates to the latest 1.2.x version +- `>1.2.3`: Updates to any version above 1.2.3 +- `1.2.3`: Keeps exactly this version (use --force to override) + +## Update Process + +1. **Version Check**: Compares installed versions with latest available +2. **Dependency Resolution**: Ensures compatibility between dependencies +3. **Download**: Fetches updated binaries from GitHub releases +4. **Verification**: Validates the downloaded binaries +5. **Backup**: Creates backups of existing binaries before updating +6. **Update**: Replaces old binaries with new versions + +## Error Handling + +Common issues and solutions: + +- **Update failed**: Check network connection and GitHub access +- **Version conflict**: Review version constraints in b.yaml +- **Permission denied**: Ensure write permissions to installation directory +- **Binary in use**: Close applications using the binary before updating \ No newline at end of file diff --git a/www/apps/docs/content/b/subcommands/version.mdx b/www/apps/docs/content/b/subcommands/version.mdx new file mode 100644 index 0000000..71d994b --- /dev/null +++ b/www/apps/docs/content/b/subcommands/version.mdx @@ -0,0 +1,113 @@ +--- +description: "Display version information for b CLI and installed binaries" +--- + +# b version + +The `b version` command displays version information about the b CLI tool and its installed binaries, helping you track which versions are currently in use. + +## Synopsis + +```bash +b version [options] [binary...] +``` + +## Description + +The `version` command shows detailed version information about the b CLI itself and any installed binaries. It's useful for debugging, reporting issues, and ensuring compatibility between different components. + +## Options + +- `--short, -s`: Show only version numbers +- `--json`: Output in JSON format +- `--all, -a`: Show versions of all installed binaries +- `--help, -h`: Show help information + +## Examples + +### Basic Usage + +```bash +# Show b CLI version +b version + +# Show version in short format +b version --short +``` + +### Check Binary Versions + +```bash +# Check version of specific binaries +b version jq kubectl + +# Show versions of all installed binaries +b version --all + +# Get version information in JSON format +b version --json +``` + +## Version Information + +The version command displays several types of version information: + +1. **CLI Version**: The version of the b CLI tool +2. **Runtime Information**: Go version and build platform +3. **Binary Versions**: For each specified binary: + - Installed version + - Latest available version + - Whether an update is available + - Source of installation + - Last checked/updated timestamp + +## Output Formats + +### Standard Output +``` +b version 1.2.3 (go1.19.5 darwin/amd64) + +jq: jq-1.6 (latest: jq-1.7) [Update available] +kubectl: v1.28.0 (latest: v1.28.0) [Up to date] +``` + +### JSON Output (--json) +```json +{ + "cli": { + "version": "1.2.3", + "goVersion": "go1.19.5", + "platform": "darwin/amd64" + }, + "binaries": { + "jq": { + "installed": "jq-1.6", + "latest": "jq-1.7", + "updateAvailable": true, + "source": "github.com/stedolan/jq" + } + } +} +``` + +## Integration with CI/CD + +The `--short` and `--json` flags are particularly useful in CI/CD pipelines: + +```yaml +# Example GitHub Actions workflow step +- name: Verify binary versions + run: | + if [ "$(b version --short jq)" != "1.6" ]; then + echo "Incorrect jq version" + exit 1 + fi +``` + +## Error Handling + +Common issues and solutions: + +- **Binary not found**: The specified binary is not installed +- **Version check failed**: Could not determine latest version (check network connection) +- **Permission denied**: Insufficient permissions to read version information \ No newline at end of file diff --git a/www/apps/docs/content/contribution/b.md b/www/apps/docs/content/contribution/b.md new file mode 100644 index 0000000..aa644e9 --- /dev/null +++ b/www/apps/docs/content/contribution/b.md @@ -0,0 +1,75 @@ +--- +sidebar_label: "b contribution" +sidebar_position: 2 +--- + +# Contribute by improving b + +In this document, you'll learn how you can contribute to b by improving the codebase. + +## Overview + +b is a binary manager for developers that simplifies installation, versioning, and management of command-line tools. It is written in Go and is used to build the core functionality of b. + +### Binaries + +Binaries are the actual command-line tools that are managed by b. They are stored in the `binaries` directory in the b repository and registered in `cmd/b/main.go`. + +``` +├── cmd +│ └── b +│ └── # All supported binaries are added here +├── pkg +│ ├── binaries +│ │ └── # Binary definitions +│ ├── binary +│ │ └── # Binary management and download logic +│ ├── cli +│ │ └── # CLI subcommands +│ ├── path +│ │ └── # PATH management +│ └── state +│ └── # State management +└── test + ├── e2e + │ └── # End-to-end tests + └── testutil + └── # Test utilities +``` + +## How to contribute + +If you’re adding a new library or contributing to the codebase, you need to fork the repository, create a new branch, and make all changes necessary in your repository. Then, once you’re done, create a PR in the b repository. + +### Base Branch + +When you make an edit to an existing documentation page or fork the repository to make changes to the documentation, you have to create a new branch. + +Documentation contributions always use `main` as the base branch. Make sure to also open your PR against the `main` branch. + +### Pull Request Conventions + +When you create a pull request, prefix the title with `fix:`, `feat:` or `docs:`. + + + +In the body of the PR, explain clearly what the PR does. If the PR solves an issue, use [closing keywords](https://docs.github.com/en/issues/tracking-your-work-with-issues/linking-a-pull-request-to-an-issue#linking-a-pull-request-to-an-issue-using-a-keyword) with the issue number. For example, “Closes #1333”. + + + + +## Testing + +Feel free to add tests if you think it's necessary. + +### Coverage + +We strive to have 100% test coverage. When you add a new library or make changes to an existing library, make sure to add tests that cover all functionality. + +## Linting + +To lint the code, run the following command: + +```bash +gofmt -w . +``` diff --git a/www/apps/docs/content/contribution/docs.md b/www/apps/docs/content/contribution/docs.md new file mode 100644 index 0000000..1121d38 --- /dev/null +++ b/www/apps/docs/content/contribution/docs.md @@ -0,0 +1,492 @@ +--- +sidebar_label: "Docs" +sidebar_position: 1 +--- + +# Docs Contribution Guidelines + +Thank you for your interest in contributing to the documentation! You will be helping the open source community and other developers interested in learning more about b and using it. + +:::tip + +This guide is specific to contributing to the documentation. If you’re interested in contributing to b’s codebase, check out the [contributing guidelines in the Medusa GitHub repository](https://github.com/fentas/b/blob/develop/CONTRIBUTING.md). + +::: + +## Documentation Workspace + +b's documentation projects are all part of the documentation yarn workspace, which you can find in the [b repository](https://github.com/fentas/b) under the `www` directory. + +The workspace has the following two directories: + +- `apps`: this directory holds the different documentation websites and projects. + - `docs`: includes the codebase for the main documentation website (the one you're viewing this documentation on). It's built with [Docusaurus](https://docusaurus.io/). +- `packages`: this directory holds the shared packages and components necessary for the development of the projects in the `apps` directory. + - `docs-ui` includes the shared React components between the different apps. + - `eslint-config-docs` includes the shared ESLint configuration between the different apps and packages. + - `tailwind` includes the shared Tailwind CSS configuration between the different apps and packages. + - `tsconfig` includes the shared TypeScript configuration between the different apps and packages. + +--- + +## Documentation Content + +### Main Documentation Website + +The documentation content is written in Markdown format and is located in the [www/apps/docs/content](https://github.com/fentas/b/tree/develop/www/apps/docs/content) directory of the **b** repository. If you’re not familiar with Markdown, check out [this cheat sheet](https://www.markdownguide.org/cheat-sheet/) for a quick start. + +You’ll also find MDX files. MDX files combine the power of Markdown with React. So, the content of the file can contain JSX components and import statements, among other features. You can learn more about [MDX in docusaurus’s guide.](https://docusaurus.io/docs/markdown-features/react). + +## Style Guide + +When you contribute to the documentation content, make sure to follow the [documentation style guide](https://www.notion.so/Style-Guide-Docs-fad86dd1c5f84b48b145e959f36628e0). + +--- + +## How to Contribute + +If you’re fixing errors in an existing documentation page, you can scroll down to the end of the page and click on the “Edit this page” link. You’ll be redirected to the GitHub edit form of that page and you can make edits directly and submit a pull request (PR). + +If you’re adding a new page or contributing to the codebase, you need to fork the repository, create a new branch, and make all changes necessary in your repository. Then, once you’re done, create a PR in the **b** repository. + +### Base Branch + +When you make an edit to an existing documentation page or fork the repository to make changes to the documentation, you have to create a new branch. + +Documentation contributions always use `main` as the base branch. Make sure to also open your PR against the `main` branch. + +### Pull Request Conventions + +When you create a pull request, prefix the title with `docs:`. + + + +In the body of the PR, explain clearly what the PR does. If the PR solves an issue, use [closing keywords](https://docs.github.com/en/issues/tracking-your-work-with-issues/linking-a-pull-request-to-an-issue#linking-a-pull-request-to-an-issue-using-a-keyword) with the issue number. For example, “Closes #1333”. + + + +--- + +## Main Documentation Sidebar + +When you add a new page to the documentation, you must add the new page in `www/apps/docs/sidebars.js`. In this file, an object is exported. This object holds more than one sidebar. The properties of the object indicate the internal sidebar name, and the value is an array of sidebar items in that sidebar. + +You can learn more about the syntax used [here](https://docusaurus.io/docs/sidebar/items). + +### Terminology + +When the documentation page is a conceptual or an overview documentation, the label in the sidebar should start with a noun. + +When the documentation page is tutorial documentation, the label in the sidebar should start with a verb. Exceptions to this rule are integration documentation and upgrade guides. + +### Sidebar Icon + +To add an icon to the sidebar item, start by checking if the icon is already exported in the file `www/apps/docs/src/theme/Icon`. If not, you can either export the icon from the [@medusajs/icons](https://docs.medusajs.com/ui/icons/overview), or add the new icon as a React component in the `www/apps/docs/src/theme/Icon/Icon/index.tsx` file, where `` is the camel-case name of your icon. The icon must be added to the React component as an SVG element. + +For example: + +```tsx title="www/docs/src/theme/Icon/Bolt/index.tsx" +import React from "react" +import { IconProps } from "@medusajs/icons/dist/types" + +export default function IconBolt(props: IconProps) { + return ( + + + + ) +} +``` + +Make sure to set the `stroke` or `fill` of the icon to `currentColor` as shown in the example above. The source code for the Sidebar passes the icon a color. So, this ensures the color is correctly used. + +If you added a new icon, add it in the exported object in the file `www/apps/docs/src/theme/Icon/index.ts`, where the property is the kebab-case version of the icon's name, and the value being the component you created. Make sure to add it in the correct alphabetical position as well. For example: + +```ts title="www/docs/src/theme/Icon/index.ts" +import IconBolt from "./Bolt" +import IconBoltSolid from "./BoltSolid" +// other imports + +export default { + // other icons + "bolt": IconBolt, + "bolt-solid": IconBoltSolid, + // other icons +} +``` + +Finally, you can add the icon to the sidebar item by adding a `sidebar_icon` property to the `customProps` property and setting its value to the kebab-cased version of the icon's name. For example: + +```js title="www/docs/sidebars.js" +module.exports = { + // other sidebars + homepage: [ + { + // other properties + customProps: { + sidebar_icon: "book-open", + }, + }, + // other items + ], +} +``` + +### Sidebar Item Types + +There are different sidebar item types used in the documentation: + +- Homepage Items: If a sidebar item is shown under the `homepage` sidebar, you should set the `className` property of the item to `homepage-sidebar-item`. You can use this with other sidebar item types. For example: + + ```js title="www/docs/sidebars.js" + module.exports = { + // other sidebars + homepage: [ + { + type: "doc", + // other properties + className: "homepage-sidebar-item", + }, + // other items + ], + } + ``` + +- Sidebar Title: This item is used as a title to the sidebar, typically added at the top of the sidebar. You typically would also use an icon with it. To use this item, add a `sidebar_is_title` property to the `customProps` object of the item with its value being `true`. For example: + + ```js title="www/docs/sidebars.js" + module.exports = { + // other sidebars + modules: [ + // other items + { + type: "doc", + id: "development/howtos/yq", + label: "How to use yq", + customProps: { + sidebar_is_title: true, + sidebar_icon: "puzzle", + }, + }, + // other items + ], + } + ``` + +- Back Item: This item is used to show a back button, typically at the top of the sidebar. To use this item, add the `sidebar_is_back_link` property to the `customProps` object of the item, with its value set to true. Also, add the `sidebar_icon` property to the `customProps` object with its value set to `back-arrow`. For example: + + ```js title="www/docs/sidebars.js" + module.exports = { + // other sidebars + core: [ + // other items + { + type: "ref", + id: "homepage", + label: "Back to home", + customProps: { + sidebar_is_back_link: true, + sidebar_icon: "back-arrow", + }, + }, + // other items + ], + } + ``` + +- Group Divider Item: This item is used if a sidebar item does not link to any document and is only used to separate between sidebar sections. The item must be of type `html`, and its `value` property holds the text that should be shown in the divider. You must also add in the `customProps` object of the item the property `sidebar_is_group_divider` with its value being `true`. For example: + + ```js title="www/docs/sidebars.js" + module.exports = { + // other sidebars + homepage: [ + // other items + { + type: "html", + value: "Browse Docs", + customProps: { + sidebar_is_group_divider: true, + }, + className: "homepage-sidebar-item", + }, + // other items + ], + } + ``` + +- Group Headline Item: This item is used if a sidebar item does not link to any document and is only used to indicate the beginning of a new section or group in the sidebar. To use this item, set the `type` of the item to `category`, and add the `sidebar_is_group_headline` property to the `customProps` object of the item, with its value set to `true`. For example: + + ```js title="www/docs/sidebars.js" + module.exports = { + // other sidebars + modules: [ + // other items + { + type: "category", + label: "Regions and Currencies", + collapsible: false, + customProps: { + sidebar_is_group_headline: true, + }, + items: [ + // items within group or section + ], + }, + // other items + ], + } + ``` + +- Soon Item: This item is used to indicate that a certain guide will be added soon, but it does not actually link to any document. To use this item, set the `type` of the item to `link`, its `href` property to `#`, and add to the `customProps` object the property `sidebar_is_soon` with its value set to `true`. For example: + + ```js title="www/docs/sidebars.js" + module.exports = { + // other sidebars + modules: [ + // other items + { + type: "link", + href: "#", + label: "Currencies", + customProps: { + sidebar_is_soon: true, + }, + }, + // other items + ], + } + ``` + +--- + +## Notes and Additional Information + +When displaying notes and additional information on a documentation page, use [Admonitions](https://docusaurus.io/docs/markdown-features/admonitions). Make sure the type of admonition used matches the note’s importance to the current document. + +If the note is something developers have to be careful of doing or not doing, use the `danger` admonition based on how critical it is. + +If the note displays helpful information and tips that may not be in the scope of the documentation page, use the `tip` admonition. + +For all other note types, use the `note` admonition. + +--- + +## Images + +If you are adding images to a documentation page, you can host the image on [Imgur](https://imgur.com) for free to include it in the PR. Our team will later upload it to our image hosting. + +--- + +## Code Blocks + +:::note + +These sections only works in the main documentation website. + +::: + +### Use Tabs with Code Blocks + +To use Tabs with Code Blocks, you have to use [Docusaurus's `Tabs` and `TabItem` components](https://docusaurus.io/docs/markdown-features/code-blocks#multi-language-support-code-blocks). + +You must also pass to the `Tabs` component the prop `isCodeTabs={true}` to ensure correct styling. + +For example: + +~~~md +import Tabs from '@theme/Tabs'; +import TabItem from '@theme/TabItem'; + + + + + + ```bash + curl -sL https://get.arg.sh | sudo tee /usr/local/bin/argsh > /dev/null + sudo chmod +x /usr/local/bin/argsh + ``` + + + + + ```bash + curl -sL https://get.arg.sh > .bin/argsh + chmod +x .bin/argsh + ``` + + + +~~~ + +### Add Title to Code Block with Tabs + +If you want to add a title to a code block with tabs, add the `codeTitle` prop to the `Tabs` component. + +For example: + +```md + +``` + +### Add Title to Code Block without Tabs + +To add a title to a code block without tabs: + +~~~md +```js title="src/index.ts" +console.log("hello") +``` +~~~ + +### Remove Report Button + +Some code block don't need a report button. To remove the report button, use the `noReport` metadata. + +For example: + +~~~md +```bash noReport +b install argsh +``` +~~~ + +### Remove Copy Button + +Some code blocks don't need a copy button. To remove the copy button, use the `noCopy` metadata: + +For example: + +~~~md +```bash noCopy +source ~/.bashrc +``` +~~~ + +--- + + +## Linting with Vale + +Argsh uses [Vale](https://vale.sh/) to lint documentation pages and perform checks on incoming PRs into the repository. + +### Result of Vale PR Checks + +You can check the result of running the "lint" action on your PR by clicking the Details link next to it. You can find there all errors that you need to fix. + +### Run Vale Locally + +If you want to check your work locally, you can do that by: + +1. [Installing direnv](https://direnv.net/) and running `direnv allow` in the root directory of the argsh repository. +2. Linting with `vale`: + +```bash +# to lint content for the main documentation +argsh lint --vale error +``` + +### VS Code Extension + +To facilitate writing documentation, you can optionally use the [Vale VS Code extension](https://marketplace.visualstudio.com/items?itemName=chrischinchilla.vale-vscode). This will show you any errors in your documentation while writing it. + +### Linter Exceptions + +If it's needed to break some style guide rules in a document, you can wrap the parts that the linter shouldn't scan with the following comments in the `md` or `mdx` files: + +```md + + +content that shouldn't be scanned for errors here... + + +``` + +You can also disable specific rules. For example: + +```md + + +Argsh supports Bash version 4.3 and later. + + +``` + +If you use this in your PR, you must justify its usage. + +--- + +## Linting with ESLint + +Argsh uses ESlint to lint code blocks both in the content and the code base of the documentation apps. + +### Linting Code/Content with ESLint + +Each PR runs through a check that lints the code in the content files using ESLint. The action's name is `code-docs-eslint`. + +If you want to check code ESLint errors locally and fix them, you can do that by: + +1\. Set up [direnv](https://direnv.net/) then run in the `root` directory: + +```bash +direnv allow +``` + +2\. Then execute the following command anywhere: + +```bash +gofmt -s -w . +``` + +This will fix any fixable errors, and show errors that require your action. + +### ESLint Exceptions + +:::note + +These exceptions only work in the main documentation website. + +::: + +If some code blocks have errors that can't or shouldn't be fixed, you can add the following command before the code block: + +~~~md + + +```js +console.log("This block isn't linted") +``` + +```js +console.log("This block is linted") +``` +~~~ + +You can also disable specific rules. For example: + +~~~md + + +```js +console.log("This block can use semicolons"); +``` + +```js +console.log("This block can't use semi colons") +``` +~~~ + +--- \ No newline at end of file diff --git a/www/apps/docs/content/getting-started.mdx b/www/apps/docs/content/getting-started.mdx new file mode 100644 index 0000000..5bc9122 --- /dev/null +++ b/www/apps/docs/content/getting-started.mdx @@ -0,0 +1,137 @@ +--- +description: 'Install b and get started with binary management for your development projects' +--- + +# Getting Started with b + +Get up and running with **b** in just a few minutes. **b** helps you manage command-line tools and binaries for your development projects with automatic PATH management and version control. + +## Installation + +### Quick Install (Recommended) + +```bash +# Install b +curl -sSL https://github.com/fentas/b/releases/latest/download/install.sh | bash + +# Or using wget +wget -qO- https://github.com/fentas/b/releases/latest/download/install.sh | bash +``` + +### Manual Installation + +1. Download the latest release for your platform from [GitHub Releases](https://github.com/fentas/b/releases) +2. Extract the binary to a directory in your PATH +3. Make it executable: `chmod +x b` + +### Verify Installation + +```bash +b version +``` + +## Quick Start + +### 1. Initialize a Project + +```bash +# Navigate to your project directory +cd my-project + +# Initialize b configuration +b init +``` + +This creates a `b.yaml` file in your project root. + +### 2. Install Tools + +```bash +# Install specific versions +b install jq@jq-1.6 kubectl@v1.28.0 + +# Install latest versions +b install terraform helm + +# Install and add to b.yaml +b install --add docker-compose@v2.20.0 +``` + +### 3. Use Your Tools + +Tools are automatically available in your PATH: + +```bash +jq --version # 1.6 +kubectl version # 1.28.0 +``` + +## Common Workflows + +### Team Collaboration + +Share tool requirements with your team: + +```bash +# Add tools to b.yaml +b install --add jq@jq-1.6 kubectl@v1.28.0 + +# Commit b.yaml to version control +git add b.yaml +git commit -m "Add project tool requirements" + +# Team members can install the same tools +b install # Installs all tools from b.yaml +``` + +### CI/CD Integration + +Use **b** in your CI/CD pipelines: + +```yaml +# .github/workflows/ci.yml +steps: + - uses: actions/checkout@v4 + - name: Install b + run: curl -sSL https://github.com/fentas/b/releases/latest/download/install.sh | bash + - name: Install project tools + run: b install + - name: Run tests + run: | + kubectl version --client + jq --version +``` + +### Version Management + +```bash +# List installed tools +b list + +# Update tools to latest versions +b update + +# Update specific tools +b update kubectl terraform + +# Search for available tools +b search docker +``` + +## Configuration + +The `b.yaml` file defines your project's tool requirements: + +```yaml +binaries: + jq: + version: "jq-1.6" + kubectl: + version: "v1.28.0" + terraform: + version: "latest" +``` + +## Next Steps + +- [CLI Reference](/b/overview) - Complete command reference \ No newline at end of file diff --git a/www/apps/docs/content/glossary.mdx b/www/apps/docs/content/glossary.mdx new file mode 100644 index 0000000..548f136 --- /dev/null +++ b/www/apps/docs/content/glossary.mdx @@ -0,0 +1,71 @@ +--- +description: "Learn about the different terms related to b" +--- + +# Glossary + +This glossary defines key terms and concepts used throughout the **b** documentation. + +## B + +**b** - A modern binary manager for developers that simplifies installation, versioning, and management of command-line tools. + +**b.yaml** - The configuration file that defines binary dependencies for a project. Contains version specifications and metadata. + +**Binary** - An executable command-line tool managed by **b** (e.g., `jq`, `kubectl`, `terraform`). + +**Binary Manager** - A tool that automates the installation, versioning, and PATH management of command-line utilities. + +## C + +**CLI** - Command Line Interface. The text-based interface used to interact with **b**. + +**Configuration Discovery** - The process by which **b** automatically locates and loads the nearest `b.yaml` file in the directory hierarchy. + +**Context-Aware** - **b**'s ability to automatically detect and use project-specific configurations without explicit file paths. + +## D + +**Dependency Management** - The process of managing tool versions and ensuring consistent environments across different systems. + +**Download Cache** - Local storage where **b** keeps downloaded binaries to avoid re-downloading. + +## E + +**Environment Isolation** - Keeping project-specific tool versions separate from system-wide installations. + +**Executable** - A binary file that can be run as a command. + +## G + +**GitHub Releases** - The source from which **b** downloads most binaries, using GitHub's release API. + +**Global Installation** - Installing **b** system-wide, making it available to all users. + +## I + +**Installation Path** - The directory where **b** installs and manages binaries (typically `~/.local/share/b/bin/`). + +**Isolation** - Keeping different projects' tool versions separate to avoid conflicts. + +## P + +**PATH** - The environment variable that tells the shell where to find executable programs. + +**PATH Management** - **b**'s automatic handling of adding managed binaries to the system PATH. + +**Project-Based Configuration** - Using **b.yaml** files to define tool requirements specific to individual projects. + +## S + +**Subcommand** - A secondary command that follows the main **b** command (e.g., `install`, `update`, `list`). + +**Symlink** - A symbolic link that points to the actual binary location, used for PATH management. + +## V + +**Version Constraint** - Specifications in **b.yaml** that define which version of a tool to use (e.g., `"1.6"`, `"latest"`). + +**Version Resolution** - The process of determining which specific version to install based on constraints. + +**Versioning** - Managing different versions of the same tool for different projects or requirements. diff --git a/www/apps/docs/content/homepage.mdx b/www/apps/docs/content/homepage.mdx new file mode 100644 index 0000000..c89f351 --- /dev/null +++ b/www/apps/docs/content/homepage.mdx @@ -0,0 +1,103 @@ +--- +id: homepage +title: b Documentation +description: "b is a binary manager for developers - install, manage, and version your command-line tools effortlessly." +slug: / +hide_table_of_contents: true +hide_footer: true +--- + +import DocCardList from '@theme/DocCardList'; +import DocCard from '@theme/DocCard'; +import Icons from '@theme/Icon'; +import ThemedImage from '@theme/ThemedImage'; + +
+ +
+ +# + +**b** is a modern binary manager that simplifies how developers install, manage, and version their command-line tools. With project-based configuration and automatic PATH management, **b** ensures your development environment is consistent and reproducible. + +## Why b? + +Managing command-line tools across different projects and environments is challenging: + +- **Version Conflicts**: Different projects need different tool versions +- **Environment Setup**: Complex PATH management and installation procedures +- **Team Consistency**: Ensuring everyone uses the same tool versions +- **CI/CD Integration**: Reproducible builds with exact tool versions + +**b** solves these problems by providing: + +✅ **Project-based Configuration** - Each project defines its required tools +✅ **Automatic PATH Management** - Tools are available when you need them +✅ **Version Control** - Lock specific versions for reproducible builds +✅ **Team Collaboration** - Share tool requirements via `b.yaml` +✅ **CI/CD Ready** - Simple integration with build pipelines + + + +## Quick Example + +```bash +# Initialize a new project +b init + +# Install tools for your project +b install jq@1.6 kubectl@1.28.0 + +# Tools are now available +jq --version # 1.6 +kubectl version --client # 1.28.0 +``` + +## Explore b + + \ No newline at end of file diff --git a/www/apps/docs/content/troubleshooting.mdx b/www/apps/docs/content/troubleshooting.mdx new file mode 100644 index 0000000..79acd1f --- /dev/null +++ b/www/apps/docs/content/troubleshooting.mdx @@ -0,0 +1,262 @@ +--- +title: Troubleshooting +description: Common issues and solutions when using b +--- + +# Troubleshooting + +This guide covers common issues you might encounter when using **b** and their solutions. + +## Installation Issues + +### Permission Denied + +**Problem**: Getting permission denied errors during installation. + +**Solution**: +```bash +# Make sure you have write permissions to the installation directory +sudo curl -sSL https://github.com/fentas/b/releases/latest/download/install.sh | bash + +# Or install to a user directory +curl -sSL https://github.com/fentas/b/releases/latest/download/install.sh | bash -s -- --prefix=$HOME/.local +``` + +### Command Not Found + +**Problem**: `b: command not found` after installation. + +**Solution**: +```bash +# Add b to your PATH +echo 'export PATH="$HOME/.local/bin:$PATH"' >> ~/.bashrc +source ~/.bashrc + +# Or for zsh +echo 'export PATH="$HOME/.local/bin:$PATH"' >> ~/.zshrc +source ~/.zshrc +``` + +## Configuration Issues + +### b.yaml Not Found + +**Problem**: `b.yaml configuration file not found` + +**Solution**: +```bash +# Initialize b in your project directory +cd your-project +b init + +# Or create b.yaml manually +cat > b.yaml << EOF +binaries: {} +EOF +``` + +### Invalid Configuration + +**Problem**: YAML parsing errors in **b.yaml** + +**Solution**: +```bash +# Validate your YAML syntax +# Check for proper indentation and structure +cat b.yaml + +# Example valid format: +binaries: + jq: + version: "jq-1.6" + kubectl: + version: "v1.28.0" +``` + +## Binary Installation Issues + +### Download Failures + +**Problem**: Failed to download binary from GitHub releases + +**Solutions**: +```bash +# Check your internet connection +curl -I https://github.com + +# Try with verbose output for debugging +b install --verbose jq + +# Check GitHub API rate limits +curl -H "Accept: application/vnd.github.v3+json" https://api.github.com/rate_limit +``` + +### Version Not Found + +**Problem**: Specified version doesn't exist + +**Solution**: +```bash +# Search for available versions +b search jq + +# Use 'latest' for the most recent version +b install jq@latest + +# Check the project's GitHub releases page +``` + +### Binary Not Executable + +**Problem**: Installed binary is not executable + +**Solution**: +```bash +# Check binary permissions +ls -la ~/.local/share/b/bin/ + +# Make executable if needed +chmod +x ~/.local/share/b/bin/jq + +# Reinstall the binary +b install --force jq +``` + +## PATH and Environment Issues + +### Tools Not Available + +**Problem**: Installed tools are not available in PATH + +**Solution**: +```bash +# Check if b's bin directory is in PATH +echo $PATH | grep -o '[^:]*b[^:]*' + +# Source your shell configuration +source ~/.bashrc # or ~/.zshrc + +# Check b's configuration +b list +``` + +### Conflicting Versions + +**Problem**: System version conflicts with b-managed version + +**Solution**: +```bash +# Check which version is being used +which jq +jq --version + +# Ensure b's bin directory comes first in PATH +export PATH="$HOME/.local/share/b/bin:$PATH" + +# Update your shell configuration +echo 'export PATH="$HOME/.local/share/b/bin:$PATH"' >> ~/.bashrc +``` + +## Performance Issues + +### Slow Downloads + +**Problem**: Binary downloads are very slow + +**Solutions**: +```bash +# Use a different mirror or CDN if available +# Check your network connection +speedtest-cli + +# Try downloading during off-peak hours +# Consider using a VPN if geographical restrictions apply +``` + +### Large Binary Cache + +**Problem**: **b**'s cache directory is taking up too much space + +**Solution**: +```bash +# Check cache size +du -sh ~/.local/share/b/ + +# Clean up old versions (if implemented) +b clean + +# Manually remove old binaries +rm -rf ~/.local/share/b/cache/ +``` + +## CI/CD Issues + +### GitHub Actions Failures + +**Problem**: **b** installation fails in GitHub Actions + +**Solution**: +```yaml +# Use specific version and add error handling +steps: + - name: Install b + run: | + curl -sSL https://github.com/fentas/b/releases/latest/download/install.sh | bash + echo "$HOME/.local/bin" >> $GITHUB_PATH + + - name: Verify b installation + run: b version + + - name: Install project tools + run: b install +``` + +### Docker Container Issues + +**Problem**: **b** doesn't work properly in Docker containers + +**Solution**: +```dockerfile +# Install b in Dockerfile +RUN curl -sSL https://github.com/fentas/b/releases/latest/download/install.sh | bash +ENV PATH="/root/.local/bin:$PATH" + +# Or use multi-stage build +FROM alpine AS b-installer +RUN apk add --no-cache curl +RUN curl -sSL https://github.com/fentas/b/releases/latest/download/install.sh | bash + +FROM alpine +COPY --from=b-installer /root/.local/bin/b /usr/local/bin/b +``` + +## Getting Help + +If you're still experiencing issues: + +1. **Check the logs**: Run commands with `--verbose` flag for detailed output +2. **Search existing issues**: Check [GitHub Issues](https://github.com/fentas/b/issues) +3. **Create a new issue**: Include your OS, **b** version, and error messages +4. **Join the community**: Participate in discussions and get help from other users + +### Debug Information + +When reporting issues, include this information: + +```bash +# b CLI version +b version + +# Operating system +uname -a + +# Shell information +echo $SHELL +echo $PATH + +# Configuration +cat b.yaml + +# Installed binaries +b list +``` \ No newline at end of file diff --git a/www/apps/docs/docusaurus.config.js b/www/apps/docs/docusaurus.config.js new file mode 100644 index 0000000..f89648c --- /dev/null +++ b/www/apps/docs/docusaurus.config.js @@ -0,0 +1,283 @@ +/* eslint-disable @typescript-eslint/no-var-requires */ +import "dotenv/config" +import fs from "fs" +import path from "path" +import { themes as prismThemes } from "prism-react-renderer" +const reverseSidebarItems = require("./src/utils/reverse-sidebar") +const excludeSidebarResults = require("./src/utils/exclude-sidebar-results") +const createLatestReleaseRedirects = require("./src/utils/createLatestReleaseRedirects") + +const announcementBar = JSON.parse(fs.readFileSync("./announcement.json")) + +/** @type {import('@medusajs/docs').MedusaDocusaurusConfig} */ +const config = { + title: "b", + tagline: "Explore and learn how to use b", + url: "https://binary.help", + baseUrl: "/", + onBrokenLinks: "throw", + onBrokenMarkdownLinks: "throw", + favicon: "favicon.ico", + organizationName: "b", + projectName: "b/www", + // experimental_router: "browser", + markdown: { + mdx1Compat: { + comments: true, + admonitions: false, + headingIds: false, + }, + mermaid: true, + }, + plugins: [ + require.resolve("docusaurus-plugin-image-zoom"), + async function tailwindPlugin() { + return { + name: "docusaurus-tailwindcss", + configurePostCss(postcssOptions) { + // Appends TailwindCSS and AutoPrefixer. + postcssOptions.plugins.push(require("tailwindcss")) + postcssOptions.plugins.push(require("autoprefixer")) + return postcssOptions + }, + } + }, + function webpackPlugin() { + return { + name: "custom-webpack-plugin", + configureWebpack() { + return { + devServer: { + client: { + overlay: { + runtimeErrors: (error) => { + if ( + error.message === + "ResizeObserver loop completed with undelivered notifications." + ) { + return false + } + return true + }, + }, + }, + }, + } + }, + } + }, + [ + "./src/plugins/docusaurus-plugin-diagram2code-showcase", + { + directoryPath: path.join(__dirname, "diagrams"), + outputPath: path.join(__dirname, "src", "utils"), + }, + ], + // [ + // '@docusaurus/plugin-client-redirects', + // { + // // redirects: [], + // // createRedirects: createLatestReleaseRedirects, + // // async redirects() { + // // const redirects = await createLatestReleaseRedirects(); + // // return redirects; + // // } + // }, + // ], + ], + themes: ["@docusaurus/theme-mermaid"], + themeConfig: { + mermaid: { + theme: { + light: "base", + dark: "base", + }, + options: { + themeVariables: { + background: "#FFFFFF", + mainBkg: "#FFFFFF", + primaryColor: "#FFFFFF", + primaryTextColor: "#030712", + primaryBorderColor: "#D1D5DB", + nodeBorder: "#D1D5DB", + lineColor: "#11181C", + fontFamily: "Inter", + fontSize: "13px", + tertiaryColor: "#F3F4F6", + tertiaryBorderColor: "#D1D5DB", + tertiaryTextColor: "#030712", + clusterBkg: "#F3F4F6", + }, + }, + }, + image: "img/docs-meta.jpg", + colorMode: { + defaultMode: "light", + disableSwitch: false, + respectPrefersColorScheme: true, + }, + algoliaConfig: { + appId: process.env.ALGOLIA_APP_ID || "temp", + apiKey: process.env.ALGOLIA_API_KEY || "temp", + indexNames: { + docs: process.env.DOCS_ALGOLIA_INDEX_NAME, + api: process.env.API_ALGOLIA_INDEX_NAME, + }, + filters: [ + { + value: "docs", + label: "Docs", + }, + ], + defaultFiltersByPath: [], + defaultFilters: ["docs"], + }, + analytics: { + apiKey: process.env.SEGMENT_API_KEY || "temp", + }, + prism: { + defaultLanguage: "ts", + additionalLanguages: ["bash", "json"], + plugins: ["line-numbers", "show-language"], + theme: { + ...prismThemes.vsDark, + plain: { + ...prismThemes.vsDark.plain, + backgroundColor: "#111827", + }, + }, + }, + zoom: { + selector: ".markdown :not(.no-zoom-img) > img:not(.no-zoom-img)", + }, + navbar: { + hideOnScroll: false, + logo: { + alt: "arg.sh Logo", + src: "img/logo-icon.svg", + srcDark: "img/logo-icon-dark.svg", + width: 20, + height: 20, + }, + items: [ + { + type: "docSidebar", + sidebarId: "homepage", + label: "Docs", + position: "left", + }, + { + type: "search", + position: "right", + }, + ], + }, + navbarActions: [ + { + type: "button", + label: "Report an Issue", + className: "max-[1014px]:hidden", + href: "https://github.com/fentas/b/issues/new?assignees=&labels=type%3A+docs&template=docs.yml", + }, + ], + mobileLogo: { + alt: "arg.sh", + src: "img/logo-mobile.png", + srcDark: "img/logo-mobile-dark.png", + width: 82, + height: 20, + }, + footer: { + copyright: `© ${new Date().getFullYear()} Jan Guth (@fentas). All rights reserved.`, + }, + socialLinks: [ + { + type: "github", + href: "https://github.com/fentas/b", + }, + ], + reportCodeLinkPrefix: + "https://github.com/fentas/b/issues/new?assignees=&labels=type%3A+docs&template=docs.yml", + footerFeedback: { + event: "survey", + }, + docs: { + sidebar: { + hideable: true, + autoCollapseCategories: true, + }, + }, + cloudinaryConfig: { + cloudName: process.env.CLOUDINARY_CLOUD_NAME || "", + flags: ["fl_lossy", "f_auto"], + resize: { + action: "pad", + aspectRatio: "16:9", + }, + roundCorners: 16, + }, + }, + presets: [ + [ + "@docusaurus/preset-classic", + { + docs: { + sidebarPath: require.resolve("./sidebars.js"), + editUrl: "https://github.com/fentas/b/edit/develop/www/apps/docs", + path: "content", + routeBasePath: "/", + remarkPlugins: [ + [require("@docusaurus/remark-plugin-npm2yarn"), { sync: true }], + ], + showLastUpdateTime: true, + // breadcrumbs: false, + async sidebarItemsGenerator({ + defaultSidebarItemsGenerator, + ...args + }) { + const sidebarItems = await defaultSidebarItemsGenerator(args) + return reverseSidebarItems( + excludeSidebarResults(sidebarItems, args.item), + args.item + ) + }, + }, + theme: { + customCss: require.resolve("./src/css/custom.css"), + }, + gtag: { + trackingID: "G-S7G7X3JYS3", + }, + sitemap: { + filename: "sitemap-docs.xml", + }, + // clientRedirects: { + // createRedirects: createLatestReleaseRedirects, + // }, + }, + ], + ], + webpack: { + jsLoader: (isServer) => ({ + loader: require.resolve("swc-loader"), + options: { + jsc: { + parser: { + syntax: "typescript", + tsx: true, + }, + target: "es2017", + }, + module: { + type: isServer ? "commonjs" : "es6", + }, + }, + }), + }, +} + +if (Object.keys(announcementBar).length) { + config.themeConfig.announcementBar = announcementBar +} + +export default config diff --git a/www/apps/docs/package.json b/www/apps/docs/package.json new file mode 100644 index 0000000..b8c649f --- /dev/null +++ b/www/apps/docs/package.json @@ -0,0 +1,83 @@ +{ + "name": "docs", + "version": "0.0.0", + "private": true, + "scripts": { + "docusaurus": "docusaurus", + "dev": "docusaurus clear && docusaurus start", + "dev:monorepo": "yarn dev --port 3001", + "build": "docusaurus build", + "swizzle": "docusaurus swizzle", + "deploy": "docusaurus deploy", + "clear": "docusaurus clear", + "start": "docusaurus serve", + "start:monorepo": "yarn start --port 3001", + "write-translations": "docusaurus write-translations", + "write-heading-ids": "docusaurus write-heading-ids", + "lint": "eslint --ext .js,.jsx,.ts,.tsx . --fix", + "lint:content": "eslint --no-eslintrc -c .content.eslintrc.js content --fix", + "diagram2code:generate": "docusaurus diagram2code:generate" + }, + "dependencies": { + "@babel/preset-react": "^7.18.6", + "@cloudinary/react": "^1.11.2", + "@cloudinary/url-gen": "^1.9.2", + "@docusaurus/core": "^3.1.0", + "@docusaurus/plugin-client-redirects": "^3.8.1", + "@docusaurus/preset-classic": "^3.1.0", + "@docusaurus/remark-plugin-npm2yarn": "^3.1.0", + "@docusaurus/theme-mermaid": "^3.1.0", + "@mdx-js/mdx": "3.0.0", + "@mdx-js/react": "3", + "@medusajs/icons": "^1.2.0", + "@svgr/webpack": "6.2.1", + "@swc/core": "^1.3.102", + "autoprefixer": "^10.4.14", + "clsx": "^1.1.1", + "docs-ui": "*", + "docusaurus-plugin-image-zoom": "^1.0.1", + "dotenv": "^16.0.3", + "eslint": "^8.49.0", + "eslint-config-docs": "*", + "file-loader": "^6.2.0", + "lodash": "^4.17.21", + "mdast-util-mdx": "^3.0.0", + "node-fetch": "2", + "postcss": "^8.4.21", + "prism-react-renderer": "^2.3.0", + "react": "^18.2.0", + "react-dom": "^18.2.0", + "react-tooltip": "5.7.4", + "react-transition-group": "^4.4.5", + "tailwind": "*", + "tailwindcss": "^3.3.2", + "tsconfig": "*", + "url-loader": "^4.1.1" + }, + "browserslist": { + "production": [ + ">0.5%", + "not dead", + "not op_mini all" + ], + "development": [ + "last 1 chrome version", + "last 1 firefox version", + "last 1 safari version" + ] + }, + "devDependencies": { + "@babel/plugin-proposal-decorators": "^7.22.15", + "@docusaurus/module-type-aliases": "^3.1.0", + "@docusaurus/tsconfig": "^3.1.0", + "@docusaurus/types": "^3.1.0", + "@types/react": "^18.2.0", + "@types/react-dom": "^18.2.0", + "@types/react-transition-group": "^4.4.6", + "swc-loader": "^0.2.3", + "typescript": "~5.2.2" + }, + "engines": { + "node": ">=18.0" + } +} diff --git a/www/apps/docs/sidebars.js b/www/apps/docs/sidebars.js new file mode 100644 index 0000000..6dc8a4e --- /dev/null +++ b/www/apps/docs/sidebars.js @@ -0,0 +1,184 @@ +/** + * Custom sidebar definitions for b CLI documentation: + * - To declare a sidebar element as part of the homepage sidebar, add className: 'homepage-sidebar-item' + * - To add an icon: + * - add the icon in www/docs/src/theme/Icon//index.ts as a React SVG element if it doesn't exist, where `` is the camel case name of the icon + * - add the mapping to the icon in www/docs/src/theme/Icon/index.js + * - add in customProps sidebar_icon: 'icon-name' + * - To add a group divider add in customProps sidebar_is_group_divider: true and set the label/value to the title that should appear in the divider. + * - To add a back item, add in customProps: + * - sidebar_is_back_link: true + * - sidebar_icon: `back-arrow` + * - To add a sidebar title, add in customProps sidebar_is_title: true + * - To add a group headline, add in customProps sidebar_is_group_headline: true + * - To add a coming soon link (with a badge), add in customProps sidebar_is_soon: true + * - To add a badge, add in customProps sidebar_badge with its value being the props to pass to the Badge component. + */ + +/** @type {import('@docusaurus/plugin-content-docs').SidebarsConfig} */ +module.exports = { + homepage: [ + { + type: "doc", + id: "homepage", + label: "Overview", + customProps: { + sidebar_icon: "book-open", + }, + className: "homepage-sidebar-item", + }, + { + type: "doc", + id: "getting-started", + label: "Getting Started", + customProps: { + sidebar_icon: "rocket-launch", + }, + className: "homepage-sidebar-item", + }, + { + type: "doc", + id: "troubleshooting", + label: "Troubleshooting", + customProps: { + sidebar_icon: "exclamation-circle-solid", + }, + className: "homepage-sidebar-item", + }, + { + type: "html", + value: "Browse Docs", + customProps: { + sidebar_is_group_divider: true, + }, + className: "homepage-sidebar-item", + }, + { + type: "ref", + id: "b/overview", + label: "CLI Reference", + customProps: { + sidebar_icon: "command-line", + }, + className: "homepage-sidebar-item", + }, + { + type: "html", + value: "Additional Resources", + customProps: { + sidebar_is_group_divider: true, + }, + className: "homepage-sidebar-item", + }, + { + type: "doc", + id: "troubleshooting", + label: "Troubleshooting", + customProps: { + sidebar_icon: "bug", + }, + className: "homepage-sidebar-item", + }, + { + type: "category", + link: { + type: "doc", + id: "contribution/docs", + }, + label: "Contribution Guidelines", + customProps: { + sidebar_icon: "document-text", + }, + className: "homepage-sidebar-item", + items: [ + { + type: "autogenerated", + dirName: "contribution", + }, + ], + }, + { + type: "doc", + id: "glossary", + label: "Glossary", + customProps: { + sidebar_icon: "book-open", + }, + className: "homepage-sidebar-item", + }, + { + type: "doc", + id: "about", + label: "About", + customProps: { + sidebar_icon: "light-bulb", + }, + className: "homepage-sidebar-item", + }, + ], + core: [ + { + type: "ref", + id: "homepage", + label: "Back to home", + customProps: { + sidebar_is_back_link: true, + sidebar_icon: "back-arrow", + }, + }, + { + type: "doc", + id: "b/overview", + label: "Overview", + customProps: { + sidebar_is_title: true, + sidebar_icon: "server-stack", + }, + }, + { + type: "category", + label: "Subcommands", + collapsible: false, + customProps: { + sidebar_is_group_headline: true, + }, + items: [ + { + type: "doc", + id: "b/subcommands/init", + label: "init", + }, + { + type: "doc", + id: "b/subcommands/install", + label: "install", + }, + { + type: "doc", + id: "b/subcommands/list", + label: "list", + }, + { + type: "doc", + id: "b/subcommands/update", + label: "update", + }, + { + type: "doc", + id: "b/subcommands/search", + label: "search", + }, + { + type: "doc", + id: "b/subcommands/version", + label: "version", + }, + { + type: "doc", + id: "b/subcommands/request", + label: "request", + }, + ], + }, + ], +} diff --git a/www/apps/docs/src/components/BorderedIcon/index.tsx b/www/apps/docs/src/components/BorderedIcon/index.tsx new file mode 100644 index 0000000..b6235ca --- /dev/null +++ b/www/apps/docs/src/components/BorderedIcon/index.tsx @@ -0,0 +1,33 @@ +import React from "react" +import type { BorderedIconProps as UiBorderedIconProps } from "docs-ui" +import { BorderedIcon as UiBorderedIcon } from "docs-ui" +import { useColorMode } from "@docusaurus/theme-common" + +type BorderedIconProps = { + icon?: { + light: string + dark?: string + } +} & Omit + +const BorderedIcon: React.FC = ({ + icon = null, + ...props +}) => { + const { colorMode } = useColorMode() + + return ( + + ) +} + +export default BorderedIcon diff --git a/www/apps/docs/src/components/CloudinaryImage/index.tsx b/www/apps/docs/src/components/CloudinaryImage/index.tsx new file mode 100644 index 0000000..b73ac78 --- /dev/null +++ b/www/apps/docs/src/components/CloudinaryImage/index.tsx @@ -0,0 +1,106 @@ +import React from "react" +import { useThemeConfig } from "@docusaurus/theme-common" +// @ts-expect-error: wait until docusaurus uses type: module +import { Cloudinary } from "@cloudinary/url-gen" +import MDXImg, { Props as MDXImgProps } from "@theme/MDXComponents/Img" +import { + pad, + imaggaScale, + imaggaCrop, + crop, + fit, + minimumPad, + fill, + scale, + limitFit, + thumbnail, + limitFill, + minimumFit, + limitPad, + fillPad, +} from "@cloudinary/url-gen/actions/resize" +import { byRadius } from "@cloudinary/url-gen/actions/roundCorners" +import { ThemeConfig } from "@medusajs/docs" + +const resizeActions = { + pad: pad, + imaggaScale: imaggaScale, + imaggaCrop: imaggaCrop, + crop: crop, + fit: fit, + minimumPad: minimumPad, + fill: fill, + scale: scale, + limitFit: limitFit, + thumbnail: thumbnail, + limitFill: limitFill, + minimumFit: minimumFit, + limitPad: limitPad, + fillPad: fillPad, +} + +const imageRegex = + /^https:\/\/res.cloudinary.com\/.*\/upload\/v[0-9]+\/(?.*)$/ + +type CloudinaryImageProps = MDXImgProps + +const CloudinaryImage: React.FC = ({ src, ...props }) => { + const { cloudinaryConfig } = useThemeConfig() as ThemeConfig + const matchingRegex = src.match(imageRegex) + if ( + !cloudinaryConfig || + !matchingRegex?.groups || + !matchingRegex.groups.imageId + ) { + // either cloudinary isn't configured or + // could not match url to a cloudinary url + // default to docusaurus's image component + return + } + + const cloudinary = new Cloudinary({ + cloud: { + cloudName: cloudinaryConfig.cloudName, + }, + }) + const image = cloudinary.image( + matchingRegex.groups.imageId.replaceAll("%20", " ") + ) + + cloudinaryConfig.flags?.forEach((flag) => image.addTransformation(flag)) + + if (cloudinaryConfig.roundCorners) { + image.roundCorners(byRadius(cloudinaryConfig.roundCorners)) + } + if (cloudinaryConfig.resize) { + const action = resizeActions[cloudinaryConfig.resize.action] + let resizeAction = action() + if (props.width || props.height) { + if (props.width) { + resizeAction = resizeAction.width(props.width) + } + + if (props.height) { + resizeAction = resizeAction.height(props.height) + } + } else if (cloudinaryConfig.resize.aspectRatio) { + resizeAction = resizeAction.aspectRatio( + cloudinaryConfig.resize.aspectRatio + ) + } else { + if (cloudinaryConfig.resize.width) { + resizeAction = resizeAction.width(cloudinaryConfig.resize.width) + } + + if (cloudinaryConfig.resize.height) { + resizeAction = resizeAction.height(cloudinaryConfig.resize.height) + } + } + + image.resize(resizeAction) + } + + return +} + +export default CloudinaryImage diff --git a/www/apps/docs/src/components/DetailsList/index.tsx b/www/apps/docs/src/components/DetailsList/index.tsx new file mode 100644 index 0000000..29dba99 --- /dev/null +++ b/www/apps/docs/src/components/DetailsList/index.tsx @@ -0,0 +1,34 @@ +import React from "react" +import Details from "../../theme/Details" +import clsx from "clsx" +import { MarkdownContent } from "docs-ui" + +type TroubleshootingSection = { + title: string + content: React.ReactNode +} + +type DetailsListProps = { + sections: TroubleshootingSection[] +} & React.AllHTMLAttributes + +const DetailsList: React.FC = ({ sections }) => { + return ( + <> + {sections.map(({ title, content }, index) => ( +
+ {React.isValidElement(content) && content} + {!React.isValidElement(content) && typeof content === "string" && ( + content + )} +
+ ))} + + ) +} + +export default DetailsList diff --git a/www/apps/docs/src/components/Diagram2CodeSpecs/index.tsx b/www/apps/docs/src/components/Diagram2CodeSpecs/index.tsx new file mode 100644 index 0000000..9a1d946 --- /dev/null +++ b/www/apps/docs/src/components/Diagram2CodeSpecs/index.tsx @@ -0,0 +1,54 @@ +import React from "react" +import { Diagram2CodeSpec } from "@medusajs/docs" +import Tabs from "@theme/Tabs" +import TabItem from "@theme/TabItem" +import { specs } from "../../utils/specs" +import CodeBlock from "../../theme/CodeBlock" +import Mermaid from "@docusaurus/theme-mermaid/lib/theme/Mermaid/index.js" +import Heading from "@theme/Heading" + +type WorkflowReferenceProps = { + specName: string +} + +const Diagram2CodeSpecs = ({ specName }: WorkflowReferenceProps) => { + if (!Object.hasOwn(specs, specName)) { + return <> + } + const specsData: Diagram2CodeSpec = specs[specName] + + const transformTitle = (title: string): string => { + return title + .split("-") + .map((word) => `${word.charAt(0).toUpperCase()}${word.substring(1)}`) + .join(" ") + } + + return ( + <> + {!Object.keys(specsData).length && No diagrams found} + {Object.entries(specsData).map(([name, diagram2code]) => ( + + {transformTitle(name)} + + + + + {diagram2code.code && ( + + {diagram2code.code} + + )} + + + ))} + + ) +} + +export default Diagram2CodeSpecs diff --git a/www/apps/docs/src/components/DocSidebarItemIcon/index.tsx b/www/apps/docs/src/components/DocSidebarItemIcon/index.tsx new file mode 100644 index 0000000..40bfc51 --- /dev/null +++ b/www/apps/docs/src/components/DocSidebarItemIcon/index.tsx @@ -0,0 +1,48 @@ +import React from "react" +import icons, { IconName } from "../../theme/Icon" +import BorderedIcon from "../BorderedIcon" +import clsx from "clsx" + +type DocSidebarItemIconProps = { + icon?: IconName + is_title?: boolean + is_disabled?: boolean +} & React.HTMLAttributes + +const DocSidebarItemIcon: React.FC = ({ + icon, + is_title, + is_disabled, +}) => { + let IconComponent = undefined + if (icon) { + IconComponent = icons[icon] + } + + return ( + <> + {is_title && ( + + )} + {!is_title && IconComponent && ( + + )} + + ) +} + +export default DocSidebarItemIcon diff --git a/www/apps/docs/src/components/Feedback/index.tsx b/www/apps/docs/src/components/Feedback/index.tsx new file mode 100644 index 0000000..fb352db --- /dev/null +++ b/www/apps/docs/src/components/Feedback/index.tsx @@ -0,0 +1,28 @@ +import React from "react" +import { + Feedback as UiFeedback, + type FeedbackProps as UiFeedbackProps, + GITHUB_ISSUES_PREFIX, +} from "docs-ui" +import useIsBrowser from "@docusaurus/useIsBrowser" +import { useLocation } from "@docusaurus/router" +import clsx from "clsx" + +type FeedbackProps = Omit + +const Feedback = (props: FeedbackProps) => { + const isBrowser = useIsBrowser() + const location = useLocation() + + return ( + + ) +} + +export default Feedback diff --git a/www/apps/docs/src/components/Footer/SocialLinks/index.tsx b/www/apps/docs/src/components/Footer/SocialLinks/index.tsx new file mode 100644 index 0000000..31949b1 --- /dev/null +++ b/www/apps/docs/src/components/Footer/SocialLinks/index.tsx @@ -0,0 +1,44 @@ +import React from "react" +import IconTwitter from "@site/src/theme/Icon/Twitter" +import IconGitHub from "@site/src/theme/Icon/GitHub" +import IconDiscord from "@site/src/theme/Icon/Discord" +import IconLinkedIn from "@site/src/theme/Icon/LinkedIn" +import { SocialLink } from "@medusajs/docs" +import Link from "@docusaurus/Link" + +type SocialLinksProps = { + links?: SocialLink[] +} & React.HTMLAttributes + +const SocialLinks: React.FC = ({ links = [] }) => { + const socialIcons = { + twitter: ( + + ), + github: ( + + ), + discord: ( + + ), + linkedin: ( + + ), + } + + return ( +
+ {links.map((link) => ( + + {socialIcons[link.type]} + + ))} +
+ ) +} + +export default SocialLinks diff --git a/www/apps/docs/src/components/Glossary/index.tsx b/www/apps/docs/src/components/Glossary/index.tsx new file mode 100644 index 0000000..1f680c8 --- /dev/null +++ b/www/apps/docs/src/components/Glossary/index.tsx @@ -0,0 +1,50 @@ +import React, { useMemo } from "react" +import Heading from "@theme/Heading" +import { GlossaryType, getGlossary } from "../../utils/glossary" +import Link from "@docusaurus/Link" + +type GlossaryProps = React.HTMLAttributes + +type GroupedGlossary = { + [letter: string]: GlossaryType[] +} + +const Glossary: React.FC = (props) => { + const groupedGlossary: GroupedGlossary = useMemo(() => { + const glossary = getGlossary() + glossary.sort((a, b) => { + return a.title.localeCompare(b.title) + }) + const grouped: GroupedGlossary = {} + glossary.forEach((glossaryItem) => { + const firstChar = glossaryItem.title.charAt(0).toLowerCase() + grouped[firstChar] = [...(grouped[firstChar] || []), glossaryItem] + }) + + return grouped + }, []) + + return ( +
+ {Object.entries(groupedGlossary).map(([letter, glossary], index) => ( + + + {letter.toUpperCase()} + +
    + {glossary.map((glossaryItem, index) => ( +
  • + + {glossaryItem.title} + + : {glossaryItem.content} +
  • + ))} +
+
+ ))} +
+ ) +} + +export default Glossary diff --git a/www/apps/docs/src/components/LargeCard/index.tsx b/www/apps/docs/src/components/LargeCard/index.tsx new file mode 100644 index 0000000..91b2a5c --- /dev/null +++ b/www/apps/docs/src/components/LargeCard/index.tsx @@ -0,0 +1,98 @@ +import React from "react" +import clsx from "clsx" +import Link from "@docusaurus/Link" +import { Badge } from "docs-ui" +import BorderedIcon from "../BorderedIcon" +import { IconProps } from "@medusajs/icons/dist/types" + +type LargeCardProps = { + Icon: React.FC + image: { + light: string + dark?: string + } + title: string + action?: { + href?: string + } + isSoon?: boolean + className?: string +} & React.HTMLAttributes + +const LargeCard: React.FC = ({ + Icon, + image, + title, + action: { href } = { + href: "", + }, + isSoon = false, + className = "", + children, +}) => { + return ( +
+
+ {isSoon && ( + + Guide coming soon + + )} + {(Icon || image) && ( + + )} +
+ + {title} + +
+
+ {children} +
+
+ {href && ( + + )} +
+ ) +} + +export default LargeCard diff --git a/www/apps/docs/src/components/LargeCardList/index.tsx b/www/apps/docs/src/components/LargeCardList/index.tsx new file mode 100644 index 0000000..32b40ed --- /dev/null +++ b/www/apps/docs/src/components/LargeCardList/index.tsx @@ -0,0 +1,30 @@ +import React from "react" +import clsx from "clsx" + +type LargeCardListProps = { + colSize?: string + className?: string +} & React.HTMLAttributes + +const LargeCardList: React.FC = ({ + colSize = "4", + className, + children, +}) => { + return ( +
+ {children} +
+ ) +} + +export default LargeCardList diff --git a/www/apps/docs/src/components/MobileLogo/index.tsx b/www/apps/docs/src/components/MobileLogo/index.tsx new file mode 100644 index 0000000..45a16aa --- /dev/null +++ b/www/apps/docs/src/components/MobileLogo/index.tsx @@ -0,0 +1,79 @@ +import React from "react" +import Link from "@docusaurus/Link" +import useBaseUrl from "@docusaurus/useBaseUrl" +import useDocusaurusContext from "@docusaurus/useDocusaurusContext" +import { useThemeConfig, type NavbarLogo } from "@docusaurus/theme-common" +import ThemedImage from "@theme/ThemedImage" +import type { Props } from "@theme/Logo" +import { ThemeConfig } from "@medusajs/docs" + +function LogoThemedImage({ + logo, + alt, + imageClassName, +}: { + logo: NavbarLogo + alt: string + imageClassName?: string +}) { + const sources = { + light: useBaseUrl(logo.src), + dark: useBaseUrl(logo.srcDark || logo.src), + } + const themedImage = ( + + ) + + // Is this extra div really necessary? + // introduced in https://github.com/facebook/docusaurus/pull/5666 + return imageClassName ? ( +
{themedImage}
+ ) : ( + themedImage + ) +} + +export default function MobileLogo(props: Omit): JSX.Element { + const { + siteConfig: { title }, + } = useDocusaurusContext() + const { + navbar: { title: navbarTitle }, + mobileLogo: logo, + } = useThemeConfig() as ThemeConfig + + const { imageClassName, titleClassName, ...propsRest } = props + const logoLink = useBaseUrl(logo?.href || "/") + + // If visible title is shown, fallback alt text should be + // an empty string to mark the logo as decorative. + const fallbackAlt = navbarTitle ? "" : title + + // Use logo alt text if provided (including empty string), + // and provide a sensible fallback otherwise. + const alt = logo?.alt ?? fallbackAlt + + return ( + + {logo && ( + + )} + {navbarTitle != null && {navbarTitle}} + + ) +} diff --git a/www/apps/docs/src/components/Navbar/Actions/index.tsx b/www/apps/docs/src/components/Navbar/Actions/index.tsx new file mode 100644 index 0000000..79de22d --- /dev/null +++ b/www/apps/docs/src/components/Navbar/Actions/index.tsx @@ -0,0 +1,80 @@ +import React from "react" +import { NavbarAction } from "@medusajs/docs" +import Icon from "../../../theme/Icon" +import clsx from "clsx" +import { Button, Tooltip } from "docs-ui" +import Link from "@docusaurus/Link" + +type NavbarActionsProps = { + items: NavbarAction[] + className?: string +} & React.HTMLAttributes + +const NavbarActions: React.FC = ({ + items = [], + className = "", +}) => { + return ( +
+ {items.map((item, index) => { + // eslint-disable-next-line no-case-declarations + const ItemIconElm = item.Icon + const ItemIcon = item.icon ? Icon[item.icon] : null + switch (item.type) { + case "link": + return ( + + + {item.label} + {ItemIconElm} + {ItemIcon && } + + + ) + case "button": + return ( + + + + ) + default: + return <> + } + })} +
+ ) +} + +export default NavbarActions diff --git a/www/apps/docs/src/components/ParameterTypes/Items/index.tsx b/www/apps/docs/src/components/ParameterTypes/Items/index.tsx new file mode 100644 index 0000000..ede8aa6 --- /dev/null +++ b/www/apps/docs/src/components/ParameterTypes/Items/index.tsx @@ -0,0 +1,291 @@ +import { + CopyButton, + DetailsSummary, + ExpandableNotice, + FeatureFlagNotice, + InlineCode, + MarkdownContent, +} from "docs-ui" +import React, { useEffect, useMemo, useRef, useState } from "react" +import Details from "../../../theme/Details" +import clsx from "clsx" +import { Parameter } from ".." +import { + ArrowDownLeftMini, + ArrowsPointingOutMini, + Link, + TriangleRightMini, +} from "@medusajs/icons" +import IconFlagMini from "../../../theme/Icon/FlagMini" +import decodeStr from "../../../utils/decode-str" +import { useLocation } from "@docusaurus/router" +import useDocusaurusContext from "@docusaurus/useDocusaurusContext" +import isInView from "../../../utils/is-in-view" + +type CommonProps = { + level?: number + expandUrl?: string + sectionTitle?: string +} + +type ParameterTypesItemProps = { + parameter: Parameter + elementKey: number +} & CommonProps & + React.AllHTMLAttributes + +const ParameterTypesItem = ({ + parameter, + level = 1, + expandUrl, + elementKey, + sectionTitle, +}: ParameterTypesItemProps) => { + const location = useLocation() + + const { + siteConfig: { url }, + } = useDocusaurusContext() + + const groupName = useMemo(() => { + switch (level) { + case 1: + return "group/parameterOne" + case 2: + return "group/parameterTwo" + case 3: + return "group/parameterThree" + case 4: + return "group/parameterFour" + } + }, [level]) + const borderForGroupName = useMemo(() => { + switch (level) { + case 1: + return "group-open/parameterOne:border-solid group-open/parameterOne:border-0 group-open/parameterOne:border-b" + case 2: + return "group-open/parameterTwo:border-solid group-open/parameterTwo:border-0 group-open/parameterTwo:border-b" + case 3: + return "group-open/parameterThree:border-solid group-open/parameterThree:border-0 group-open/parameterThree:border-b" + case 4: + return "group-open/parameterFour:border-solid group-open/parameterFour:border-0 group-open/parameterFour:border-b" + } + }, [level]) + const rotateForGroupName = useMemo(() => { + switch (level) { + case 1: + return "group-open/parameterOne:rotate-90" + case 2: + return "group-open/parameterTwo:rotate-90" + case 3: + return "group-open/parameterThree:rotate-90" + case 4: + return "group-open/parameterFour:rotate-90" + } + }, [level]) + function getItemClassNames(details = true) { + return clsx( + "odd:[&:not(:first-child):not(:last-child)]:!border-y last:not(:first-child):!border-t", + "first:!border-t-0 first:not(:last-child):!border-b last:!border-b-0 even:!border-y-0", + details && groupName, + !details && borderForGroupName + ) + } + const formatId = (str: string) => { + return str.replaceAll(" ", "_") + } + const parameterId = useMemo(() => { + return sectionTitle + ? `#${formatId(sectionTitle)}-${formatId( + parameter.name + )}-${level}-${elementKey}` + : "" + }, [sectionTitle, parameter, elementKey]) + const parameterPath = useMemo( + () => `${location.pathname}${parameterId}`, + [location, parameterId] + ) + const parameterUrl = useMemo( + () => `${url}${parameterPath}`, + [url, parameterPath] + ) + + const ref = useRef() + const [isSelected, setIsSelected] = useState(false) + + useEffect(() => { + if (!parameterId.length) { + return + } + + const shouldScroll = location.hash === parameterId + if (shouldScroll && !isSelected && ref.current && !isInView(ref.current)) { + ref.current.scrollIntoView({ + block: "center", + }) + } + + setIsSelected(shouldScroll) + }, [parameterId]) + + function getSummary(parameter: Parameter, nested = true) { + return ( + + + {parameter.description} + + {parameter.defaultValue && ( +

+ Default: {parameter.defaultValue} +

+ )} + + ) : undefined + } + expandable={parameter.children?.length > 0} + hideExpandableIcon={true} + className={clsx( + getItemClassNames(false), + "py-1 pr-1", + level === 1 && "pl-1", + level === 2 && "pl-3", + level === 3 && "pl-[120px]", + level === 4 && "pl-[160px]", + !nested && "cursor-default", + isSelected && "animate-flash animate-bg-surface" + )} + onClick={(e) => { + const targetElm = e.target as HTMLElement + if (targetElm.tagName.toLowerCase() === "a") { + window.location.href = + targetElm.getAttribute("href") || window.location.href + return + } + }} + summaryRef={!nested ? ref : undefined} + id={!nested && parameterId ? parameterId : ""} + > +
+ {nested && ( + + )} + {!nested && level > 1 && ( + + )} + {level === 1 && parameterId.length > 0 && ( + ) => { + e.preventDefault() + e.stopPropagation() + }} + > + + + )} +
+ {decodeStr(parameter.name)} + + + {parameter.type} + + + {parameter.optional === false && ( + + Required + + )} + {parameter.featureFlag && ( + + } + /> + )} + {parameter.expandable && ( + } + /> + )} +
+
+
+ ) + } + + return ( + <> + {parameter.children?.length > 0 && ( +
+ {parameter.children && ( + + )} +
+ )} + {(parameter.children?.length || 0) === 0 && getSummary(parameter, false)} + + ) +} + +type ParameterTypesItemsProps = { + parameters: Parameter[] +} & CommonProps + +const ParameterTypesItems = ({ + parameters, + ...rest +}: ParameterTypesItemsProps) => { + return ( +
+ {parameters.map((parameter, key) => ( + + ))} +
+ ) +} + +export default ParameterTypesItems diff --git a/www/apps/docs/src/components/ParameterTypes/index.tsx b/www/apps/docs/src/components/ParameterTypes/index.tsx new file mode 100644 index 0000000..5c52ad8 --- /dev/null +++ b/www/apps/docs/src/components/ParameterTypes/index.tsx @@ -0,0 +1,45 @@ +import clsx from "clsx" +import React, { Suspense, lazy } from "react" +import { Loading } from "docs-ui" + +export type Parameter = { + name: string + type: string + optional?: boolean + defaultValue?: string + description?: string + featureFlag?: string + expandable: boolean + children?: Parameter[] +} + +type ParameterTypesType = { + parameters: Parameter[] + expandUrl?: string + sectionTitle?: string +} & React.HTMLAttributes + +const ParameterTypesItems = lazy(async () => import("./Items")) + +const ParameterTypes = ({ + parameters, + className, + ...props +}: ParameterTypesType) => { + return ( +
+ }> + + +
+ ) +} + +export default ParameterTypes diff --git a/www/apps/docs/src/components/QueryNote/index.tsx b/www/apps/docs/src/components/QueryNote/index.tsx new file mode 100644 index 0000000..f3d61c1 --- /dev/null +++ b/www/apps/docs/src/components/QueryNote/index.tsx @@ -0,0 +1,29 @@ +import Admonition, { Props as AdmonitionProps } from "@theme/Admonition" +import { useQueryStringValue } from "@docusaurus/theme-common/internal" +import React from "react" + +type QueryNoteProps = { + query: { + key: string + value?: string + } + admonition: AdmonitionProps +} & React.HTMLAttributes + +const QueryNote: React.FC = ({ + query: { key, value = "" }, + admonition, + children, +}) => { + const queryValue = useQueryStringValue(key) + + return ( + <> + {queryValue === value && ( + {children} + )} + + ) +} + +export default QueryNote diff --git a/www/apps/docs/src/components/StructuredData/HowTo/index.tsx b/www/apps/docs/src/components/StructuredData/HowTo/index.tsx new file mode 100644 index 0000000..48c828b --- /dev/null +++ b/www/apps/docs/src/components/StructuredData/HowTo/index.tsx @@ -0,0 +1,44 @@ +import React from "react" +import Head from "@docusaurus/Head" +import { useLocation } from "@docusaurus/router" +import useDocusaurusContext from "@docusaurus/useDocusaurusContext" +import type { TOCItem } from "@docusaurus/mdx-loader" + +type StructuredDataHowToProps = { + toc: readonly TOCItem[] + title: string +} + +const StructuredDataHowTo: React.FC = ({ + toc, + title, +}) => { + const location = useLocation() + const { + siteConfig: { url }, + } = useDocusaurusContext() + const mainUrl = `${url}/${location.pathname}` + + return ( + + + + ) +} + +export default StructuredDataHowTo diff --git a/www/apps/docs/src/components/UiIcon/index.tsx b/www/apps/docs/src/components/UiIcon/index.tsx new file mode 100644 index 0000000..a1dd0a9 --- /dev/null +++ b/www/apps/docs/src/components/UiIcon/index.tsx @@ -0,0 +1,27 @@ +import React from "react" +import ThemedImage from "@theme/ThemedImage" + +type UiIconProps = { + lightIcon: string + darkIcon?: string + alt?: string +} + +const UiIcon: React.FC = ({ + lightIcon, + darkIcon = "", + alt = "", +}) => { + return ( + + ) +} + +export default UiIcon diff --git a/www/apps/docs/src/css/_docusaurus.css b/www/apps/docs/src/css/_docusaurus.css new file mode 100644 index 0000000..20166d2 --- /dev/null +++ b/www/apps/docs/src/css/_docusaurus.css @@ -0,0 +1,287 @@ +/** This CSS file includes tailwind styling definitions for classes defined by docusaurus **/ +html, +body { + @apply h-full; +} + +.cards-grid { + @apply grid gap-x-1 auto-rows-fr; +} + +.cards-grid.grid-6 { + @apply md:grid-cols-2 grid-cols-1; +} + +.cards-grid.grid-4 { + @apply lg:grid-cols-3 md:grid-cols-2 grid-cols-1; +} + +h1 + .cards-grid, +h1 + .card-wrapper, +h2 + .cards-grid, +h2 + .card-wrapper, +h3 + .cards-grid, +h3 + .card-wrapper { + @apply mt-1.5; +} + +.markdown p + img, +.markdown .alert, +.markdown .code-wrapper { + @apply mb-2; +} + +.markdown h2, +.markdown h3, +.markdown p + .code-wrapper, +.markdown p + .tabs-wrapper, +.markdown p + .alert, +.markdown p + section, +video { + @apply mt-2; +} + +.theme-code-block { + @apply border border-solid border-medusa-code-border; +} + +.markdown p + .card-wrapper { + @apply mt-1.5; +} + +.card + p, +details + p { + @apply mt-2; +} + +.card-highlighted { + @apply relative mb-4 bg-medusa-bg-subtle dark:bg-medusa-bg-base hover:bg-medusa-bg-subtle-hover dark:hover:bg-medusa-bg-base-hover; +} + +.col.toc-wrapper { + --ifm-col-width: var(--ifm-toc-width); +} + +.markdown-doc-wrapper--fluid { + @apply max-w-[inherit]; +} + +:global(.docusaurus-mt-lg) { + @apply mt-3; +} + +:global(#__docusaurus) { + @apply min-h-full flex flex-col; +} + +.code-tabs .theme-code-block { + @apply !rounded-t-none !rounded-b +} + +[class*=codeLineNumber] { + @apply text-medusa-code-text-subtle !pl-0; +} + +.prism-code { + @apply xs:max-w-[90%] text-code-body [&_*]:text-code-body xs:after:content-[''] xs:after:rounded xs:after:absolute; + @apply xs:after:right-0 xs:after:top-0 xs:after:w-[calc(10%+24px)] xs:after:h-full xs:after:bg-code-fade; +} + +.prism-code:not(:hover)::-webkit-scrollbar-thumb, +.prism-code:not(:hover)::-webkit-scrollbar-track { + @apply xs:invisible; +} + +.prism-code:hover::-webkit-scrollbar-thumb, +.prism-code:hover::-webkit-scrollbar-track { + @apply xs:opacity-100 +} + +.prism-code { + @apply bg-transparent break-words !outline-none; +} + +.prism-code div { + @apply !outline-none focus:!outline-none active:!outline-none; +} + +.code-tabs { + @apply relative; +} + +.sidebar-desktop nav { + --ifm-scrollbar-track-background-color: transparent !important; + --ifm-scrollbar-thumb-background-color: transparent !important; + --ifm-scrollbar-thumb-hover-background-color: transparent !important; +} + +.main-wrapper { + @apply max-w-xl mx-auto xl:min-w-xl w-full; +} + +.theme-doc-breadcrumbs { + @apply hidden; +} + +article { + @apply max-w-[960px]; +} + +.padding-top--md { + @apply !pt-3; +} + +.margin-bottom--lg { + @apply !mb-1; +} + +details summary { + @apply cursor-pointer; +} + +.reference-table { + @apply !table table-fixed w-full; +} + +.reference-table p { + --ifm-paragraph-margin-bottom: 0; +} + +.reference-table.table-col-4 th, +.reference-table.table-col-4 td { + @apply [&:nth-child(1)]:!w-1/5 [&:nth-child(2)]:!w-1/5 [&:nth-child(3)]:!w-2/5 [&:nth-child(4)]:!w-1/5; +} + +.reference-table th:nth-child(1), +.reference-table td:nth-child(1) { + @apply [&:nth-child(1)]:!w-[30%] [&:nth-child(2)]:!w-[30%] [&:nth-child(3)]:!w-2/5; +} + +.reference-table .tooltip-container code { + @apply whitespace-nowrap; +} + +.reference-table .theme-code-block span { + @apply !max-w-full !break-words !whitespace-break-spaces; +} + +.theme-code-block { + @apply !bg-medusa-code-bg-base; +} + +.reference-table .code-block-numbering { + @apply !block; +} + +.container { + @apply !pt-3 !max-w-full; +} + +.pagination-nav { + @apply hidden; +} + +.theme-doc-footer { + @apply !mt-0 border-0 !border-t border-solid !border-medusa-border-base; + @apply pt-2; +} + +.theme-last-updated { + @apply font-normal not-italic text-compact-small-plus; +} + +.theme-last-updated, +.theme-last-updated b { + @apply !font-normal; +} + +.medium-zoom-overlay { + @apply z-[400]; +} + +.medium-zoom-image--opened { + @apply z-[400]; +} + +details > div { + --docusaurus-details-decoration-color: transparent !important; +} + +.row--justify-end { + @apply justify-end; +} + +.docs-page-container { + @apply !px-0; +} + +.search-result-match { + @apply text-medusa-fg-base; + @apply bg-medusa-bg-highlight py-0.25 px-0; +} + +.navbar { + @apply z-[399] p-0 border-0 border-b border-solid border-medusa-border-base; +} + +html:not(.plugin-redoc) .navbar:not(.navbar-sidebar--show) { + @apply supports-[backdrop-filter]:bg-transparent supports-[backdrop-filter]:backdrop-blur-md; +} + +.navbar__link { + @apply text-compact-small-plus; +} + +.navbar__brand { + @apply mr-0; +} + +.navbar__logo { + @apply w-[82px] h-[20px] lg:w-[20px] lg:h-[20px] flex justify-center items-center !mr-0; +} + +.navbar__item { + @apply p-0 lg:!block !hidden; +} + +h1 { + @apply !text-h1; +} + +h2 { + @apply !text-h2; +} + +h3 { + @apply !text-h3; +} + +h1, h2, h3, h4, h5, h6 { + @apply text-medusa-fg-base; +} + +.markdown > h1:first-child, +.markdown > h2, +.markdown > h3 { + @apply mb-0.5; +} + +.markdown > p { + @apply mb-0.5; +} + +.markdown > p img { + @apply mt-0.5; +} + +.markdown { + @apply mb-0; +} + +*::selection { + @apply bg-medusa-bg-highlight; +} + +.prism-code *::selection, .code-header *::selection { + @apply bg-medusa-code-text-highlight; +} \ No newline at end of file diff --git a/www/apps/docs/src/css/_variables.css b/www/apps/docs/src/css/_variables.css new file mode 100644 index 0000000..c1a00d8 --- /dev/null +++ b/www/apps/docs/src/css/_variables.css @@ -0,0 +1,144 @@ +/* You can override the default Infima variables here. */ +@import url('https://fonts.googleapis.com/css2?family=Inter:wght@100;200;300;400;500;600;700;800;900&display=swap'); +@import url('https://fonts.googleapis.com/css2?family=Roboto+Mono&display=swap'); + +:root { + /* Base Styles */ + --ifm-hr-margin-vertical: theme(margin.2); + --ifm-leading: theme(lineHeight.DEFAULT); + --ifm-list-left-padding: theme(spacing.1); + --font-inter: "Inter"; + --font-roboto-mono: "Roboto Mono"; + + /* Colors */ + --ifm-color-primary: theme(colors.medusa.fg.base); + --ifm-background-color: theme(colors.medusa.bg.base.DEFAULT); + --ifm-background-surface-color: theme(colors.medusa.bg.subtle.DEFAULT); + --ifm-color-content: theme(colors.medusa.fg.subtle) !important; + --ifm-color-content-secondary: var(--ifm-color-content); + --ifm-base-border-color: theme(colors.medusa.border.base); + --ifm-strong-border-color: theme(colors.medusa.border.strong); + --ifm-hr-background-color: theme(colors.medusa.border.base); + + /* Fonts */ + --ifm-code-font-size: theme(fontSize.code-label); + --ifm-font-family-base: theme(fontFamily.base); + --ifm-font-family-monospace: theme(fontFamily.monospace); + --ifm-font-size-base: theme(fontSize.medium[0]); + --ifm-line-height-base: theme(fontSize.medium[1].lineHeight); + --ifm-font-weight-base: theme(fontSize.medium[1].fontWeight); + + /* Headings */ + /** Due to how docusaurus styles headings, the styles are applied on h1, h2, and h3 again in _docusaurus **/ + --ifm-color-headers: var(--ifm-color-primary); + --ifm-h1-font-size: theme(fontSize.h1[0]); + --ifm-h1-line-height: theme(fontSize.h1[1].lineHeight); + --ifm-h1-weight: theme(fontSize.h1[1].fontWeight); + --ifm-h2-font-size: theme(fontSize.h2[0]); + --ifm-h2-line-height: theme(fontSize.h2[1].lineHeight); + --ifm-h2-weight: theme(fontSize.h2[1].fontWeight); + --ifm-h3-font-size: theme(fontSize.h3[0]); + --ifm-h3-line-height: theme(fontSize.h3[1].lineHeight); + --ifm-h3-weight: theme(fontSize.h3[1].fontWeight); + --ifm-h4-font-size: var(--ifm-font-size-base); + + /* Links */ + --ifm-link-color: theme(colors.medusa.fg.interactive.DEFAULT); + --ifm-link-hover-color: theme(colors.medusa.fg.interactive.hover); + --ifm-link-decoration: none; + --ifm-link-hover-decoration: none; + + /* Sidebar */ + --ifm-menu-link-padding-vertical: 6px; + --ifm-menu-link-padding-horizontal: theme(margin.1); + --ifm-menu-color: theme(colors.medusa.fg.subtle); + --ifm-menu-color-active: theme(colors.medusa.fg.base); + --ifm-menu-color-background-hover: theme(colors.medusa.bg.base.hover); + --ifm-menu-color-background-active: theme(colors.medusa.bg.base.pressed); + + /* Toc */ + --ifm-toc-border-color: theme(colors.medusa.border.base); + --ifm-toc-link-color: theme(colors.medusa.fg.subtle); + --ifm-toc-padding-horizontal: theme(padding.1); + + /* Navbar */ + --ifm-navbar-background-color: var(--ifm-background-color); + --ifm-navbar-shadow: none; + --ifm-navbar-padding-vertical: 12px; + --ifm-navbar-padding-horizontal: theme(padding[1.5]); + --ifm-navbar-item-padding-vertical: 6px; + --ifm-navbar-item-padding-horizontal: theme(padding[1]); + --ifm-navbar-height: theme(height.navbar); + --ifm-navbar-link-hover-color: theme(colors.medusa.fg.base); + --ifm-navbar-link-color: theme(colors.medusa.fg.subtle); + + /* Inline Code */ + --ifm-code-border-radius: theme(borderRadius.DEFAULT); + --ifm-code-padding-horizontal: theme(padding[0.5]); + --ifm-code-background: theme(colors.medusa.tag.neutral.bg.DEFAULT) !important; + + /* Code Blocks */ + --ifm-pre-background: theme(colors.medusa.code.bg.base.DEFAULT); + --ifm-pre-padding: theme(padding.1); + + /* Tabs */ + --ifm-tabs-color-active: var(--ifm-color-primary); + + /* Tooltip */ + --rt-opacity: theme(opacity.100) !important; + --rt-color-dark: theme(colors.medusa.bg.base.DEFAULT) !important; + --rt-color-white: var(--ifm-color-content) !important; + + /* Footer */ + --ifm-footer-color: theme(colors.medusa.fg.muted); + --ifm-footer-background-color: transparent; + --ifm-footer-padding-horizontal: 0; + --ifm-footer-link-color: var(--ifm-color-content); + + /* Announcement Bar */ + --docusaurus-announcement-bar-height: auto !important; + + /* Tables */ + --ifm-table-border-color: theme(colors.medusa.border.base); + --ifm-table-head-background: var(--ifm-background-surface-color); + --ifm-table-head-color: var(--ifm-color-primary); + --ifm-table-head-font-weight: theme(fontSize.medium-plus[1].fontWeight); + --ifm-table-stripe-background: var(--ifm-background-surface-color) !important; +} + +html[data-theme="dark"] { + /* Colors */ + --ifm-background-color: theme(colors.medusa.bg.subtle.DEFAULT); + --ifm-background-surface-color: theme(colors.medusa.bg.base.DEFAULT); + + /* Sidebar */ + --ifm-menu-color-background-hover: theme(colors.medusa.bg.subtle.hover); + --ifm-menu-color-background-active: theme(colors.medusa.bg.subtle.pressed); + + /* Navbar */ + --ifm-navbar-shadow: none; +} + +@media screen and (min-width: 1441px) { + :root { + /** Table of Content **/ + --ifm-toc-width: calc(2 / 12 * 100%); + } +} + +@media screen and (max-width: 1440px) { + :root { + /** Table of Content **/ + --ifm-toc-width: calc(3 / 12 * 100%); + } +} + +@media (min-width: 997px) { + :root { + --docusaurus-announcement-bar-height: 30px; + } +} + +.alert { + --ifm-code-background: theme(colors.medusa.tag.neutral.bg.DEFAULT) !important; +} \ No newline at end of file diff --git a/www/apps/docs/src/css/components/sidebar.css b/www/apps/docs/src/css/components/sidebar.css new file mode 100644 index 0000000..2d86f29 --- /dev/null +++ b/www/apps/docs/src/css/components/sidebar.css @@ -0,0 +1,156 @@ +.theme-doc-sidebar-container { + --animate-duration: 0.2s; +} + +.sidebar-desktop nav { + --ifm-scrollbar-track-background-color: transparent !important; + --ifm-scrollbar-thumb-background-color: transparent !important; + --ifm-scrollbar-thumb-hover-background-color: transparent !important; +} + +.menu__list-item:not(:first-child):not(.sidebar-title) { + margin-top: 0 !important; +} + +.menu__list-item .menu__list:not(.theme-doc-sidebar-menu) [class*=theme-doc-sidebar-item-], +.menu__list-item .menu__list:not(.theme-doc-sidebar-menu) [class*=theme-doc-sidebar-item-] .menu__link--active { + @apply relative; +} + +.menu__list-item .menu__list:not(.theme-doc-sidebar-menu) [class*=theme-doc-sidebar-item-]:not(.theme-doc-sidebar-item-link-category)::before, +.menu__list-item .menu__list:not(.theme-doc-sidebar-menu) .theme-doc-sidebar-item-category .menu__list-item-collapsible .menu__link--active::before, +.menu__list-item .menu__list:not(.theme-doc-sidebar-menu) > .theme-doc-sidebar-item-link > .menu__link--active::before, +.menu__list-item .menu__list:not(.theme-doc-sidebar-menu) .theme-doc-sidebar-item-category > .menu__list-item-collapsible::before { + @apply content-[''] h-full w-[1px] absolute left-0.5 top-0 z-[1]; +} + +.menu__list-item .menu__list:not(.theme-doc-sidebar-menu) [class*=theme-doc-sidebar-item-] .menu__link--active::before { + @apply !h-[20px]; +} + +.theme-doc-sidebar-item-category-level-1 > .menu__list > .menu__list-item:first-child::before, +.menu__list-item .menu__list:not(.theme-doc-sidebar-menu) .theme-doc-sidebar-item-category:first-child .menu__list-item-collapsible::before, +.theme-doc-sidebar-item-category-level-1 > .menu__list > .menu__list-item:last-child::before { + @apply !h-[28px]; +} + +.menu__list-item .menu__list:not(.theme-doc-sidebar-menu) .theme-doc-sidebar-item-link:first-child::before, +.menu__list-item .menu__list:not(.theme-doc-sidebar-menu) .theme-doc-sidebar-item-category:first-child .menu__list-item-collapsible::before { + @apply !bottom-0 !top-[unset]; +} + +.menu__list-item .menu__list:not(.theme-doc-sidebar-menu) .theme-doc-sidebar-item-category:first-child .menu__list-item-collapsible { + @apply !pb-[6px]; +} + +.menu__list-item .menu__list:not(.theme-doc-sidebar-menu) .theme-doc-sidebar-item-category:first-child .menu__list-item-collapsible .menu__link { + @apply !pb-0; +} + +.menu__list-item .menu__list:not(.theme-doc-sidebar-menu) [class*=theme-doc-sidebar-item-]::before, +.menu__list-item .menu__list:not(.theme-doc-sidebar-menu) .theme-doc-sidebar-item-category:first-child .menu__list-item-collapsible::before { + @apply bg-medusa-border-base; +} + +.theme-doc-sidebar-item-category-level-2 > .menu__list-item-collapsible .menu__link--active::before, +.menu__list:not(.theme-doc-sidebar-menu) > .theme-doc-sidebar-item-link.theme-doc-sidebar-item-link-level-2 > .menu__link--active::before { + @apply bg-medusa-fg-interactive !z-[2] !top-[6px]; +} + +.theme-doc-sidebar-item-category-level-2:only-child > .menu__list-item-collapsible .menu__link--active::before, +.menu__list:not(.theme-doc-sidebar-menu) > .theme-doc-sidebar-item-link.theme-doc-sidebar-item-link-level-2:only-child > .menu__link--active::before, +.menu__list:not(.theme-doc-sidebar-menu) > .theme-doc-sidebar-item-link.theme-doc-sidebar-item-link-level-2:first-child > .menu__link--active::before { + @apply !top-0.5; +} + +.theme-doc-sidebar-item-link-level-1:not(.sidebar-title):not(.homepage-sidebar-item):not(.sidebar-back-link) { + @apply mb-1; +} + +.theme-doc-sidebar-item-link-level-1:not(.sidebar-title):not(.homepage-sidebar-item):not(.sidebar-back-link) .menu__link { + @apply !pl-0; +} + +.theme-doc-sidebar-item-category-level-1.sidebar-group-headline { + @apply mb-1; +} + +[class*="level-2"]:is([class*="theme-doc-sidebar-item"]) .menu__link, +[class*="level-2"]:is([class*="theme-doc-sidebar-item"]).sidebar-group-divider, +[class*="level-3"]:is([class*="theme-doc-sidebar-item"]) .menu__link, +[class*="level-3"]:is([class*="theme-doc-sidebar-item"]).sidebar-group-divider, +[class*="level-4"]:is([class*="theme-doc-sidebar-item"]) .menu__link, +[class*="level-4"]:is([class*="theme-doc-sidebar-item"]).sidebar-group-divider { + @apply py-[6px]; +} + +[class*="level-2"]:is([class*="theme-doc-sidebar-item"]) .menu__link, +[class*="level-2"]:is([class*="theme-doc-sidebar-item"]).sidebar-group-divider { + @apply pl-2; +} + +[class*="level-3"]:is([class*="theme-doc-sidebar-item"]) .menu__link, +[class*="level-3"]:is([class*="theme-doc-sidebar-item"]).sidebar-group-divider { + @apply pl-3; +} + +[class*="level-4"]:is([class*="theme-doc-sidebar-item"]) .menu__link, +[class*="level-4"]:is([class*="theme-doc-sidebar-item"]).sidebar-group-divider { + @apply pl-4; +} + +.homepage-sidebar-item:is([class*="level-1"]):is([class*="theme-doc-sidebar-item"]) > .menu__link, +.homepage-sidebar-item:is([class*="level-1"]):is([class*="theme-doc-sidebar-item"]) > .menu__list-item-collapsible > .menu__link { + @apply !pl-0.5; +} + +.menu__list-item-collapsible { + @apply !rounded; +} + +.menu__list-item-collapsible--active { + @apply !bg-transparent; +} + +.menu__list-item-collapsible .menu__link--sublist:hover { + @apply !bg-medusa-bg-base-hover dark:!bg-medusa-bg-subtle-hover; +} + +.menu__list:not(.theme-doc-sidebar-menu) > .theme-doc-sidebar-item-link:last-child > .menu__link--active::before { + @apply !top-0.25; +} + +.menu__link--sublist-caret:after { + @apply content-none; +} + +.menu__link { + @apply cursor-pointer !rounded text-compact-small-plus; +} + +.theme-doc-sidebar-item-category-level-1 > .menu__list { + @apply mb-0.25; +} + +.menu__list:not(.theme-doc-sidebar-menu), +.theme-doc-sidebar-item-category-level-1 > .menu__list { + @apply !pl-0; +} + +.menu__list .menu__list { + @apply !mt-0; +} + +/** General sidebar styles **/ +.theme-doc-sidebar-container { + @apply z-[398] border-0 border-r border-solid border-medusa-border-base; +} + +/** Mobile Sidebar **/ +.navbar-sidebar__back { + @apply bg-transparent w-fit top-[unset] pl-0 ml-0 mb-1 text-compact-small-plus; +} + +.theme-doc-sidebar-item-link { + @apply flex items-center; +} \ No newline at end of file diff --git a/www/apps/docs/src/css/components/toc.css b/www/apps/docs/src/css/components/toc.css new file mode 100644 index 0000000..16855cf --- /dev/null +++ b/www/apps/docs/src/css/components/toc.css @@ -0,0 +1,60 @@ +.theme-doc-toc-desktop { + @apply pt-3; +} + +.theme-doc-toc-desktop .table-of-contents { + @apply !border-l-0 !p-0 text-[12px] relative overflow-y-hidden; + @apply before:bg-toc dark:before:bg-toc-dark; + @apply before:bg-no-repeat before:bg-[length:14px_10px] before:bg-[center_left]; + @apply before:pl-[22px] before:content-['On_this_page'] before:pb-0 text-compact-small-plus; + @apply after:content-[''] after:absolute after:left-0 after:top-2.5; + @apply after:h-full after:w-[1px] after:bg-medusa-border-base; +} + +.theme-doc-toc-desktop .table-of-contents .table-of-contents__link { + @apply pl-[11px]; +} + +.theme-doc-toc-desktop .table-of-contents > li { + @apply first:mt-1 [&:not(:first-child)]:mt-0 last:mb-0 [&:not(:last-child)]:mb-0.25; +} + +.theme-doc-toc-desktop .table-of-contents li a + ul { + @apply mt-0.25; +} + +.theme-doc-toc-desktop .table-of-contents__link { + @apply relative text-compact-x-small-plus; + @apply hover:text-medusa-fg-base; +} + +.theme-doc-toc-desktop .table-of-contents__link:hover code { + @apply text-medusa-fg-base; +} + +.theme-doc-toc-desktop .table-of-contents__link--active { + @apply text-medusa-fg-base; + @apply after:content-[''] after:absolute after:left-0 after:top-0; + @apply after:h-full after:w-[1px] after:bg-medusa-fg-base; + @apply z-[1]; +} + +.theme-doc-toc-desktop .table-of-contents__link--active code { + @apply text-medusa-fg-base; +} + +.theme-doc-toc-desktop .table-of-contents li { + @apply mx-0; +} + +.theme-doc-toc-desktop .table-of-contents ul li { + @apply mt-0; +} + +.table-of-contents ul { + @apply pl-0; +} + +.table-of-contents ul .table-of-contents__link { + @apply !pl-[27px]; +} \ No newline at end of file diff --git a/www/apps/docs/src/css/components/tooltip.css b/www/apps/docs/src/css/components/tooltip.css new file mode 100644 index 0000000..0a7b180 --- /dev/null +++ b/www/apps/docs/src/css/components/tooltip.css @@ -0,0 +1,10 @@ +.react-tooltip { + @apply !border !border-solid !border-medusa-border-base; + @apply !rounded !text-compact-x-small-plus !shadow-tooltip dark:!shadow-tooltip-dark; + @apply !py-0.4 !px-1 lg:block hidden; +} + +.react-tooltip-arrow { + @apply hidden; +} + diff --git a/www/apps/docs/src/css/custom.css b/www/apps/docs/src/css/custom.css new file mode 100644 index 0000000..b24507f --- /dev/null +++ b/www/apps/docs/src/css/custom.css @@ -0,0 +1,149 @@ +@tailwind base; +@tailwind components; +@tailwind utilities; + +@layer base { + body { + @apply !overflow-x-hidden; + } + body[data-modal="opened"] { + @apply !overflow-hidden; + } +} + +@layer components { + .sidebar-title { + @apply !m-0 !py-1 !px-0; + @apply lg:first:top-0 lg:[&:not(:first-child)]:top-[20px]; + } + + .sidebar-title .menu__link { + @apply !px-0; + } + + .sidebar-title .menu__link, + .sidebar-title span { + @apply !text-compact-medium-plus text-medusa-fg-base; + } + + .sidebar-title .menu__link--active, + .sidebar-title .menu__link:hover { + @apply !bg-transparent; + } + + .sidebar-group-headline { + @apply mt-1 py-[6px] px-0; + } + + .sidebar-group-headline:not(.theme-doc-sidebar-item-category-level-1) { + @apply mb-[6px]; + } + + .sidebar-group-headline > .menu__link { + @apply text-medusa-fg-base; + } + + .sidebar-group-headline > .menu__list-item-collapsible > .menu__link { + @apply text-medusa-fg-base !p-0; + } + + .sidebar-group-headline > .menu__list-item-collapsible > .menu__link:not([href]) { + @apply cursor-default + } + + .sidebar-group-headline > .menu__list-item-collapsible > .menu__link:hover, + .sidebar-group-headline .menu__list-item-collapsible:hover { + @apply !bg-transparent; + } + + .sidebar-group-headline > .menu__link, + .sidebar-group-headline > .menu__list-item-collapsible > .menu__link { + @apply font-semibold; + } + + .sidebar-group-divider { + @apply pb-[6px] uppercase text-medusa-fg-muted text-compact-x-small-plus; + @apply first:pt-[6px] [&:not(:first-child)]:!pt-1; + } + + .sidebar-divider-line { + @apply h-[1px] w-full bg-medusa-border-base my-1 mx-0; + } + + .sidebar-back-link { + @apply cursor-pointer lg:top-0; + } + + .sidebar-back-link, + .sidebar-title { + @apply lg:sticky lg:bg-medusa-bg-base dark:lg:bg-medusa-bg-subtle lg:z-[100]; + } + + .sidebar-back-link .menu__link { + @apply !p-0 hover:!bg-transparent hover:text-medusa-fg-base; + } + + .sidebar-back-link .menu__link, + .sidebar-back-link span { + @apply text-compact-small-plus; + } + + .sidebar-back-link .sidebar-item-icon { + @apply mr-0.5; + } + + .sidebar-soon-link { + @apply pointer-events-none [&_*]:text-medusa-fg-disabled; + } + + + .sidebar-badge-wrapper { + @apply flex justify-between items-center; + } + + .search-page-input { + @apply rounded border border-solid border-medusa-border-base; + @apply font-base text-medium p-0.75 w-full bg-medusa-bg-subtle; + @apply text-medusa-fg-base mb-1; + @apply transition-[border] duration-200 ease-ease; + @apply focus:border-medusa-border-base; + @apply focus:outline-none !shadow-none; + } + + .code-header { + @apply py-0.75 px-1 bg-medusa-code-bg-header text-medusa-code-text-subtle; + @apply flex justify-between items-center; + @apply rounded-tl rounded-tr rounded-br-none rounded-bl-none border-b-0; + @apply border border-solid border-medusa-code-border border-b-0; + } + + .no-scrollbar::-webkit-scrollbar { + @apply hidden; + } + + .navbar-action-icon-item { + @apply lg:bg-button-neutral lg:bg-medusa-button-neutral lg:dark:bg-button-neutral-dark; + @apply lg:hover:bg-medusa-button-neutral-hover lg:hover:bg-no-image lg:hover:no-underline; + @apply lg:active:bg-medusa-button-neutral-pressed lg:active:bg-no-image; + @apply lg:focus:bg-medusa-button-neutral-pressed lg:focus:bg-no-image; + @apply lg:lg:border lg:border-solid lg:border-medusa-border-base rounded; + @apply w-2 h-2 flex justify-center items-center cursor-pointer; + } + + .btn-clear { + @apply bg-transparent shadow-none border-0 outline-none cursor-pointer; + } +} + +@layer utilities { + .clip { + clip-path: inset(0); + } +} + +@import url('./_variables.css'); + +@import url('./_docusaurus.css'); +@import url('./components/sidebar.css'); +@import url('./components/toc.css'); +@import url('./components/tooltip.css'); \ No newline at end of file diff --git a/www/apps/docs/src/plugins/docusaurus-plugin-diagram2code-showcase/index.js b/www/apps/docs/src/plugins/docusaurus-plugin-diagram2code-showcase/index.js new file mode 100644 index 0000000..f2de7a0 --- /dev/null +++ b/www/apps/docs/src/plugins/docusaurus-plugin-diagram2code-showcase/index.js @@ -0,0 +1,118 @@ +import { exec } from "child_process" +import { readdir, readFile, writeFile } from "fs/promises" +import path from "path" + +export default async function docusaurusPluginDiagram2codeShowcase( + context, + { directoryPath, outputPath, debug = false } +) { + async function readIfExists(filePath) { + try { + return await readFile(filePath, "utf-8") + } catch (e) { + if (debug) { + console.error( + `[Diagram2Code Showcase Plugin] An error occurred while reading ${filePath}: ${e}` + ) + } + return null + } + } + + async function generateSpecs() { + let specs = {} + let diagramSpecDirectories = [] + + try { + // read files under the provided directory path + diagramSpecDirectories = ( + await readdir(directoryPath, { withFileTypes: true }) + ).filter((dirent) => dirent.isDirectory()) + } catch { + console.error( + `Directory ${directoryPath} doesn't exist. Skipping reading diagrams...` + ) + return + } + + await Promise.all( + diagramSpecDirectories.map(async (dirent) => { + const tempSpecs = {} + const specsPath = path.join(directoryPath, dirent.name) + + const specDirents = ( + await readdir(specsPath, { withFileTypes: true }) + ).filter((specDirent) => specDirent.isDirectory()) + await Promise.all( + specDirents.map(async (specDirent) => { + const specPath = path.join(specsPath, specDirent.name) + // read the diagram and code files + const diagram = await readIfExists( + path.join(specPath, "diagram.mermaid") + ) + const code = + (await readIfExists(path.join(specPath, "code.ts"))) || + (await readIfExists(path.join(specPath, "code.tsx"))) || + (await readIfExists(path.join(specPath, "code.js"))) + + if (!diagram) { + return + } + + tempSpecs[specDirent.name] = { + diagram, + code, + } + }) + ) + + if (Object.keys(tempSpecs).length) { + specs[dirent.name] = tempSpecs + } + }) + ) + + // order steps alphabetically + specs = Object.keys(specs) + .sort() + .reduce((accumulator, key) => { + accumulator[key] = specs[key] + + return accumulator + }, {}) + + // store specs in a JavaScript object that can be consumed + const specOutputFilePath = path.join(outputPath, "specs.ts") + await writeFile( + specOutputFilePath, + `export const specs = ${JSON.stringify(specs, null, "\t")}` + ) + + // execute eslint + exec(`eslint ${specOutputFilePath} --fix`) + + return specOutputFilePath + } + + return { + name: "docusaurus-plugin-diagram2code-showcase", + async loadContent() { + await generateSpecs() + }, + extendCli(cli) { + cli + .command("diagram2code:generate") + .description( + "Generate the spec file used to create diagram-to-code showcase" + ) + .action(async () => { + const specFile = await generateSpecs() + // eslint-disable-next-line no-console + console.log(`Generated diagram2code spec file at ${specFile}`) + }) + }, + getPathsToWatch() { + return [directoryPath] + }, + } +} diff --git a/www/apps/docs/src/providers/DocsProviders/index.tsx b/www/apps/docs/src/providers/DocsProviders/index.tsx new file mode 100644 index 0000000..982e3a3 --- /dev/null +++ b/www/apps/docs/src/providers/DocsProviders/index.tsx @@ -0,0 +1,38 @@ +import { + AnalyticsProvider, + ColorModeProvider, + ModalProvider, + NotificationProvider, +} from "docs-ui" +import React from "react" +import { useThemeConfig } from "@docusaurus/theme-common" +import { ThemeConfig } from "@medusajs/docs" +import SearchProvider from "../Search" +import SkipToContent from "@theme/SkipToContent" + +type DocsProvidersProps = { + children?: React.ReactNode +} + +const DocsProviders = ({ children }: DocsProvidersProps) => { + const { + analytics: { apiKey }, + } = useThemeConfig() as ThemeConfig + + return ( + + + + + + + {children} + + + + + + ) +} + +export default DocsProviders diff --git a/www/apps/docs/src/providers/LearningPath/index.tsx b/www/apps/docs/src/providers/LearningPath/index.tsx new file mode 100644 index 0000000..c2bb2b5 --- /dev/null +++ b/www/apps/docs/src/providers/LearningPath/index.tsx @@ -0,0 +1,256 @@ +import useIsBrowser from "@docusaurus/useIsBrowser" +import { getLearningPath } from "@site/src/utils/learning-paths" +import React, { createContext, useContext, useEffect, useState } from "react" +import { useHistory } from "@docusaurus/router" +import { LearningPathFinishType } from "@site/src/components/LearningPath/Finish" +import { useAnalytics } from "docs-ui" + +export type LearningPathType = { + name: string + label: string + description?: string + steps: LearningPathStepType[] + finish?: LearningPathFinishType + notificationId?: string +} + +export type LearningPathStepType = { + title?: string + description?: string + descriptionJSX?: JSX.Element + path?: string +} + +export type LearningPathContextType = { + path?: LearningPathType + setPath: (value: LearningPathType) => void + currentStep: number + setCurrentStep: (value: number) => void + startPath: (path: LearningPathType) => void + updatePath: (data: Pick) => void + endPath: () => void + nextStep: () => void + hasNextStep: () => boolean + previousStep: () => void + hasPreviousStep: () => boolean + goToStep: (stepIndex: number) => void + isCurrentPath: () => boolean + goToCurrentPath: () => void +} + +type LearningPathProviderProps = { + children?: React.ReactNode +} + +const LearningPathContext = createContext(null) + +const LearningPathProvider: React.FC = ({ + children, +}) => { + const [path, setPath] = useState(null) + const [currentStep, setCurrentStep] = useState(-1) + const isBrowser = useIsBrowser() + const history = useHistory() + const { track } = useAnalytics() + + const startPath = (path: LearningPathType) => { + setPath(path) + setCurrentStep(-1) + if (isBrowser) { + localStorage.setItem( + "learning-path", + JSON.stringify({ + pathName: path.name, + currentStep: -1, + }) + ) + } + + track(`learning_path_${path.name}`, { + url: history.location.pathname, + state: `start`, + }) + } + + useEffect(() => { + if (path && currentStep === -1) { + nextStep() + } + }, [path]) + + const endPath = () => { + const didFinish = currentStep === path.steps.length - 1 + const reachedIndex = currentStep === -1 ? 0 : currentStep + track(`learning_path_${path.name}`, { + url: history.location.pathname, + state: !didFinish ? `closed` : `end`, + reachedStep: + path.steps[reachedIndex]?.title || + path.steps[reachedIndex]?.description || + path.steps[reachedIndex]?.descriptionJSX || + reachedIndex, + }) + setPath(null) + setCurrentStep(-1) + if (isBrowser) { + localStorage.removeItem("learning-path") + } + } + + const hasNextStep = () => currentStep !== path?.steps.length - 1 + + const nextStep = () => { + if (!path || !hasNextStep()) { + return + } + const nextStepIndex = currentStep + 1 + setCurrentStep(nextStepIndex) + const newPath = path.steps[nextStepIndex].path + if (isBrowser) { + localStorage.setItem( + "learning-path", + JSON.stringify({ + pathName: path.name, + currentStep: nextStepIndex, + }) + ) + } + if (history.location.pathname !== newPath) { + history.push(newPath) + } + } + + const hasPreviousStep = () => currentStep > 0 + + const previousStep = () => { + if (!path || !hasPreviousStep()) { + return + } + + const previousStepIndex = currentStep - 1 + setCurrentStep(previousStepIndex) + const newPath = path.steps[previousStepIndex].path + if (isBrowser) { + localStorage.setItem( + "learning-path", + JSON.stringify({ + pathName: path.name, + currentStep: previousStepIndex, + }) + ) + } + if (history.location.pathname !== newPath) { + history.push(newPath) + } + } + + const goToStep = (stepIndex: number) => { + if (!path || stepIndex >= path.steps.length) { + return + } + + setCurrentStep(stepIndex) + const newPath = path.steps[stepIndex].path + if (isBrowser) { + localStorage.setItem( + "learning-path", + JSON.stringify({ + pathName: path.name, + currentStep: stepIndex, + }) + ) + } + if (history.location.pathname !== newPath) { + history.push(newPath) + } + } + + const isCurrentPath = () => { + if (!path || currentStep === -1) { + return false + } + + return history.location.pathname === path.steps[currentStep].path + } + + const goToCurrentPath = () => { + if (!path || currentStep === -1) { + return + } + + history.push(path.steps[currentStep].path) + } + + const updatePath = (data: Pick) => { + setPath({ + ...path, + ...data, + }) + } + + const initPath = () => { + if (isBrowser) { + // give query parameters higher precedence over local storage + const queryPathName = new URLSearchParams(history.location.search).get( + "path" + ) + const queryPath = getLearningPath(queryPathName) + if (queryPath) { + startPath(queryPath) + } else { + const storedPath = localStorage.getItem("learning-path") + if (storedPath) { + const storedPathParsed = JSON.parse(storedPath) + const currentPath = getLearningPath(storedPathParsed?.pathName) + if (currentPath) { + setPath(currentPath) + setCurrentStep(storedPathParsed?.currentStep || 0) + } + } + } + } + } + + useEffect(() => { + if (isBrowser && !path) { + initPath() + } + }, [isBrowser]) + + return ( + + {children} + + ) +} + +export default LearningPathProvider + +export const useLearningPath = () => { + const context = useContext(LearningPathContext) + + if (!context) { + throw new Error( + "useLearningPath must be used within a LearningPathProvider" + ) + } + + return context +} diff --git a/www/apps/docs/src/providers/Search/index.tsx b/www/apps/docs/src/providers/Search/index.tsx new file mode 100644 index 0000000..f36fd81 --- /dev/null +++ b/www/apps/docs/src/providers/Search/index.tsx @@ -0,0 +1,73 @@ +import React, { useEffect, useState } from "react" +import { SearchProvider as UiSearchProvider, checkArraySameElms } from "docs-ui" +import { ThemeConfig } from "@medusajs/docs" +import { useThemeConfig } from "@docusaurus/theme-common" +import { useLocalPathname } from "@docusaurus/theme-common/internal" + +type SearchProviderProps = { + children: React.ReactNode +} + +const SearchProvider = ({ children }: SearchProviderProps) => { + const [defaultFilters, setDefaultFilters] = useState([]) + const { algoliaConfig: algolia } = useThemeConfig() as ThemeConfig + const currentPath = useLocalPathname() + + useEffect(() => { + let resultFilters = [] + algolia.defaultFiltersByPath.some((filtersByPath) => { + if (currentPath.startsWith(filtersByPath.path)) { + resultFilters = filtersByPath.filters + } + }) + if (!resultFilters.length && algolia.defaultFilters) { + resultFilters = algolia.defaultFilters + } + if (!checkArraySameElms(defaultFilters, resultFilters)) { + setDefaultFilters(resultFilters) + } + }, [currentPath]) + + return ( + + {children} + + ) +} + +export default SearchProvider diff --git a/www/apps/docs/src/providers/Sidebar/index.tsx b/www/apps/docs/src/providers/Sidebar/index.tsx new file mode 100644 index 0000000..b3e2e7d --- /dev/null +++ b/www/apps/docs/src/providers/Sidebar/index.tsx @@ -0,0 +1,102 @@ +import React, { + createContext, + useCallback, + useContext, + useEffect, + useState, +} from "react" +import { prefersReducedMotion } from "@docusaurus/theme-common" + +type SidebarContextType = { + hasSidebar: boolean + hiddenSidebar: boolean + setHiddenSidebar: (value: boolean) => void + hiddenSidebarContainer: boolean + setHiddenSidebarContainer: (value: boolean) => void + floatingSidebar: boolean + setFloatingSidebar: (value: boolean) => void + onCollapse: () => void +} + +const SidebarContext = createContext(null) + +type SidebarProviderProps = { + sidebarName?: string + children?: React.ReactNode +} + +const SidebarProvider: React.FC = ({ + sidebarName, + children, +}) => { + const [hiddenSidebar, setHiddenSidebar] = useState(false) + const [hiddenSidebarContainer, setHiddenSidebarContainer] = useState(false) + const [floatingSidebar, setFloatingSidebar] = useState(false) + + const toggleSidebar = useCallback(() => { + if (hiddenSidebar) { + setHiddenSidebar(false) + } + // onTransitionEnd won't fire when sidebar animation is disabled + // fixes https://github.com/facebook/docusaurus/issues/8918 + if (!hiddenSidebar && prefersReducedMotion()) { + setHiddenSidebar(true) + } + setHiddenSidebarContainer((value) => !value) + }, [setHiddenSidebarContainer, hiddenSidebar]) + + useEffect(() => { + function isEditingContent(event: KeyboardEvent) { + const element = event.target as HTMLElement + const tagName = element.tagName + return ( + element.isContentEditable || + tagName === "INPUT" || + tagName === "SELECT" || + tagName === "TEXTAREA" + ) + } + + function sidebarShortcut(e: KeyboardEvent) { + if ( + (e.metaKey || e.ctrlKey) && + e.key.toLowerCase() === "i" && + !isEditingContent(e) + ) { + e.preventDefault() + toggleSidebar() + } + } + + window.addEventListener("keydown", sidebarShortcut) + + return () => { + window.removeEventListener("keydown", sidebarShortcut) + } + }) + + return ( + + {children} + + ) +} + +export default SidebarProvider + +export const useSidebar = () => { + const context = useContext(SidebarContext) + + return context +} diff --git a/www/apps/docs/src/theme/Admonition/Icon/Danger.tsx b/www/apps/docs/src/theme/Admonition/Icon/Danger.tsx new file mode 100644 index 0000000..5520694 --- /dev/null +++ b/www/apps/docs/src/theme/Admonition/Icon/Danger.tsx @@ -0,0 +1,19 @@ +import React from "react" +import type { IconProps } from "@medusajs/icons/dist/types" +import { ExclamationCircleSolid } from "@medusajs/icons" +import clsx from "clsx" + +export default function AdmonitionIconDanger({ + className, + ...props +}: IconProps): JSX.Element { + return ( + + ) +} diff --git a/www/apps/docs/src/theme/Admonition/Icon/Info.tsx b/www/apps/docs/src/theme/Admonition/Icon/Info.tsx new file mode 100644 index 0000000..3616e96 --- /dev/null +++ b/www/apps/docs/src/theme/Admonition/Icon/Info.tsx @@ -0,0 +1,7 @@ +import React from "react" +import AdmonitionIconNote from "./Note" +import type { IconProps } from "@medusajs/icons/dist/types" + +export default function AdmonitionIconInfo(props: IconProps): JSX.Element { + return +} diff --git a/www/apps/docs/src/theme/Admonition/Icon/Note.tsx b/www/apps/docs/src/theme/Admonition/Icon/Note.tsx new file mode 100644 index 0000000..7075c76 --- /dev/null +++ b/www/apps/docs/src/theme/Admonition/Icon/Note.tsx @@ -0,0 +1,19 @@ +import React from "react" +import { InformationCircleSolid } from "@medusajs/icons" +import type { IconProps } from "@medusajs/icons/dist/types" +import clsx from "clsx" + +export default function AdmonitionIconNote({ + className, + ...props +}: IconProps): JSX.Element { + return ( + + ) +} diff --git a/www/apps/docs/src/theme/Admonition/Icon/Tip.tsx b/www/apps/docs/src/theme/Admonition/Icon/Tip.tsx new file mode 100644 index 0000000..62e9e96 --- /dev/null +++ b/www/apps/docs/src/theme/Admonition/Icon/Tip.tsx @@ -0,0 +1,7 @@ +import type { IconProps } from "@medusajs/icons/dist/types" +import React from "react" +import AdmonitionIconNote from "./Note" + +export default function AdmonitionIconTip(props: IconProps): JSX.Element { + return +} diff --git a/www/apps/docs/src/theme/Admonition/Icon/Warning.tsx b/www/apps/docs/src/theme/Admonition/Icon/Warning.tsx new file mode 100644 index 0000000..68596b7 --- /dev/null +++ b/www/apps/docs/src/theme/Admonition/Icon/Warning.tsx @@ -0,0 +1,7 @@ +import React from "react" +import AdmonitionIconDanger from "./Danger" +import type { IconProps } from "@medusajs/icons/dist/types" + +export default function AdmonitionIconCaution(props: IconProps): JSX.Element { + return +} diff --git a/www/apps/docs/src/theme/Admonition/Layout/index.tsx b/www/apps/docs/src/theme/Admonition/Layout/index.tsx new file mode 100644 index 0000000..2a23771 --- /dev/null +++ b/www/apps/docs/src/theme/Admonition/Layout/index.tsx @@ -0,0 +1,86 @@ +import React, { type ReactNode } from "react" +import clsx from "clsx" + +import type { Props } from "@theme/Admonition/Layout" + +function AdmonitionContainer({ + className, + children, + type, +}: Pick & { children: ReactNode }) { + return ( +
+
{children}
+
+ ) +} + +function AdmonitionHeading({ icon }: Pick) { + return {icon} +} + +function AdmonitionContent({ + children, + title, + type, +}: Pick) { + return children ? ( +
*:last-child]:mb-0", + "[&>p>code]:px-0.5 [&>p>code]:text-code-label" + )} + > + {title && ( + + {transformAdmonitionTitle(title)} + + )} + {children} +
+ ) : null +} + +export default function AdmonitionLayout(props: Props): JSX.Element { + const { type, icon, children, className, title } = props + return ( + + + + {children} + + + ) +} + +function transformAdmonitionTitle(title: T): T | string { + if (typeof title !== "string") { + return title + } + switch (title) { + case "note": + case "tip": + case "danger": + case "warning": + case "info": + case "caution": + return title.charAt(0).toUpperCase + title.substring(1) + default: + return title + } +} diff --git a/www/apps/docs/src/theme/Admonition/Type/Caution.tsx b/www/apps/docs/src/theme/Admonition/Type/Caution.tsx new file mode 100644 index 0000000..0addec8 --- /dev/null +++ b/www/apps/docs/src/theme/Admonition/Type/Caution.tsx @@ -0,0 +1,34 @@ +import React from "react" +import clsx from "clsx" +import Translate from "@docusaurus/Translate" +import type { Props } from "@theme/Admonition/Type/Caution" +import AdmonitionLayout from "@theme/Admonition/Layout" +import IconWarning from "@theme/Admonition/Icon/Warning" + +const infimaClassName = "alert alert--warning" + +const defaultProps = { + icon: , + title: ( + + Caution + + ), +} + +// TODO remove before v4: Caution replaced by Warning +// see https://github.com/facebook/docusaurus/issues/7558 +export default function AdmonitionTypeCaution(props: Props): JSX.Element { + return ( + + {props.children} + + ) +} diff --git a/www/apps/docs/src/theme/Admonition/Type/Danger.tsx b/www/apps/docs/src/theme/Admonition/Type/Danger.tsx new file mode 100644 index 0000000..7a93418 --- /dev/null +++ b/www/apps/docs/src/theme/Admonition/Type/Danger.tsx @@ -0,0 +1,32 @@ +import React from "react" +import clsx from "clsx" +import Translate from "@docusaurus/Translate" +import type { Props } from "@theme/Admonition/Type/Danger" +import AdmonitionLayout from "@theme/Admonition/Layout" +import IconDanger from "@theme/Admonition/Icon/Danger" + +const infimaClassName = "alert alert--danger" + +const defaultProps = { + icon: , + title: ( + + Danger + + ), +} + +export default function AdmonitionTypeDanger(props: Props): JSX.Element { + return ( + + {props.children} + + ) +} diff --git a/www/apps/docs/src/theme/Admonition/Type/Info.tsx b/www/apps/docs/src/theme/Admonition/Type/Info.tsx new file mode 100644 index 0000000..1823fc7 --- /dev/null +++ b/www/apps/docs/src/theme/Admonition/Type/Info.tsx @@ -0,0 +1,32 @@ +import React from "react" +import clsx from "clsx" +import Translate from "@docusaurus/Translate" +import type { Props } from "@theme/Admonition/Type/Info" +import AdmonitionLayout from "@theme/Admonition/Layout" +import IconInfo from "@theme/Admonition/Icon/Info" + +const infimaClassName = "alert alert--info" + +const defaultProps = { + icon: , + title: ( + + Info + + ), +} + +export default function AdmonitionTypeInfo(props: Props): JSX.Element { + return ( + + {props.children} + + ) +} diff --git a/www/apps/docs/src/theme/Admonition/Type/Note.tsx b/www/apps/docs/src/theme/Admonition/Type/Note.tsx new file mode 100644 index 0000000..bca2b2f --- /dev/null +++ b/www/apps/docs/src/theme/Admonition/Type/Note.tsx @@ -0,0 +1,32 @@ +import React from "react" +import clsx from "clsx" +import Translate from "@docusaurus/Translate" +import type { Props } from "@theme/Admonition/Type/Note" +import AdmonitionLayout from "@theme/Admonition/Layout" +import IconNote from "@theme/Admonition/Icon/Note" + +const infimaClassName = "alert alert--secondary" + +const defaultProps = { + icon: , + title: ( + + Note + + ), +} + +export default function AdmonitionTypeNote(props: Props): JSX.Element { + return ( + + {props.children} + + ) +} diff --git a/www/apps/docs/src/theme/Admonition/Type/Tip.tsx b/www/apps/docs/src/theme/Admonition/Type/Tip.tsx new file mode 100644 index 0000000..66fad7c --- /dev/null +++ b/www/apps/docs/src/theme/Admonition/Type/Tip.tsx @@ -0,0 +1,32 @@ +import React from "react" +import clsx from "clsx" +import Translate from "@docusaurus/Translate" +import type { Props } from "@theme/Admonition/Type/Tip" +import AdmonitionLayout from "@theme/Admonition/Layout" +import IconTip from "@theme/Admonition/Icon/Tip" + +const infimaClassName = "alert alert--success" + +const defaultProps = { + icon: , + title: ( + + Tip + + ), +} + +export default function AdmonitionTypeTip(props: Props): JSX.Element { + return ( + + {props.children} + + ) +} diff --git a/www/apps/docs/src/theme/Admonition/Type/Warning.tsx b/www/apps/docs/src/theme/Admonition/Type/Warning.tsx new file mode 100644 index 0000000..d5445b0 --- /dev/null +++ b/www/apps/docs/src/theme/Admonition/Type/Warning.tsx @@ -0,0 +1,32 @@ +import React from "react" +import clsx from "clsx" +import Translate from "@docusaurus/Translate" +import type { Props } from "@theme/Admonition/Type/Warning" +import AdmonitionLayout from "@theme/Admonition/Layout" +import IconWarning from "@theme/Admonition/Icon/Warning" + +const infimaClassName = "alert alert--warning" + +const defaultProps = { + icon: , + title: ( + + Warning + + ), +} + +export default function AdmonitionTypeWarning(props: Props): JSX.Element { + return ( + + {props.children} + + ) +} diff --git a/www/apps/docs/src/theme/AnnouncementBar/CloseButton/index.tsx b/www/apps/docs/src/theme/AnnouncementBar/CloseButton/index.tsx new file mode 100644 index 0000000..827a7e0 --- /dev/null +++ b/www/apps/docs/src/theme/AnnouncementBar/CloseButton/index.tsx @@ -0,0 +1,33 @@ +import React from "react" +import clsx from "clsx" +import { translate } from "@docusaurus/Translate" +import IconClose from "@theme/Icon/Close" +import type { Props } from "@theme/AnnouncementBar/CloseButton" + +export default function AnnouncementBarCloseButton( + props: Props +): JSX.Element | null { + return ( + + ) +} diff --git a/www/apps/docs/src/theme/AnnouncementBar/Content/index.tsx b/www/apps/docs/src/theme/AnnouncementBar/Content/index.tsx new file mode 100644 index 0000000..698030f --- /dev/null +++ b/www/apps/docs/src/theme/AnnouncementBar/Content/index.tsx @@ -0,0 +1,29 @@ +import React from "react" +import clsx from "clsx" +import { useThemeConfig } from "@docusaurus/theme-common" +import type { Props } from "@theme/AnnouncementBar/Content" + +export default function AnnouncementBarContent( + props: Props +): JSX.Element | null { + const { announcementBar } = useThemeConfig() + const { content } = announcementBar! + return ( +
+
+ Read more +
+ ) +} diff --git a/www/apps/docs/src/theme/AnnouncementBar/index.tsx b/www/apps/docs/src/theme/AnnouncementBar/index.tsx new file mode 100644 index 0000000..fbc4334 --- /dev/null +++ b/www/apps/docs/src/theme/AnnouncementBar/index.tsx @@ -0,0 +1,52 @@ +import React from "react" +import { useThemeConfig } from "@docusaurus/theme-common" +import { useAnnouncementBar } from "@docusaurus/theme-common/internal" +import AnnouncementBarCloseButton from "@theme/AnnouncementBar/CloseButton" +import AnnouncementBarContent from "@theme/AnnouncementBar/Content" + +import clsx from "clsx" +import { Bordered } from "docs-ui" +import { BellAlertSolid } from "@medusajs/icons" +import Link from "@docusaurus/Link" + +export default function AnnouncementBar(): JSX.Element | null { + const { announcementBar } = useThemeConfig() + const { isActive, close } = useAnnouncementBar() + if (!isActive) { + return null + } + const { isCloseable, id } = announcementBar! + return ( +
+ +
+ +
+
+ + {isCloseable && ( + + )} + +
+ ) +} diff --git a/www/apps/docs/src/theme/BackToTopButton/index.tsx b/www/apps/docs/src/theme/BackToTopButton/index.tsx new file mode 100644 index 0000000..97fca7c --- /dev/null +++ b/www/apps/docs/src/theme/BackToTopButton/index.tsx @@ -0,0 +1,33 @@ +import React from "react" +import clsx from "clsx" +import { translate } from "@docusaurus/Translate" +import { useBackToTopButton } from "@docusaurus/theme-common/internal" +import { Button, useNotifications } from "docs-ui" +import { ArrowUpMini } from "@medusajs/icons" + +export default function BackToTopButton(): JSX.Element { + const { shown, scrollToTop } = useBackToTopButton({ threshold: 300 }) + const { notifications } = useNotifications() + + return ( + + ) +} diff --git a/www/apps/docs/src/theme/CodeBlock/Content/String.tsx b/www/apps/docs/src/theme/CodeBlock/Content/String.tsx new file mode 100644 index 0000000..b22b3d0 --- /dev/null +++ b/www/apps/docs/src/theme/CodeBlock/Content/String.tsx @@ -0,0 +1,153 @@ +import React from "react" +import clsx from "clsx" +import { useThemeConfig, usePrismTheme } from "@docusaurus/theme-common" +import { + parseCodeBlockTitle, + parseLanguage, + parseLines, + containsLineNumbers, + useCodeWordWrap, +} from "@docusaurus/theme-common/internal" +import { Highlight, type Language } from "prism-react-renderer" +import Line from "@theme/CodeBlock/Line" +import Container from "@theme/CodeBlock/Container" +import type { Props } from "@theme/CodeBlock/Content/String" +import { Tooltip, CopyButton } from "docs-ui" +import useIsBrowser from "@docusaurus/useIsBrowser" +import { ThemeConfig } from "@medusajs/docs" +import { ExclamationCircleSolid, SquareTwoStackSolid } from "@medusajs/icons" +import Link from "@docusaurus/Link" + +// Prism languages are always lowercase +// We want to fail-safe and allow both "php" and "PHP" +// See https://github.com/facebook/docusaurus/issues/9012 +function normalizeLanguage(language: string | undefined): string | undefined { + return language?.toLowerCase() +} + +export default function CodeBlockString({ + children, + className: blockClassName = "", + metastring, + title: titleProp, + showLineNumbers: showLineNumbersProp, + language: languageProp, + noReport = false, + noCopy = false, +}: Props): JSX.Element { + const { + prism: { defaultLanguage, magicComments }, + reportCodeLinkPrefix = "", + } = useThemeConfig() as ThemeConfig + const language = normalizeLanguage( + languageProp ?? parseLanguage(blockClassName) ?? defaultLanguage + ) + + const prismTheme = usePrismTheme() + const wordWrap = useCodeWordWrap() + const isBrowser = useIsBrowser() + + // We still parse the metastring in case we want to support more syntax in the + // future. Note that MDX doesn't strip quotes when parsing metastring: + // "title=\"xyz\"" => title: "\"xyz\"" + const title = parseCodeBlockTitle(metastring) || titleProp + + const { lineClassNames, code } = parseLines(children, { + metastring, + language, + magicComments, + }) + const showLineNumbers = showLineNumbersProp ?? containsLineNumbers(metastring) + + return ( + + {title &&
{title}
} +
+ + {({ className, tokens, getLineProps, getTokenProps }) => ( + <> +
+                 1 &&
+                      "table p-1 code-block-numbering",
+                    title && "p-1",
+                    !title && tokens.length > 1 && "p-1",
+                    !title && tokens.length === 1 && "py-0.5 pr-0.5 pl-1"
+                  )}
+                >
+                  {tokens.map((line, i) => (
+                     1}
+                    />
+                  ))}
+                
+              
+
1 && "top-1" + )} + > + {!noReport && ( + + + + + + )} + {!noCopy && ( + + + + )} +
+ + )} +
+
+
+ ) +} diff --git a/www/apps/docs/src/theme/CodeBlock/index.tsx b/www/apps/docs/src/theme/CodeBlock/index.tsx new file mode 100644 index 0000000..8297831 --- /dev/null +++ b/www/apps/docs/src/theme/CodeBlock/index.tsx @@ -0,0 +1,101 @@ +import React, { isValidElement, type ReactNode } from "react" +import useIsBrowser from "@docusaurus/useIsBrowser" +import ElementContent from "@theme/CodeBlock/Content/Element" +import StringContent from "@theme/CodeBlock/Content/String" +import type { Props } from "@theme/CodeBlock" +import clsx from "clsx" +import { Badge, BadgeVariant } from "docs-ui" + +/** + * Best attempt to make the children a plain string so it is copyable. If there + * are react elements, we will not be able to copy the content, and it will + * return `children` as-is; otherwise, it concatenates the string children + * together. + */ +function maybeStringifyChildren(children: ReactNode): ReactNode { + if (React.Children.toArray(children).some((el) => isValidElement(el))) { + return children + } + // The children is now guaranteed to be one/more plain strings + return Array.isArray(children) ? children.join("") : (children as string) +} + +export default function CodeBlock({ + children: rawChildren, + noReport = false, + noCopy = false, + ...props +}: Props): JSX.Element { + // The Prism theme on SSR is always the default theme but the site theme can + // be in a different mode. React hydration doesn't update DOM styles that come + // from SSR. Hence force a re-render after mounting to apply the current + // relevant styles. + const isBrowser = useIsBrowser() + const children = maybeStringifyChildren(rawChildren) + const CodeBlockComp = + typeof children === "string" ? StringContent : ElementContent + + const metastringTitleRegex = /title="?([^"]*)"?/ + const metastringBadgeLabelRegex = /badgeLabel="?([^"]*)"?/ + const metastringBadgeColorRegex = /badgeColor="?([^"]*)"?/ + + let title = props.title + delete props.title + + function extractFromMetastring(regex: RegExp): string { + if (!props.metastring) { + return "" + } + + let value = "" + + const matched = props.metastring.match(regex) + if (matched?.length) { + value = matched[1].replace(/^"/, "").replace(/"$/, "") + props.metastring = props.metastring.replace(regex, "") + } + + return value + } + + if (!title) { + title = extractFromMetastring(metastringTitleRegex) + } + + const badge = { + label: extractFromMetastring(metastringBadgeLabelRegex), + color: extractFromMetastring(metastringBadgeColorRegex), + } + + return ( +
+ {(title || badge.label) && ( +
+ {title} + {badge.label && ( + + {badge.label} + + )} +
+ )} + + {children as string} + +
+ ) +} diff --git a/www/apps/docs/src/theme/Details/index.tsx b/www/apps/docs/src/theme/Details/index.tsx new file mode 100644 index 0000000..fe3cc50 --- /dev/null +++ b/www/apps/docs/src/theme/Details/index.tsx @@ -0,0 +1,26 @@ +import React from "react" +import { + Details as UiDetails, + type DetailsProps as UiDetailsProps, +} from "docs-ui" + +export type DetailsProps = { + summary: React.ReactNode + children?: React.ReactNode +} & UiDetailsProps + +export default function Details({ + summary, + children, + ...props +}: DetailsProps): JSX.Element { + return ( + + {children} + + ) +} diff --git a/www/apps/docs/src/theme/DocCard/index.tsx b/www/apps/docs/src/theme/DocCard/index.tsx new file mode 100644 index 0000000..4788a0f --- /dev/null +++ b/www/apps/docs/src/theme/DocCard/index.tsx @@ -0,0 +1,245 @@ +import React, { type ReactNode } from "react" +import clsx from "clsx" +import Link from "@docusaurus/Link" +import { + findFirstSidebarItemLink, + useDocById, +} from "@docusaurus/theme-common/internal" +import isInternalUrl from "@docusaurus/isInternalUrl" +import { translate } from "@docusaurus/Translate" +import { + ModifiedDocCard, + ModifiedDocCardItemCategory, + ModifiedDocCardItemLink, + ModifiedSidebarItem, +} from "@medusajs/docs" +import { Badge } from "docs-ui" +import Icons from "../Icon" +import BorderedIcon from "../../components/BorderedIcon" + +type ModifiedProps = { + item: ModifiedDocCard +} + +function CardContainer({ + href, + children, + className, +}: { + href: string + children: ReactNode + className?: string +}): JSX.Element { + return ( +
+ + {children} + +
+ ) +} + +function CardLayout({ + href, + icon, + title, + description, + html, + containerClassName, + isSoon = false, + badge, +}: ModifiedDocCard): JSX.Element { + const isHighlighted = containerClassName?.includes("card-highlighted") + return ( + +
+ {icon} + {isSoon && Guide coming soon} + {badge && } +
+
*:last-child]:mb-0")}> + + {title} + + {description && ( +

+ {description} +

+ )} + {html && ( +

+ )} +
+
+ ) +} + +function getCardIcon(item: ModifiedSidebarItem): JSX.Element { + if (item.customProps?.themedImage) { + return ( + + ) + } else if (item.customProps?.image) { + return ( + + ) + } else if (item.customProps?.icon) { + return ( + + ) + } else if ( + item.customProps?.iconName && + Object.hasOwn(Icons, item.customProps?.iconName) + ) { + return ( + + ) + } else { + return ( +
+ {isInternalUrl( + "href" in item ? item.href : "value" in item ? item.value : "#" + ) + ? "📄️" + : "🔗"} +
+ ) + } +} + +function CardCategory({ + item, +}: { + item: ModifiedDocCardItemCategory +}): JSX.Element | null { + const href = findFirstSidebarItemLink(item) + const icon = getCardIcon(item) + + // Unexpected: categories that don't have a link have been filtered upfront + if (!href) { + return null + } + + return ( + + ) +} + +function CardLink({ item }: { item: ModifiedDocCardItemLink }): JSX.Element { + const icon = getCardIcon(item) + const doc = useDocById(item.docId ?? undefined) + return ( + + ) +} + +export default function DocCard({ item }: ModifiedProps): JSX.Element { + switch (item.type) { + case "link": + return + case "category": + return + default: + throw new Error(`unknown item type ${JSON.stringify(item)}`) + } +} diff --git a/www/apps/docs/src/theme/DocCardList/index.tsx b/www/apps/docs/src/theme/DocCardList/index.tsx new file mode 100644 index 0000000..368b131 --- /dev/null +++ b/www/apps/docs/src/theme/DocCardList/index.tsx @@ -0,0 +1,39 @@ +import React from "react" +import clsx from "clsx" +import { + useCurrentSidebarCategory, + filterDocCardListItems, +} from "@docusaurus/theme-common" +import DocCard from "@theme/DocCard" +import type { Props } from "@theme/DocCardList" + +type ModifiedProps = { + colSize?: string +} & Props + +function DocCardListForCurrentSidebarCategory({ + className, + ...rest +}: ModifiedProps) { + const category = useCurrentSidebarCategory() + return +} + +export default function DocCardList(props: ModifiedProps): JSX.Element { + const { items, className } = props + if (!items) { + return + } + const filteredItems = filterDocCardListItems(items).filter( + (item) => !item.customProps?.exclude_from_doclist + ) + return ( +
+ {filteredItems.map((item, index) => ( + + ))} +
+ ) +} diff --git a/www/apps/docs/src/theme/DocItem/Content/index.tsx b/www/apps/docs/src/theme/DocItem/Content/index.tsx new file mode 100644 index 0000000..d73d5f2 --- /dev/null +++ b/www/apps/docs/src/theme/DocItem/Content/index.tsx @@ -0,0 +1,66 @@ +import React from "react" +import clsx from "clsx" +import { ThemeClassNames } from "@docusaurus/theme-common" +import { useDoc } from "@docusaurus/theme-common/internal" +import Heading from "@theme/Heading" +import MDXContent from "@theme/MDXContent" +import type { Props } from "@theme/DocItem/Content" +import { DocContextValue } from "@medusajs/docs" +import { Badge, BadgeVariant } from "docs-ui" + +/** + Title can be declared inside md content or declared through + front matter and added manually. To make both cases consistent, + the added title is added under the same div.markdown block + See https://github.com/facebook/docusaurus/pull/4882#issuecomment-853021120 + + We render a "synthetic title" if: + - user doesn't ask to hide it with front matter + - the markdown content does not already contain a top-level h1 heading +*/ +function useSyntheticTitle(): string | null { + const { metadata, frontMatter, contentTitle } = useDoc() + const shouldRender = + !frontMatter.hide_title && typeof contentTitle === "undefined" + if (!shouldRender) { + return null + } + return metadata.title +} + +export default function DocItemContent({ children }: Props): JSX.Element { + const { + frontMatter: { badge }, + } = useDoc() as DocContextValue + const syntheticTitle = useSyntheticTitle() + return ( +
+ {syntheticTitle && ( +
+ + {syntheticTitle} + {badge && ( + + {badge.text} + + )} + + {badge && ( + + {badge.text} + + )} +
+ )} + {children} +
+ ) +} diff --git a/www/apps/docs/src/theme/DocItem/Footer/index.tsx b/www/apps/docs/src/theme/DocItem/Footer/index.tsx new file mode 100644 index 0000000..b8dc30d --- /dev/null +++ b/www/apps/docs/src/theme/DocItem/Footer/index.tsx @@ -0,0 +1,28 @@ +import React from "react" +import Footer from "@theme-original/DocItem/Footer" +import type FooterType from "@theme/DocItem/Footer" +import type { WrapperProps } from "@docusaurus/types" +import { useDoc } from "@docusaurus/theme-common/internal" +import { useThemeConfig } from "@docusaurus/theme-common" +import type { ThemeConfig } from "@medusajs/docs" +import Feedback from "../../../components/Feedback" + +type Props = WrapperProps + +export default function FooterWrapper(props: Props): JSX.Element { + const { metadata } = useDoc() + const { footerFeedback = { event: "" } } = useThemeConfig() as ThemeConfig + return ( + <> + {!metadata.frontMatter?.hide_footer && ( +
+ +
+
+ )} + + ) +} diff --git a/www/apps/docs/src/theme/DocItem/Layout/index.tsx b/www/apps/docs/src/theme/DocItem/Layout/index.tsx new file mode 100644 index 0000000..843581c --- /dev/null +++ b/www/apps/docs/src/theme/DocItem/Layout/index.tsx @@ -0,0 +1,77 @@ +import React from "react" +import clsx from "clsx" +import { useWindowSize } from "@docusaurus/theme-common" +import { useDoc } from "@docusaurus/theme-common/internal" +import DocItemPaginator from "@theme/DocItem/Paginator" +import DocVersionBanner from "@theme/DocVersionBanner" +import DocVersionBadge from "@theme/DocVersionBadge" +import DocItemFooter from "@theme/DocItem/Footer" +import DocItemTOCMobile from "@theme/DocItem/TOC/Mobile" +import DocItemTOCDesktop from "@theme/DocItem/TOC/Desktop" +import DocItemContent from "@theme/DocItem/Content" +import DocBreadcrumbs from "@theme/DocBreadcrumbs" +import Unlisted from "@theme/Unlisted" +import type { Props } from "@theme/DocItem/Layout" +import { useSidebar } from "../../../providers/Sidebar" +import Footer from "@theme/Footer" + +/** + * Decide if the toc should be rendered, on mobile or desktop viewports + */ +function useDocTOC() { + const { frontMatter, toc } = useDoc() + const windowSize = useWindowSize() + + const hidden = frontMatter.hide_table_of_contents + const canRender = !hidden && toc.length > 0 + + const mobile = canRender ? : undefined + + const desktop = + canRender && (windowSize === "desktop" || windowSize === "ssr") ? ( + + ) : undefined + + return { + hidden, + mobile, + desktop, + } +} + +export default function DocItemLayout({ children }: Props): JSX.Element { + const docTOC = useDocTOC() + const { + metadata: { unlisted }, + } = useDoc() + const sidebarContext = useSidebar() + return ( +
+
+ {unlisted && } + +
+
*:first-child]:mt-0")}> + + + {docTOC.mobile} + {children} + +
+ +
+
+
+ {docTOC.desktop && ( +
{docTOC.desktop}
+ )} +
+ ) +} diff --git a/www/apps/docs/src/theme/DocRoot/Layout/Main/index.tsx b/www/apps/docs/src/theme/DocRoot/Layout/Main/index.tsx new file mode 100644 index 0000000..4f65a4f --- /dev/null +++ b/www/apps/docs/src/theme/DocRoot/Layout/Main/index.tsx @@ -0,0 +1,32 @@ +import React from "react" +import clsx from "clsx" +import { useDocsSidebar } from "@docusaurus/theme-common/internal" +import type { Props } from "@theme/DocRoot/Layout/Main" + +import { useSidebar } from "../../../../providers/Sidebar" + +export default function DocRootLayoutMain({ children }: Props): JSX.Element { + const sidebar = useDocsSidebar() + const sidebarContext = useSidebar() + return ( +
+
+ {children} +
+
+ ) +} diff --git a/www/apps/docs/src/theme/DocRoot/Layout/Sidebar/index.tsx b/www/apps/docs/src/theme/DocRoot/Layout/Sidebar/index.tsx new file mode 100644 index 0000000..6ef6e5d --- /dev/null +++ b/www/apps/docs/src/theme/DocRoot/Layout/Sidebar/index.tsx @@ -0,0 +1,105 @@ +import React, { type ReactNode, useRef } from "react" +import clsx from "clsx" +import { ThemeClassNames } from "@docusaurus/theme-common" +import { useDocsSidebar } from "@docusaurus/theme-common/internal" +import { useLocation } from "@docusaurus/router" +import DocSidebar from "@theme/DocSidebar" +import type { Props } from "@theme/DocRoot/Layout/Sidebar" +import { useSidebar } from "../../../../providers/Sidebar" +import { CSSTransition, SwitchTransition } from "react-transition-group" + +// Reset sidebar state when sidebar changes +// Use React key to unmount/remount the children +// See https://github.com/facebook/docusaurus/issues/3414 +function ResetOnSidebarChange({ children }: { children: ReactNode }) { + const sidebar = useDocsSidebar() + return ( + + {children} + + ) +} + +export default function DocRootLayoutSidebar({ + sidebar, + hiddenSidebarContainer, +}: Props): JSX.Element { + const { pathname } = useLocation() + const sidebarContext = useSidebar() + const { name } = useDocsSidebar() + const sidebarRef = useRef(null) + + return ( + + ) +} diff --git a/www/apps/docs/src/theme/DocRoot/Layout/index.tsx b/www/apps/docs/src/theme/DocRoot/Layout/index.tsx new file mode 100644 index 0000000..7771392 --- /dev/null +++ b/www/apps/docs/src/theme/DocRoot/Layout/index.tsx @@ -0,0 +1,35 @@ +import React from "react" +import { useDocsSidebar } from "@docusaurus/theme-common/internal" +import BackToTopButton from "@theme/BackToTopButton" +import DocRootLayoutSidebar from "@theme/DocRoot/Layout/Sidebar" +import DocRootLayoutMain from "@theme/DocRoot/Layout/Main" +import type { Props } from "@theme/DocRoot/Layout" + +import { useSidebar } from "../../../providers/Sidebar" +import clsx from "clsx" + +export default function DocRootLayout({ children }: Props): JSX.Element { + const sidebar = useDocsSidebar() + const sidebarContext = useSidebar() + return ( +
+ +
+ {sidebar && ( + + )} + + {children} + +
+
+ ) +} diff --git a/www/apps/docs/src/theme/DocRoot/index.tsx b/www/apps/docs/src/theme/DocRoot/index.tsx new file mode 100644 index 0000000..e5cc96c --- /dev/null +++ b/www/apps/docs/src/theme/DocRoot/index.tsx @@ -0,0 +1,33 @@ +import React from "react" +import clsx from "clsx" +import { + HtmlClassNameProvider, + ThemeClassNames, +} from "@docusaurus/theme-common" +import { + DocsSidebarProvider, + useDocRootMetadata, +} from "@docusaurus/theme-common/internal" +import DocRootLayout from "@theme/DocRoot/Layout" +import NotFoundContent from "@theme/NotFound/Content" +import type { Props } from "@theme/DocRoot" +import SidebarProvider from "../../providers/Sidebar" + +export default function DocRoot(props: Props): JSX.Element { + const currentDocRouteMetadata = useDocRootMetadata(props) + if (!currentDocRouteMetadata) { + // We only render the not found content to avoid a double layout + // see https://github.com/facebook/docusaurus/pull/7966#pullrequestreview-1077276692 + return + } + const { docElement, sidebarName, sidebarItems } = currentDocRouteMetadata + return ( + + + + {docElement} + + + + ) +} diff --git a/www/apps/docs/src/theme/DocSidebar/Desktop/index.tsx b/www/apps/docs/src/theme/DocSidebar/Desktop/index.tsx new file mode 100644 index 0000000..e573958 --- /dev/null +++ b/www/apps/docs/src/theme/DocSidebar/Desktop/index.tsx @@ -0,0 +1,95 @@ +import React, { useEffect, useRef } from "react" +import clsx from "clsx" +import { useThemeConfig } from "@docusaurus/theme-common" +import AnnouncementBar from "@theme/AnnouncementBar" +import Content from "@theme/DocSidebar/Desktop/Content" +import type { Props } from "@theme/DocSidebar/Desktop" +import useIsBrowser from "@docusaurus/useIsBrowser" +import { useLocation } from "@docusaurus/router" + +function DocSidebarDesktop({ path, sidebar }: Props) { + const { + navbar: { hideOnScroll }, + } = useThemeConfig() + const isBrowser = useIsBrowser() + const sidebarRef = useRef(null) + const location = useLocation() + + useEffect(() => { + function handleScroll() { + if (!sidebarRef.current?.classList.contains("scrolling")) { + sidebarRef.current?.classList.add("scrolling") + const intervalId = setInterval(() => { + if (!sidebarRef.current?.matches(":hover")) { + sidebarRef.current?.classList.remove("scrolling") + clearInterval(intervalId) + } + }, 300) + } + } + + if (isBrowser && sidebarRef.current) { + const navElement = sidebarRef.current.querySelector(".main-sidebar") + navElement.addEventListener("scroll", handleScroll) + + return () => { + navElement?.removeEventListener("scroll", handleScroll) + } + } + }, [isBrowser, sidebarRef.current]) + + useEffect(() => { + const navElement = sidebarRef.current.querySelector(".main-sidebar") + const navElementBoundingRect = navElement.getBoundingClientRect() + + // logic to scroll to current active item + const activeItem = document.querySelector( + ".sidebar-desktop [aria-current=page]" + ) + + if (!activeItem) { + return + } + + const activeItemBoundingReact = activeItem.getBoundingClientRect() + // the extra 160 is due to the sticky elements in the sidebar + const isActiveItemVisible = + activeItemBoundingReact.top >= 0 && + activeItemBoundingReact.bottom + 160 <= navElementBoundingRect.height + + if (!isActiveItemVisible) { + const elementToScrollTo = activeItem + const elementBounding = elementToScrollTo.getBoundingClientRect() + // scroll to element + navElement.scroll({ + // the extra 160 is due to the sticky elements in the sidebar + top: + elementBounding.top - + navElementBoundingRect.top + + navElement.scrollTop - + 160, + behaviour: "smooth", + }) + } + }, [location]) + + return ( +
+ + +
+ ) +} + +export default React.memo(DocSidebarDesktop) diff --git a/www/apps/docs/src/theme/DocSidebarItem/Category/index.tsx b/www/apps/docs/src/theme/DocSidebarItem/Category/index.tsx new file mode 100644 index 0000000..a59c4c0 --- /dev/null +++ b/www/apps/docs/src/theme/DocSidebarItem/Category/index.tsx @@ -0,0 +1,244 @@ +import React, { type ComponentProps, useEffect, useMemo } from "react" +import clsx from "clsx" +import { + ThemeClassNames, + useThemeConfig, + usePrevious, + Collapsible, + useCollapsible, +} from "@docusaurus/theme-common" +import { + isActiveSidebarItem, + findFirstSidebarItemLink, + useDocSidebarItemsExpandedState, + isSamePath, +} from "@docusaurus/theme-common/internal" +import Link from "@docusaurus/Link" +import { translate } from "@docusaurus/Translate" +import useIsBrowser from "@docusaurus/useIsBrowser" +import DocSidebarItems from "@theme/DocSidebarItems" +import type { Props } from "@theme/DocSidebarItem/Category" +import { ModifiedPropSidebarItemCategory } from "@medusajs/docs" +import DocSidebarItemIcon from "../../../components/DocSidebarItemIcon" +import { Badge } from "docs-ui" + +type ModifiedProps = Props & { + item: ModifiedPropSidebarItemCategory +} + +// If we navigate to a category and it becomes active, it should automatically +// expand itself +function useAutoExpandActiveCategory({ + isActive, + collapsed, + updateCollapsed, +}: { + isActive: boolean + collapsed: boolean + updateCollapsed: (b: boolean) => void +}) { + const wasActive = usePrevious(isActive) + useEffect(() => { + const justBecameActive = isActive && !wasActive + if (justBecameActive && collapsed) { + updateCollapsed(false) + } + }, [isActive, wasActive, collapsed, updateCollapsed]) +} + +/** + * When a collapsible category has no link, we still link it to its first child + * during SSR as a temporary fallback. This allows to be able to navigate inside + * the category even when JS fails to load, is delayed or simply disabled + * React hydration becomes an optional progressive enhancement + * see https://github.com/facebookincubator/infima/issues/36#issuecomment-772543188 + * see https://github.com/facebook/docusaurus/issues/3030 + */ +function useCategoryHrefWithSSRFallback( + item: Props["item"] +): string | undefined { + const isBrowser = useIsBrowser() + return useMemo(() => { + if (item.href && !item.linkUnlisted) { + return item.href + } + // In these cases, it's not necessary to render a fallback + // We skip the "findFirstCategoryLink" computation + if (isBrowser || !item.collapsible) { + return undefined + } + return findFirstSidebarItemLink(item) + }, [item, isBrowser]) +} + +function CollapseButton({ + categoryLabel, + onClick, +}: { + collapsed: boolean + categoryLabel: string + onClick: ComponentProps<"button">["onClick"] +}) { + return ( + + ) +} diff --git a/www/apps/docs/src/theme/Footer/Layout/index.tsx b/www/apps/docs/src/theme/Footer/Layout/index.tsx new file mode 100644 index 0000000..e060e4d --- /dev/null +++ b/www/apps/docs/src/theme/Footer/Layout/index.tsx @@ -0,0 +1,51 @@ +import React from "react" +import clsx from "clsx" +import type { Props } from "@theme/Footer/Layout" +import { ThemeConfig } from "@medusajs/docs" +import { useThemeConfig } from "@docusaurus/theme-common" +import SocialLinks from "@site/src/components/Footer/SocialLinks" + +export default function FooterLayout({ + style, + links, + logo, + copyright, +}: Props): JSX.Element { + const { socialLinks } = useThemeConfig() as ThemeConfig + + return ( +
+
+ {(logo || copyright || socialLinks) && ( +
+
+ {logo &&
{logo}
} + {copyright} +
+
+ )} +
+ {socialLinks && } + {links} +
+
+
+ ) +} diff --git a/www/apps/docs/src/theme/Icon/Beaker/index.tsx b/www/apps/docs/src/theme/Icon/Beaker/index.tsx new file mode 100644 index 0000000..432c801 --- /dev/null +++ b/www/apps/docs/src/theme/Icon/Beaker/index.tsx @@ -0,0 +1,27 @@ +import { IconProps } from "@medusajs/icons/dist/types" +import clsx from "clsx" +import React from "react" + +const IconBeaker = (props: IconProps) => { + return ( + + + + ) +} + +export default IconBeaker diff --git a/www/apps/docs/src/theme/Icon/CircleDottedLine/index.tsx b/www/apps/docs/src/theme/Icon/CircleDottedLine/index.tsx new file mode 100644 index 0000000..9420c34 --- /dev/null +++ b/www/apps/docs/src/theme/Icon/CircleDottedLine/index.tsx @@ -0,0 +1,62 @@ +import { IconProps } from "@medusajs/icons/dist/types" +import clsx from "clsx" +import React from "react" + +const IconCircleDottedLine = (props: IconProps) => { + return ( + + + + + + + + + ) +} + +export default IconCircleDottedLine diff --git a/www/apps/docs/src/theme/Icon/Close/index.tsx b/www/apps/docs/src/theme/Icon/Close/index.tsx new file mode 100644 index 0000000..76a363d --- /dev/null +++ b/www/apps/docs/src/theme/Icon/Close/index.tsx @@ -0,0 +1,9 @@ +import React from "react" +import { XMark } from "@medusajs/icons" +import { IconProps } from "@medusajs/icons/dist/types" + +const IconClose = (props: IconProps) => { + return +} + +export default IconClose diff --git a/www/apps/docs/src/theme/Icon/Copy/index.tsx b/www/apps/docs/src/theme/Icon/Copy/index.tsx new file mode 100644 index 0000000..e2d0a16 --- /dev/null +++ b/www/apps/docs/src/theme/Icon/Copy/index.tsx @@ -0,0 +1,9 @@ +import React from "react" +import { SquareTwoStackSolid } from "@medusajs/icons" +import { IconProps } from "@medusajs/icons/dist/types" + +const IconCopy = (props: IconProps) => { + return +} + +export default IconCopy diff --git a/www/apps/docs/src/theme/Icon/DarkMode/index.tsx b/www/apps/docs/src/theme/Icon/DarkMode/index.tsx new file mode 100644 index 0000000..3668187 --- /dev/null +++ b/www/apps/docs/src/theme/Icon/DarkMode/index.tsx @@ -0,0 +1,9 @@ +import { Moon } from "@medusajs/icons" +import { IconProps } from "@medusajs/icons/dist/types" +import React from "react" + +const IconDarkMode = (props: IconProps) => { + return +} + +export default IconDarkMode diff --git a/www/apps/docs/src/theme/Icon/Discord/index.tsx b/www/apps/docs/src/theme/Icon/Discord/index.tsx new file mode 100644 index 0000000..960b8bc --- /dev/null +++ b/www/apps/docs/src/theme/Icon/Discord/index.tsx @@ -0,0 +1,24 @@ +import { IconProps } from "@medusajs/icons/dist/types" +import clsx from "clsx" +import React from "react" + +const IconDiscord = (props: IconProps) => { + return ( + + + + ) +} + +export default IconDiscord diff --git a/www/apps/docs/src/theme/Icon/ExternalLink/index.tsx b/www/apps/docs/src/theme/Icon/ExternalLink/index.tsx new file mode 100644 index 0000000..2fe03f1 --- /dev/null +++ b/www/apps/docs/src/theme/Icon/ExternalLink/index.tsx @@ -0,0 +1,9 @@ +import { ArrowUpRightOnBox } from "@medusajs/icons" +import { IconProps } from "@medusajs/icons/dist/types" +import React from "react" + +const IconExternalLink = (props: IconProps) => { + return +} + +export default IconExternalLink diff --git a/www/apps/docs/src/theme/Icon/FlagMini/index.tsx b/www/apps/docs/src/theme/Icon/FlagMini/index.tsx new file mode 100644 index 0000000..bd3948f --- /dev/null +++ b/www/apps/docs/src/theme/Icon/FlagMini/index.tsx @@ -0,0 +1,27 @@ +import { IconProps } from "@medusajs/icons/dist/types" +import clsx from "clsx" +import React from "react" + +const IconFlagMini = (props: IconProps) => { + return ( + + + + ) +} + +export default IconFlagMini diff --git a/www/apps/docs/src/theme/Icon/GitHub/index.tsx b/www/apps/docs/src/theme/Icon/GitHub/index.tsx new file mode 100644 index 0000000..678d426 --- /dev/null +++ b/www/apps/docs/src/theme/Icon/GitHub/index.tsx @@ -0,0 +1,26 @@ +import { IconProps } from "@medusajs/icons/dist/types" +import clsx from "clsx" +import React from "react" + +const IconGitHub = (props: IconProps) => { + return ( + + + + ) +} + +export default IconGitHub diff --git a/www/apps/docs/src/theme/Icon/LightMode/index.tsx b/www/apps/docs/src/theme/Icon/LightMode/index.tsx new file mode 100644 index 0000000..544e788 --- /dev/null +++ b/www/apps/docs/src/theme/Icon/LightMode/index.tsx @@ -0,0 +1,9 @@ +import React from "react" +import { Sun } from "@medusajs/icons" +import { IconProps } from "@medusajs/icons/dist/types" + +const IconLightMode = (props: IconProps) => { + return +} + +export default IconLightMode diff --git a/www/apps/docs/src/theme/Icon/LinkedIn/index.tsx b/www/apps/docs/src/theme/Icon/LinkedIn/index.tsx new file mode 100644 index 0000000..ba5660f --- /dev/null +++ b/www/apps/docs/src/theme/Icon/LinkedIn/index.tsx @@ -0,0 +1,24 @@ +import { IconProps } from "@medusajs/icons/dist/types" +import clsx from "clsx" +import React from "react" + +const IconLinkedIn = (props: IconProps) => { + return ( + + + + ) +} + +export default IconLinkedIn diff --git a/www/apps/docs/src/theme/Icon/Nextjs/index.tsx b/www/apps/docs/src/theme/Icon/Nextjs/index.tsx new file mode 100644 index 0000000..a105a45 --- /dev/null +++ b/www/apps/docs/src/theme/Icon/Nextjs/index.tsx @@ -0,0 +1,28 @@ +import { IconProps } from "@medusajs/icons/dist/types" +import clsx from "clsx" +import React from "react" + +const IconNextjs = (props: IconProps) => { + return ( + + + + + ) +} + +export default IconNextjs diff --git a/www/apps/docs/src/theme/Icon/PuzzleSolid/index.tsx b/www/apps/docs/src/theme/Icon/PuzzleSolid/index.tsx new file mode 100644 index 0000000..558fbda --- /dev/null +++ b/www/apps/docs/src/theme/Icon/PuzzleSolid/index.tsx @@ -0,0 +1,24 @@ +import { IconProps } from "@medusajs/icons/dist/types" +import clsx from "clsx" +import React from "react" + +const IconPuzzleSolid = (props: IconProps) => { + return ( + + + + ) +} + +export default IconPuzzleSolid diff --git a/www/apps/docs/src/theme/Icon/Twitter/index.tsx b/www/apps/docs/src/theme/Icon/Twitter/index.tsx new file mode 100644 index 0000000..19bdcbc --- /dev/null +++ b/www/apps/docs/src/theme/Icon/Twitter/index.tsx @@ -0,0 +1,24 @@ +import { IconProps } from "@medusajs/icons/dist/types" +import clsx from "clsx" +import React from "react" + +const IconTwitter = (props: IconProps) => { + return ( + + + + ) +} + +export default IconTwitter diff --git a/www/apps/docs/src/theme/Icon/index.tsx b/www/apps/docs/src/theme/Icon/index.tsx new file mode 100644 index 0000000..0b5eaa6 --- /dev/null +++ b/www/apps/docs/src/theme/Icon/index.tsx @@ -0,0 +1,222 @@ +import { + AtSymbol, + AcademicCapSolid, + Adjustments, + ArrowDownLeftMini, + ArrowDownTray, + ArrowUpRightOnBox, + ArrowUturnLeft, + BarsThree, + BellAlert, + BellAlertSolid, + Bolt, + BoltSolid, + BookOpen, + Bug, + BugAntSolid, + BuildingStorefront, + BuildingTax, + BuildingsSolid, + Calendar, + CashSolid, + Channels, + ChannelsSolid, + CheckCircleSolid, + CheckMini, + ChevronDoubleLeftMiniSolid, + ChevronUpDown, + CircleDottedLine, + CircleMiniSolid, + CircleStack, + CircleStackSolid, + ClockSolidMini, + CloudArrowUp, + CogSixTooth, + CogSixToothSolid, + CommandLine, + CommandLineSolid, + ComponentSolid, + ComputerDesktop, + ComputerDesktopSolid, + CreditCardSolid, + CubeSolid, + CurrencyDollar, + CurrencyDollarSolid, + Discord, + DocumentText, + DocumentTextSolid, + EllipseMiniSolid, + ExclamationCircle, + ExclamationCircleSolid, + FlyingBox, + Folder, + FolderOpen, + Gatsby, + GiftSolid, + GlobeEurope, + GlobeEuropeSolid, + InformationCircleSolid, + JavascriptEx, + Key, + KeySolid, + LightBulb, + LightBulbSolid, + Linkedin, + MagnifyingGlass, + Map, + Moon, + Newspaper, + PencilSquareSolid, + Puzzle, + ReactJsEx, + ReceiptPercent, + RocketLaunch, + Server, + ServerSolid, + ServerStack, + ServerStackSolid, + ShoppingCart, + ShoppingCartSolid, + Sparkles, + SparklesSolid, + SquareTwoStackSolid, + SquaresPlus, + SquaresPlusSolid, + Star, + StarSolid, + Stripe, + Sun, + SwatchSolid, + TagSolid, + Text, + Tools, + ToolsSolid, + Twitter, + User, + UsersSolid, + XCircleSolid, + XMark, + XMarkMini, + PhotoSolid, + PlaySolid, + ChatBubbleLeftRightSolid, +} from "@medusajs/icons" +import IconPuzzleSolid from "./PuzzleSolid" +import IconNextjs from "./Nextjs" +import IconFlagMini from "./FlagMini" +import IconBeaker from "./Beaker" +import IconGitHub from "./GitHub" + +const icons = { + "academic-cap-solid": AcademicCapSolid, + adjustments: Adjustments, + alert: ExclamationCircleSolid, + "arrow-down-left-mini": ArrowDownLeftMini, + "arrow-down-tray": ArrowDownTray, + "at-symbol": AtSymbol, + "back-arrow": ArrowUturnLeft, + "bars-three": BarsThree, + beaker: IconBeaker, + bell: BellAlert, + "bell-alert-solid": BellAlertSolid, + bolt: Bolt, + "bolt-solid": BoltSolid, + "book-open": BookOpen, + bug: Bug, + "bug-ant-solid": BugAntSolid, + "building-solid": BuildingsSolid, + "building-storefront": BuildingStorefront, + "building-tax": BuildingTax, + calendar: Calendar, + "cash-solid": CashSolid, + "channels-solid": ChannelsSolid, + channels: Channels, + "chat-bubble-left-right-solid": ChatBubbleLeftRightSolid, + "check-circle-solid": CheckCircleSolid, + "check-mini": CheckMini, + "chevron-double-left-mini-solid": ChevronDoubleLeftMiniSolid, + "chevron-up-down": ChevronUpDown, + "circle-dotted-line": CircleDottedLine, + "circle-mini-solid": CircleMiniSolid, + "circle-stack": CircleStack, + "circle-stack-solid": CircleStackSolid, + "clock-solid-mini": ClockSolidMini, + close: XMark, + "cloud-arrow-up": CloudArrowUp, + "cog-six-tooth": CogSixTooth, + "cog-six-tooth-solid": CogSixToothSolid, + "command-line": CommandLine, + "command-line-solid": CommandLineSolid, + "component-solid": ComponentSolid, + "computer-desktop": ComputerDesktop, + "computer-desktop-solid": ComputerDesktopSolid, + copy: SquareTwoStackSolid, + "credit-card-solid": CreditCardSolid, + "cube-solid": CubeSolid, + "currency-dollar": CurrencyDollar, + "currency-dollar-solid": CurrencyDollarSolid, + "dark-mode": Moon, + discord: Discord, + "document-text": DocumentText, + "document-text-solid": DocumentTextSolid, + "ellipse-mini-solid": EllipseMiniSolid, + "exclamation-circle-solid": ExclamationCircleSolid, + "external-link": ArrowUpRightOnBox, + "flying-box": FlyingBox, + folder: Folder, + "folder-open": FolderOpen, + gatsby: Gatsby, + "gift-solid": GiftSolid, + "flag-mini": IconFlagMini, + github: IconGitHub, + "globe-europe": GlobeEurope, + "globe-europe-solid": GlobeEuropeSolid, + "information-circle-solid": InformationCircleSolid, + javascript: JavascriptEx, + key: Key, + "key-solid": KeySolid, + "light-bulb": LightBulb, + "light-bulb-solid": LightBulbSolid, + "light-mode": Sun, + linkedin: Linkedin, + "magnifying-glass": MagnifyingGlass, + map: Map, + newspaper: Newspaper, + nextjs: IconNextjs, + "pencil-square-solid": PencilSquareSolid, + "photo-solid": PhotoSolid, + "play-solid": PlaySolid, + puzzle: Puzzle, + // TODO change once available in Icons package + "puzzle-solid": IconPuzzleSolid, + react: ReactJsEx, + "receipt-percent": ReceiptPercent, + report: ExclamationCircle, + "rocket-launch": RocketLaunch, + server: Server, + "server-solid": ServerSolid, + "server-stack": ServerStack, + "server-stack-solid": ServerStackSolid, + "shopping-cart": ShoppingCart, + "shopping-cart-solid": ShoppingCartSolid, + sparkles: Sparkles, + "sparkles-solid": SparklesSolid, + "squares-plus": SquaresPlus, + "squares-plus-solid": SquaresPlusSolid, + star: Star, + "star-solid": StarSolid, + stripe: Stripe, + "swatch-solid": SwatchSolid, + "tag-solid": TagSolid, + text: Text, + tools: Tools, + "tools-solid": ToolsSolid, + twitter: Twitter, + user: User, + "users-solid": UsersSolid, + "x-circle-solid": XCircleSolid, + "x-mark": XMark, + "x-mark-mini": XMarkMini, +} +export type IconName = keyof typeof icons +export default icons \ No newline at end of file diff --git a/www/apps/docs/src/theme/Layout/index.tsx b/www/apps/docs/src/theme/Layout/index.tsx new file mode 100644 index 0000000..a422645 --- /dev/null +++ b/www/apps/docs/src/theme/Layout/index.tsx @@ -0,0 +1,75 @@ +import React, { useEffect } from "react" +import clsx from "clsx" +import ErrorBoundary from "@docusaurus/ErrorBoundary" +import { + PageMetadata, + SkipToContentFallbackId, + ThemeClassNames, +} from "@docusaurus/theme-common" +import { useKeyboardNavigation } from "@docusaurus/theme-common/internal" +import SkipToContent from "@theme/SkipToContent" +import Navbar from "@theme/Navbar" +import LayoutProvider from "@theme/Layout/Provider" +import ErrorPageContent from "@theme/ErrorPageContent" +import type { Props } from "@theme/Layout" +import useIsBrowser from "@docusaurus/useIsBrowser" +import { useLocation } from "@docusaurus/router" +import { useAnalytics } from "docs-ui" + +export default function Layout(props: Props): JSX.Element { + const { + children, + wrapperClassName, + // Not really layout-related, but kept for convenience/retro-compatibility + title, + description, + } = props + + useKeyboardNavigation() + const isBrowser = useIsBrowser() + const location = useLocation() + const { track } = useAnalytics() + + useEffect(() => { + if (isBrowser) { + const handlePlay = () => { + track("video_played") + } + + const videos = document.querySelectorAll("video") + videos.forEach((video) => + video.addEventListener("play", handlePlay, { + once: true, + capture: true, + }) + ) + + return () => { + videos.forEach((video) => video.removeEventListener("play", handlePlay)) + } + } + }, [isBrowser, location.pathname]) + + return ( + + + + + + + +
+ }> + {children} + +
+
+ ) +} diff --git a/www/apps/docs/src/theme/MDXComponents/A.tsx b/www/apps/docs/src/theme/MDXComponents/A.tsx new file mode 100644 index 0000000..14887f8 --- /dev/null +++ b/www/apps/docs/src/theme/MDXComponents/A.tsx @@ -0,0 +1,48 @@ +import React, { useMemo } from "react" +import { getGlossaryByPath } from "../../utils/glossary" +import useDocusaurusContext from "@docusaurus/useDocusaurusContext" +import { MedusaDocusaurusContext } from "@medusajs/docs" +import Link from "@docusaurus/Link" +import type { Props } from "@docusaurus/Link" +import clsx from "clsx" +import { Tooltip } from "docs-ui" + +const MDXA = (props: Omit) => { + const { href, children } = props + const { + siteConfig: { url }, + } = useDocusaurusContext() as MedusaDocusaurusContext + + // check if a glossary exists for href + const glossary = useMemo(() => { + return (typeof children === "string" && href.startsWith("/")) || + href.includes(url) + ? getGlossaryByPath(children as string) + : null + }, [href, children]) + + if (!glossary) { + return + } + + return ( + + + {glossary.title} + + {glossary.content} + + } + clickable={true} + > + + + ) +} + +export default MDXA diff --git a/www/apps/docs/src/theme/MDXComponents/Code.tsx b/www/apps/docs/src/theme/MDXComponents/Code.tsx new file mode 100644 index 0000000..b16de38 --- /dev/null +++ b/www/apps/docs/src/theme/MDXComponents/Code.tsx @@ -0,0 +1,17 @@ +import type { ComponentProps } from "react" +import React from "react" +import CodeBlock from "@theme/CodeBlock" +import type { Props } from "@theme/MDXComponents/Code" +import { InlineCode } from "docs-ui" + +export default function MDXCode(props: Omit): JSX.Element { + const shouldBeInline = React.Children.toArray(props.children).every( + (el) => typeof el === "string" && !el.includes("\n") + ) + + return shouldBeInline ? ( + + ) : ( + )} /> + ) +} diff --git a/www/apps/docs/src/theme/MDXComponents/Details.tsx b/www/apps/docs/src/theme/MDXComponents/Details.tsx new file mode 100644 index 0000000..d678659 --- /dev/null +++ b/www/apps/docs/src/theme/MDXComponents/Details.tsx @@ -0,0 +1,27 @@ +import React, { type ComponentProps, type ReactElement } from "react" +import Details from "@theme/Details" +import type { Props } from "@theme/MDXComponents/Details" +import { DetailsSummary } from "docs-ui" + +export default function MDXDetails(props: Omit): JSX.Element { + const items = React.Children.toArray(props.children) + // Split summary item from the rest to pass it as a separate prop to the + // Details theme component + const summary = items.find( + ( + item: ReactElement> + ): item is ReactElement> => { + return ( + React.isValidElement(item) && + (item.type === "summary" || item.type === DetailsSummary) + ) + } + ) + const children = <>{items.filter((item) => item !== summary)} + + return ( +
+ {children} +
+ ) +} diff --git a/www/apps/docs/src/theme/MDXComponents/H1.tsx b/www/apps/docs/src/theme/MDXComponents/H1.tsx new file mode 100644 index 0000000..34b696c --- /dev/null +++ b/www/apps/docs/src/theme/MDXComponents/H1.tsx @@ -0,0 +1,28 @@ +import React from "react" +import type { Props } from "@theme/MDXComponents/Heading" +import MDXHeading from "@theme/MDXComponents/Heading" +import { useDoc } from "@docusaurus/theme-common/internal" +import { DocContextValue } from "@medusajs/docs" +import { Badge, BadgeVariant } from "docs-ui" +import clsx from "clsx" + +const H1 = ({ className, ...props }: Omit) => { + const { + frontMatter: { badge }, + } = useDoc() as DocContextValue + + return ( +
+ + {badge && ( + {badge.text} + )} +
+ ) +} + +export default H1 diff --git a/www/apps/docs/src/theme/MDXComponents/index.tsx b/www/apps/docs/src/theme/MDXComponents/index.tsx new file mode 100644 index 0000000..a068bb7 --- /dev/null +++ b/www/apps/docs/src/theme/MDXComponents/index.tsx @@ -0,0 +1,25 @@ +// Import the original mapper +import MDXComponents from "@theme-original/MDXComponents" +import CloudinaryImage from "@site/src/components/CloudinaryImage" +import MDXA from "./A" +import { Kbd, DetailsSummary } from "docs-ui" +import H1 from "./H1" +import MDXCode from "./Code" +import MDXDetails from "./Details" +import DocCard from "@theme/DocCard" +import DocCardList from "@theme/DocCardList" + +export default { + // Re-use the default mapping + ...MDXComponents, + code: MDXCode, + img: CloudinaryImage, + details: MDXDetails, + Details: MDXDetails, + Summary: DetailsSummary, + a: MDXA, + kbd: Kbd, + h1: H1, + DocCard, + DocCardList, +} diff --git a/www/apps/docs/src/theme/Navbar/ColorModeToggle/index.tsx b/www/apps/docs/src/theme/Navbar/ColorModeToggle/index.tsx new file mode 100644 index 0000000..01b0425 --- /dev/null +++ b/www/apps/docs/src/theme/Navbar/ColorModeToggle/index.tsx @@ -0,0 +1,25 @@ +import React from "react" +import { useColorMode, useThemeConfig } from "@docusaurus/theme-common" +import ColorModeToggle from "@theme/ColorModeToggle" +import type { Props } from "@theme/Navbar/ColorModeToggle" +import clsx from "clsx" + +export default function NavbarColorModeToggle({ + className, +}: Props): JSX.Element | null { + const disabled = useThemeConfig().colorMode.disableSwitch + const { colorMode, setColorMode } = useColorMode() + + if (disabled) { + return null + } + + return ( + + ) +} diff --git a/www/apps/docs/src/theme/Navbar/Content/index.tsx b/www/apps/docs/src/theme/Navbar/Content/index.tsx new file mode 100644 index 0000000..0bc3535 --- /dev/null +++ b/www/apps/docs/src/theme/Navbar/Content/index.tsx @@ -0,0 +1,167 @@ +import React, { type ReactNode } from "react" +import { useThemeConfig } from "@docusaurus/theme-common" +import { + splitNavbarItems, + useNavbarMobileSidebar, +} from "@docusaurus/theme-common/internal" +import NavbarItem, { type Props as NavbarItemConfig } from "@theme/NavbarItem" +import NavbarColorModeToggle from "@theme/Navbar/ColorModeToggle" +import NavbarMobileSidebarToggle from "@theme/Navbar/MobileSidebar/Toggle" +import NavbarLogo from "@theme/Navbar/Logo" +import clsx from "clsx" +import { ThemeConfig } from "@medusajs/docs" +import { useSidebar } from "../../../providers/Sidebar" +import useIsBrowser from "@docusaurus/useIsBrowser" +import { Tooltip } from "docs-ui" +import NavbarActions from "../../../components/Navbar/Actions" +import { ChevronDoubleLeftMiniSolid, Sidebar } from "@medusajs/icons" + +function useNavbarItems() { + // TODO temporary casting until ThemeConfig type is improved + return useThemeConfig().navbar.items as NavbarItemConfig[] +} + +function NavbarItems({ items }: { items: NavbarItemConfig[] }): JSX.Element { + return ( + <> + {items.map((item, i) => ( + + ))} + + ) +} + +function NavbarContentLayout({ + left, + right, +}: { + left: ReactNode + right: ReactNode +}) { + return ( +
+
+ {left} +
+
+ {right} +
+
+ ) +} + +export default function NavbarContent(): JSX.Element { + const mobileSidebar = useNavbarMobileSidebar() + + const items = useNavbarItems() + const [leftItems, rightItems] = splitNavbarItems(items) + const { + navbarActions, + docs: { + sidebar: { hideable }, + }, + } = useThemeConfig() as ThemeConfig + const sidebarContext = useSidebar() + const isBrowser = useIsBrowser() + + const isApple = isBrowser + ? navigator.userAgent.toLowerCase().indexOf("mac") !== 0 + : true + + return ( + + {!mobileSidebar.disabled && } + + + + } + right={ + // TODO stop hardcoding items? + // Ask the user to add the respective navbar items => more flexible +
+ + {hideable && sidebarContext?.hasSidebar && ( + Close sidebar ${isApple ? "⌘" : "Ctrl"} + I` + : `Lock sidebar open ${isApple ? "⌘" : "Ctrl"} + I`, + events: { + onClick: sidebarContext?.onCollapse, + onMouseEnter: () => { + if (!sidebarContext?.hiddenSidebarContainer) { + sidebarContext?.setFloatingSidebar(false) + } else { + sidebarContext?.setFloatingSidebar(true) + } + }, + onMouseLeave: () => { + setTimeout(() => { + if ( + !document.querySelector( + ".theme-doc-sidebar-container:hover" + ) + ) { + sidebarContext?.setFloatingSidebar(false) + } + }, 100) + }, + }, + Icon: !sidebarContext?.hiddenSidebarContainer ? ( + + ) : ( + + ), + buttonType: "icon", + }, + ]} + className="sidebar-toggler" + /> + )} + + button]:!rounded" + )} + /> + + +
+ } + /> + ) +} diff --git a/www/apps/docs/src/theme/Navbar/Layout/index.tsx b/www/apps/docs/src/theme/Navbar/Layout/index.tsx new file mode 100644 index 0000000..f200cd2 --- /dev/null +++ b/www/apps/docs/src/theme/Navbar/Layout/index.tsx @@ -0,0 +1,44 @@ +import React from "react" +import clsx from "clsx" +import { useThemeConfig } from "@docusaurus/theme-common" +import { + useHideableNavbar, + useNavbarMobileSidebar, +} from "@docusaurus/theme-common/internal" +import { translate } from "@docusaurus/Translate" +import NavbarMobileSidebar from "@theme/Navbar/MobileSidebar" +import type { Props } from "@theme/Navbar/Layout" + +export default function NavbarLayout({ children }: Props): JSX.Element { + const { + navbar: { hideOnScroll, style }, + } = useThemeConfig() + const mobileSidebar = useNavbarMobileSidebar() + const { navbarRef, isNavbarVisible } = useHideableNavbar(hideOnScroll) + return ( + + ) +} diff --git a/www/apps/docs/src/theme/Navbar/Logo/index.tsx b/www/apps/docs/src/theme/Navbar/Logo/index.tsx new file mode 100644 index 0000000..15e6192 --- /dev/null +++ b/www/apps/docs/src/theme/Navbar/Logo/index.tsx @@ -0,0 +1,20 @@ +import React from "react" +import Logo from "@theme/Logo" +import MobileLogo from "../../../components/MobileLogo" + +export default function NavbarLogo(): JSX.Element { + return ( + <> + + + + ) +} diff --git a/www/apps/docs/src/theme/Navbar/MobileSidebar/Header/index.tsx b/www/apps/docs/src/theme/Navbar/MobileSidebar/Header/index.tsx new file mode 100644 index 0000000..68a99a0 --- /dev/null +++ b/www/apps/docs/src/theme/Navbar/MobileSidebar/Header/index.tsx @@ -0,0 +1,43 @@ +import React from "react" +import { useNavbarMobileSidebar } from "@docusaurus/theme-common/internal" +import { translate } from "@docusaurus/Translate" +import NavbarColorModeToggle from "@theme/Navbar/ColorModeToggle" +import IconClose from "@theme/Icon/Close" +import NavbarLogo from "@theme/Navbar/Logo" +import clsx from "clsx" + +function CloseButton() { + const mobileSidebar = useNavbarMobileSidebar() + return ( + + ) +} + +export default function NavbarMobileSidebarHeader(): JSX.Element { + return ( +
+ + button]:hover:bg-medusa-button-neutral-hover", + "[&>button]:!rounded" + )} + /> + +
+ ) +} diff --git a/www/apps/docs/src/theme/Navbar/MobileSidebar/Layout/index.tsx b/www/apps/docs/src/theme/Navbar/MobileSidebar/Layout/index.tsx new file mode 100644 index 0000000..2016389 --- /dev/null +++ b/www/apps/docs/src/theme/Navbar/MobileSidebar/Layout/index.tsx @@ -0,0 +1,23 @@ +import React from "react" +import clsx from "clsx" +import { useNavbarSecondaryMenu } from "@docusaurus/theme-common/internal" +import type { Props } from "@theme/Navbar/MobileSidebar/Layout" + +export default function NavbarMobileSidebarLayout({ + primaryMenu, + secondaryMenu, +}: Props): JSX.Element { + const { shown: secondaryMenuShown } = useNavbarSecondaryMenu() + return ( +
+
+
{primaryMenu}
+
{secondaryMenu}
+
+
+ ) +} diff --git a/www/apps/docs/src/theme/Navbar/MobileSidebar/Toggle/index.tsx b/www/apps/docs/src/theme/Navbar/MobileSidebar/Toggle/index.tsx new file mode 100644 index 0000000..015493f --- /dev/null +++ b/www/apps/docs/src/theme/Navbar/MobileSidebar/Toggle/index.tsx @@ -0,0 +1,25 @@ +import React from "react" +import { useNavbarMobileSidebar } from "@docusaurus/theme-common/internal" +import { translate } from "@docusaurus/Translate" +import { Sidebar, XMark } from "@medusajs/icons" + +export default function MobileSidebarToggle(): JSX.Element { + const { toggle, shown } = useNavbarMobileSidebar() + return ( + + ) +} diff --git a/www/apps/docs/src/theme/Navbar/Search/index.tsx b/www/apps/docs/src/theme/Navbar/Search/index.tsx new file mode 100644 index 0000000..a93dcda --- /dev/null +++ b/www/apps/docs/src/theme/Navbar/Search/index.tsx @@ -0,0 +1,10 @@ +import React from "react" +import clsx from "clsx" +import type { Props } from "@theme/Navbar/Search" + +export default function NavbarSearch({ + children, + className, +}: Props): JSX.Element { + return
{children}
+} diff --git a/www/apps/docs/src/theme/NavbarItem/NavbarNavLink.tsx b/www/apps/docs/src/theme/NavbarItem/NavbarNavLink.tsx new file mode 100644 index 0000000..a87c90e --- /dev/null +++ b/www/apps/docs/src/theme/NavbarItem/NavbarNavLink.tsx @@ -0,0 +1,55 @@ +import React from "react" +import Link from "@docusaurus/Link" +import useBaseUrl from "@docusaurus/useBaseUrl" +import { isRegexpStringMatch } from "@docusaurus/theme-common" +import type { Props } from "@theme/NavbarItem/NavbarNavLink" + +export default function NavbarNavLink({ + activeBasePath, + activeBaseRegex, + to, + href, + label, + html, + prependBaseUrlToHref, + ...props +}: Omit): JSX.Element { + // TODO all this seems hacky + // {to: 'version'} should probably be forbidden, in favor of {to: '/version'} + const toUrl = useBaseUrl(to) + const activeBaseUrl = useBaseUrl(activeBasePath) + const normalizedHref = useBaseUrl(href, { forcePrependBaseUrl: true }) + + // Link content is set through html XOR label + const linkContentProps = html + ? { dangerouslySetInnerHTML: { __html: html } } + : { + children: <>{label}, + } + + if (href) { + return ( + + ) + } + + return ( + { + return activeBaseRegex + ? isRegexpStringMatch(activeBaseRegex, location.pathname) + : location.pathname.startsWith(activeBaseUrl) + }, + })} + {...props} + {...linkContentProps} + /> + ) +} diff --git a/www/apps/docs/src/theme/NavbarItem/SearchNavbarItem.tsx b/www/apps/docs/src/theme/NavbarItem/SearchNavbarItem.tsx new file mode 100644 index 0000000..1618b18 --- /dev/null +++ b/www/apps/docs/src/theme/NavbarItem/SearchNavbarItem.tsx @@ -0,0 +1,17 @@ +import React from "react" +import NavbarSearch from "@theme/Navbar/Search" +import type { Props } from "@theme/NavbarItem/SearchNavbarItem" +import { SearchModalOpener } from "docs-ui" +import { useWindowSize } from "@docusaurus/theme-common" + +export default function SearchNavbarItem({ + mobile, +}: Props): JSX.Element | null { + const windowSize = useWindowSize() + + return ( + + + + ) +} diff --git a/www/apps/docs/src/theme/NotFound/Content/index.tsx b/www/apps/docs/src/theme/NotFound/Content/index.tsx new file mode 100644 index 0000000..67b276c --- /dev/null +++ b/www/apps/docs/src/theme/NotFound/Content/index.tsx @@ -0,0 +1,47 @@ +import React from "react" +import clsx from "clsx" +import Translate from "@docusaurus/Translate" +import type { Props } from "@theme/NotFound/Content" +import Heading from "@theme/Heading" +import Link from "@docusaurus/Link" + +export default function NotFoundContent({ className }: Props): JSX.Element { + return ( +
+
+
+ + + Page Not Found + + +

+ + Looks like the page you're looking for has either changed + into a different location or isn't in our documentation + anymore. + +

+

+ If you think this is a mistake, please{" "} + + report this issue on GitHub + +

+
+
+
+ ) +} diff --git a/www/apps/docs/src/theme/NotFound/index.tsx b/www/apps/docs/src/theme/NotFound/index.tsx new file mode 100644 index 0000000..bcd6d94 --- /dev/null +++ b/www/apps/docs/src/theme/NotFound/index.tsx @@ -0,0 +1,21 @@ +import React from "react" +import { translate } from "@docusaurus/Translate" +import { PageMetadata } from "@docusaurus/theme-common" +import Layout from "@theme/Layout" +import NotFoundContent from "@theme/NotFound/Content" +import DocsProviders from "../../providers/DocsProviders" + +export default function Index(): JSX.Element { + const title = translate({ + id: "theme.NotFound.title", + message: "Page Not Found", + }) + return ( + + + + + + + ) +} diff --git a/www/apps/docs/src/theme/SearchBar/index.tsx b/www/apps/docs/src/theme/SearchBar/index.tsx new file mode 100644 index 0000000..2edced1 --- /dev/null +++ b/www/apps/docs/src/theme/SearchBar/index.tsx @@ -0,0 +1,51 @@ +import React, { useEffect } from "react" +import SearchBar from "@theme-original/SearchBar" +import type SearchBarType from "@theme/SearchBar" +import type { WrapperProps } from "@docusaurus/types" +import useIsBrowser from "@docusaurus/useIsBrowser" +import { useLocation } from "@docusaurus/router" +import { useAnalytics } from "docs-ui" + +type Props = WrapperProps + +export default function SearchBarWrapper(props: Props): JSX.Element { + const isBrowser = useIsBrowser() + const location = useLocation() + const { track } = useAnalytics() + + useEffect(() => { + if (isBrowser) { + const trackSearch = (e) => { + if ( + !e.target.classList?.contains("DocSearch-Input") && + !( + e.target.tagName.toLowerCase() === "input" && + e.target.getAttribute("type") === "search" + ) + ) { + return + } + + const query = e.target.value + if (query.length >= 3) { + // send event to segment + track("search", { + query, + }) + } + } + + document.body.addEventListener("keyup", trackSearch) + + return () => { + document.body.removeEventListener("keyup", trackSearch) + } + } + }, [isBrowser, location.pathname]) + + return ( + <> + + + ) +} diff --git a/www/apps/docs/src/theme/SearchTranslations/index.ts b/www/apps/docs/src/theme/SearchTranslations/index.ts new file mode 100644 index 0000000..caee173 --- /dev/null +++ b/www/apps/docs/src/theme/SearchTranslations/index.ts @@ -0,0 +1,12 @@ +import { translate } from "@docusaurus/Translate" +import translations from "@theme-original/SearchTranslations" + +const changedTranslations = { + ...translations, + placeholder: translate({ + id: "theme.SearchModal.placeholder", + message: "Find something", + description: "The placeholder of the input of the DocSearch pop-up modal", + }), +} +export default changedTranslations diff --git a/www/apps/docs/src/theme/TOCItems/index.tsx b/www/apps/docs/src/theme/TOCItems/index.tsx new file mode 100644 index 0000000..2c86e1b --- /dev/null +++ b/www/apps/docs/src/theme/TOCItems/index.tsx @@ -0,0 +1,22 @@ +import React from "react" +import TOCItems from "@theme-original/TOCItems" +import type TOCItemsType from "@theme/TOCItems" +import type { WrapperProps } from "@docusaurus/types" +import { useDoc } from "@docusaurus/theme-common/internal" +import { DocContextValue } from "@medusajs/docs" +import StructuredDataHowTo from "../../components/StructuredData/HowTo" + +type Props = WrapperProps + +export default function TOCItemsWrapper(props: Props): JSX.Element { + const { frontMatter, contentTitle } = useDoc() as DocContextValue + + return ( + <> + + {frontMatter?.addHowToData && ( + + )} + + ) +} diff --git a/www/apps/docs/src/theme/Tabs/index.tsx b/www/apps/docs/src/theme/Tabs/index.tsx new file mode 100644 index 0000000..c216b71 --- /dev/null +++ b/www/apps/docs/src/theme/Tabs/index.tsx @@ -0,0 +1,280 @@ +import React, { + cloneElement, + useRef, + type ReactElement, + useEffect, + useState, +} from "react" +import clsx from "clsx" +import { + useScrollPositionBlocker, + useTabs, + sanitizeTabsChildren, + type TabItemProps, +} from "@docusaurus/theme-common/internal" +import useIsBrowser from "@docusaurus/useIsBrowser" +import type { Props as OldProps } from "@theme/Tabs" + +type TabsCustomProps = { + isCodeTabs?: boolean + codeTitle?: string +} + +type TabListProps = OldProps & ReturnType & TabsCustomProps + +type TabsComponentProp = TabsCustomProps & OldProps + +type TabsProps = { + wrapperClassName?: string + isCodeTabs?: boolean +} & OldProps + +function TabList({ + className, + selectedValue, + selectValue, + tabValues, + isCodeTabs = false, + codeTitle, +}: TabListProps) { + const tabRefs: (HTMLLIElement | null)[] = [] + const { blockElementScrollPositionUntilNextRender } = + useScrollPositionBlocker() + const codeTabSelectorRef = useRef(null) + const codeTabsWrapperRef = useRef(null) + const [tabsTitle, setTabsTitle] = useState(codeTitle) + + const handleTabChange = ( + event: + | React.FocusEvent + | React.MouseEvent + | React.KeyboardEvent + ) => { + const newTab = event.currentTarget + const newTabIndex = tabRefs.indexOf(newTab) + const newTabValue = tabValues[newTabIndex]!.value + + if (newTabValue !== selectedValue) { + blockElementScrollPositionUntilNextRender(newTab) + selectValue(newTabValue) + } + } + + const handleKeydown = (event: React.KeyboardEvent) => { + let focusElement: HTMLLIElement | null = null + + switch (event.key) { + case "Enter": { + handleTabChange(event) + break + } + case "ArrowRight": { + const nextTab = tabRefs.indexOf(event.currentTarget) + 1 + focusElement = tabRefs[nextTab] ?? tabRefs[0]! + break + } + case "ArrowLeft": { + const prevTab = tabRefs.indexOf(event.currentTarget) - 1 + focusElement = tabRefs[prevTab] ?? tabRefs[tabRefs.length - 1]! + break + } + default: + break + } + + focusElement?.focus() + } + + const changeTabSelectorCoordinates = (selectedTab) => { + if (!codeTabSelectorRef?.current || !codeTabsWrapperRef?.current) { + return + } + const selectedTabsCoordinates = selectedTab.getBoundingClientRect() + const tabsWrapperCoordinates = + codeTabsWrapperRef.current.getBoundingClientRect() + codeTabSelectorRef.current.style.left = `${ + selectedTabsCoordinates.left - tabsWrapperCoordinates.left + }px` + codeTabSelectorRef.current.style.width = `${selectedTabsCoordinates.width}px` + codeTabSelectorRef.current.style.height = `${selectedTabsCoordinates.height}px` + } + + useEffect(() => { + if (codeTabSelectorRef?.current && tabRefs.length) { + const selectedTab = tabRefs.find( + (tab) => tab.getAttribute("aria-selected") === "true" + ) + if (selectedTab) { + changeTabSelectorCoordinates(selectedTab) + } + } + }, [codeTabSelectorRef, tabRefs]) + + useEffect(() => { + const selectedTab = tabValues.find((tab) => tab.value === selectedValue) + if (selectedTab?.attributes?.title) { + setTabsTitle(selectedTab.attributes.title as string) + } else { + setTabsTitle(codeTitle) + } + }, [selectedValue]) + + return ( +
+
+ {isCodeTabs && ( + + )} +
    + {tabValues.map(({ value, label, attributes }) => ( +
  • tabRefs.push(tabControl)} + onKeyDown={handleKeydown} + onClick={handleTabChange} + {...attributes} + className={clsx( + isCodeTabs && [ + "text-compact-small-plus py-0.25 border border-solid border-transparent whitespace-nowrap rounded-full [&:not(:first-child)]:ml-0.25", + "z-[2] flex justify-center items-center", + selectedValue !== value && + "text-medusa-code-text-subtle hover:!bg-medusa-code-bg-base", + selectedValue === value && + "text-medusa-code-text-base border border-solid border-medusa-code-border bg-medusa-code-bg-base xs:!border-none xs:!bg-transparent", + attributes?.badge && + "[&_.badge]:ml-0.5 [&_.badge]:py-0.125 [&_.badge]:px-[6px] [&_.badge]:rounded-full pl-0.75 pr-0.25", + !attributes?.badge && "px-0.75", + ], + !isCodeTabs && [ + "[&:not(:last-child)]:mr-0.5 px-0.75 py-[6px] txt-compact-small-plus", + "border-0 rounded-full transition-shadow duration-200 ease-ease", + selectedValue === value && + "text-medusa-fg-base shadow-card-rest dark:shadow-card-rest-dark", + selectedValue !== value && + "text-medusa-fg-subtle hover:text-medusa-fg-base", + "flex gap-0.5", + ], + "!mt-0 cursor-pointer", + attributes?.className + )} + > + {label ?? value} +
  • + ))} +
+
+ {isCodeTabs && ( + + )} +
+ ) +} + +function TabContent({ + lazy, + children, + selectedValue, +}: OldProps & ReturnType) { + const childTabs = (Array.isArray(children) ? children : [children]).filter( + Boolean + ) as ReactElement[] + if (lazy) { + const selectedTabItem = childTabs.find( + (tabItem) => tabItem.props.value === selectedValue + ) + if (!selectedTabItem) { + // fail-safe or fail-fast? not sure what's best here + return null + } + return cloneElement(selectedTabItem) + } + return ( +
+ {childTabs.map((tabItem, i) => + cloneElement(tabItem, { + key: i, + hidden: tabItem.props.value !== selectedValue, + }) + )} +
+ ) +} + +function TabsComponent(props: TabsComponentProp): JSX.Element { + const tabs = useTabs(props) + return ( +
+ + +
+ ) +} + +function checkCodeTabs(props: TabsProps): boolean { + return props.groupId === "npm2yarn" || props.isCodeTabs +} + +export default function Tabs(props: TabsProps): JSX.Element { + const isBrowser = useIsBrowser() + + useEffect(() => { + if (!window.localStorage.getItem("docusaurus.tab.npm2yarn")) { + // set the default + window.localStorage.setItem("docusaurus.tab.npm2yarn", "yarn") + } + }, []) + + const isCodeTabs = checkCodeTabs(props) + + return ( +
+ + {sanitizeTabsChildren(props.children)} + +
+ ) +} diff --git a/www/apps/docs/src/types/global.d.ts b/www/apps/docs/src/types/global.d.ts new file mode 100644 index 0000000..3747492 --- /dev/null +++ b/www/apps/docs/src/types/global.d.ts @@ -0,0 +1,6 @@ +export declare global { + interface Window { + // eslint-disable-next-line @typescript-eslint/no-explicit-any + analytics?: any + } +} diff --git a/www/apps/docs/src/types/index.d.ts b/www/apps/docs/src/types/index.d.ts new file mode 100644 index 0000000..0ea506c --- /dev/null +++ b/www/apps/docs/src/types/index.d.ts @@ -0,0 +1,217 @@ +declare module "@theme/CodeBlock" { + import type { Props as DocusaurusProps } from "@theme/CodeBlock" + + export interface Props extends DocusaurusProps { + readonly noReport?: boolean + readonly noCopy?: boolean + } +} + +declare module "@theme/CodeBlock/Content/String" { + import type { Props as CodeBlockProps } from "@theme/CodeBlock" + + export interface Props extends Omit { + readonly children: string + readonly noReport?: boolean + readonly noCopy?: boolean + } + + export default function CodeBlockStringContent(props: Props): JSX.Element +} + +declare module "@medusajs/docs" { + import type { ThemeConfig as DocusaurusThemeConfig } from "@docusaurus/preset-classic" + import type { DocusaurusConfig } from "@docusaurus/types" + import type { + PropSidebarItemCategory, + PropSidebarItemLink, + PropSidebarItemHtml, + } from "@docusaurus/plugin-content-docs" + import { BadgeProps, ButtonType, ButtonVariants } from "docs-ui" + import { IconProps } from "@medusajs/icons/dist/types" + import { DocContextValue as DocusaurusDocContextValue } from "@docusaurus/theme-common/internal" + import { ReactNode } from "react" + import { NavbarLogo } from "@docusaurus/theme-common" + import type { DocusaurusContext } from "@docusaurus/types" + + type ItemCustomProps = { + customProps?: { + themedImage: { + light: string + dark?: string + } + image?: string + icon?: React.FC + iconName?: string + description?: string + className?: string + isSoon?: boolean + badge: BadgeProps + html?: string + sidebar_icon?: string + sidebar_is_title?: boolean + sidebar_is_soon?: boolean + sidebar_is_group_headline?: boolean + sidebar_is_group_divider?: boolean + sidebar_is_divider_line?: boolean + sidebar_is_back_link?: boolean + sidebar_badge?: BadgeProps + category_id?: string + } + } + + export declare type ModifiedPropSidebarItemCategory = + PropSidebarItemCategory & ItemCustomProps + + export declare type ModifiedPropSidebarItemLink = PropSidebarItemLink & + ItemCustomProps + + export declare type ModifiedPropSidebarItemHtml = PropSidebarItemHtml & + ItemCustomProps + + export declare type ModifiedSidebarItem = + | ModifiedPropSidebarItemCategory + | ModifiedPropSidebarItemLink + | ModifiedPropSidebarItemHtml + + export declare type ModifiedDocCardBase = { + type: string + href: string + icon: ReactNode | string + title: string + description?: string + html?: string + containerClassName?: string + isSoon?: boolean + badge?: BadgeProps + children?: React.ReactNode + } + + export declare type ModifiedDocCardItemLink = { + type: "link" + } & ModifiedDocCardBase & + ModifiedPropSidebarItemLink + + export declare type ModifiedDocCardItemCategory = { + type: "category" + } & ModifiedDocCardBase & + ModifiedPropSidebarItemCategory + + export declare type ModifiedDocCard = + | ModifiedDocCardItemLink + | ModifiedDocCardItemCategory + + export declare type SocialLink = { + href: string + type: string + } + + export declare type NavbarActionBase = { + type: string + title?: string + icon?: string + Icon?: React.ReactElement + className?: string + label?: string + html?: string + } + + export declare type NavbarActionLink = NavbarActionBase & { + type: "link" + href: string + } + + export declare type NavbarActionButton = NavbarActionBase & { + type: "button" + variant?: ButtonVariants + buttonType?: ButtonType + href?: string + events?: { + onClick?: MouseEventHandler + onMouseEnter?: MouseEventHandler + onMouseLeave?: MouseEventHandler + onMouseOver?: MouseEventHandler + } + } + + export declare type NavbarAction = NavbarActionLink | NavbarActionButton + + export declare type OptionType = { + value: string + label: string + isAllOption?: boolean + } + + export declare type ThemeConfig = { + reportCodeLinkPrefix?: string + footerFeedback: { + event: string + } + socialLinks?: SocialLink[] + cloudinaryConfig?: { + cloudName?: string + flags?: string[] + resize?: { + action: string + width?: number + height?: number + aspectRatio?: string + } + roundCorners?: number + } + navbarActions: NavbarAction[] + // resolve type errors + prism: { + magicComments: MagicCommentConfig[] + } + mobileLogo: NavbarLogo + algoliaConfig?: { + apiKey: string + indexNames: { + docs: string + api: string + } + appId: string + filters: OptionType[] + defaultFilters: string[] + defaultFiltersByPath: { + path: string + filters: string[] + }[] + } + analytics?: { + apiKey: string + } + } & DocusaurusThemeConfig + + export declare type MedusaDocusaurusConfig = { + themeConfig: ThemeConfig + } & DocusaurusConfig + + export declare type DocContextValue = { + frontMatter: { + addHowToData?: boolean + badge?: { + variant: string + text: string + } + } + } & DocusaurusDocContextValue + + export declare type MedusaDocusaurusContext = DocusaurusContext & { + siteConfig: MedusaDocusaurusConfig + } + + export declare type Diagram2Code = { + diagram: string + code: string + } + + export declare type Diagram2CodeSpec = { + [k: string]: Diagram2Code + } + + export declare type Diagram2CodeSpecs = { + [k: string]: Diagram2CodeSpec + } +} diff --git a/www/apps/docs/src/utils/createLatestReleaseRedirects.js b/www/apps/docs/src/utils/createLatestReleaseRedirects.js new file mode 100644 index 0000000..c5bd2fe --- /dev/null +++ b/www/apps/docs/src/utils/createLatestReleaseRedirects.js @@ -0,0 +1,63 @@ +const fetch = require('node-fetch'); + +/** + * A map of architectures to their corresponding file names and extensions. + * This makes it easy to add or change architectures in the future. + */ +const ARCHITECTURES = [ + { from: '/amd64', os: 'linux', arch: 'amd64', ext: 'tar.gz' }, + { from: '/arm64', os: 'linux', arch: 'arm64', ext: 'tar.gz' }, + { from: '/windows', os: 'windows', arch: 'amd64', ext: 'zip' }, + // Add other architectures here as needed +]; + +/** + * This function runs at build time to dynamically create redirects. + * It fetches the latest release tag from GitHub and constructs the download URLs. + */ +async function createLatestReleaseRedirects(ex) { + console.log('Fetching latest release tag from GitHub...'); + try { + // We use a HEAD request because we only need the final redirected URL, not the page content. + // This is much faster and more efficient. + const response = await fetch('https://github.com/fentas/b/releases/latest', { + method: 'HEAD', + }); + + // The 'response.url' property will contain the URL after all redirects. + // e.g., 'https://github.com/fentas/b/releases/tag/v2.3.0' + const latestUrl = response.url; + + // Extract the tag (e.g., 'v2.3.0') from the URL. + const tag = latestUrl.split('/').pop(); + + if (!tag || !tag.startsWith('v')) { + console.error(`Error: Could not parse a valid release tag from URL: ${latestUrl}`); + // Return an empty array to prevent build failure. + return []; + } + + console.log(`Successfully fetched latest release tag: ${tag}`); + + // Construct the base URL for downloads for the latest tag. + const downloadBaseUrl = `https://github.com/fentas/b/releases/download/${tag}`; + + // Create a redirect object for each architecture. + const redirects = ARCHITECTURES.map(({ from, os, arch, ext }) => { + return { + from: from, + to: `${downloadBaseUrl}/b-${os}-${arch}.${ext}`, + }; + }); + + console.log('Generated redirects:', redirects); + return redirects; + + } catch (error) { + console.error('Failed to fetch latest release from GitHub.', error); + // Return an empty array on error to ensure the Docusaurus build can complete. + return []; + } +} + +module.exports = createLatestReleaseRedirects \ No newline at end of file diff --git a/www/apps/docs/src/utils/decode-str.ts b/www/apps/docs/src/utils/decode-str.ts new file mode 100644 index 0000000..20e9cfe --- /dev/null +++ b/www/apps/docs/src/utils/decode-str.ts @@ -0,0 +1,8 @@ +export default function decodeStr(str: string) { + return str + .replaceAll("<", "<") + .replaceAll("{", "{") + .replaceAll("}", "}") + .replaceAll(">", ">") + .replaceAll("\\|", "|") +} diff --git a/www/apps/docs/src/utils/exclude-sidebar-results.js b/www/apps/docs/src/utils/exclude-sidebar-results.js new file mode 100644 index 0000000..4925583 --- /dev/null +++ b/www/apps/docs/src/utils/exclude-sidebar-results.js @@ -0,0 +1,17 @@ +function excludeSidebarResults(sidebarItems, categoryItem) { + const results = [] + sidebarItems.forEach((item) => { + if (item.type === "category") { + results.push({ + ...item, + items: excludeSidebarResults(item.items, categoryItem), + }) + } else if (!item.customProps?.exclude_from_auto_sidebar) { + return results.push(item) + } + }) + + return results +} + +module.exports = excludeSidebarResults diff --git a/www/apps/docs/src/utils/filter-list-items.ts b/www/apps/docs/src/utils/filter-list-items.ts new file mode 100644 index 0000000..f5d6407 --- /dev/null +++ b/www/apps/docs/src/utils/filter-list-items.ts @@ -0,0 +1,33 @@ +import { + PropSidebarItem, + PropSidebarItemLink, +} from "@docusaurus/plugin-content-docs" + +export default function filterListItems( + items: PropSidebarItemLink[], + pathPattern: string | RegExp +): PropSidebarItemLink[] { + if (!items.length) { + return items + } + + const pattern = new RegExp(pathPattern) + + return items.filter((item: PropSidebarItemLink) => pattern.test(item.href)) +} + +/** + * Flatting a sidebar list moving items from category + * to links + */ +export function flattenList(items: PropSidebarItem[]): PropSidebarItem[] { + const newItems = items.map((item: PropSidebarItem) => { + if (item.type !== "category") { + return item + } + + return item.items + }) + + return newItems.flat() +} diff --git a/www/apps/docs/src/utils/get-first-category-item.ts b/www/apps/docs/src/utils/get-first-category-item.ts new file mode 100644 index 0000000..4191064 --- /dev/null +++ b/www/apps/docs/src/utils/get-first-category-item.ts @@ -0,0 +1,25 @@ +import { + findSidebarCategory, + useDocsSidebar, +} from "@docusaurus/theme-common/internal" +import { PropSidebarItem } from "@docusaurus/plugin-content-docs" + +type Options = { + categoryLabel?: string + categoryCustomId?: string +} + +export function getCategoryItems({ categoryLabel, categoryCustomId }: Options) { + return findSidebarCategory( + useDocsSidebar().items, + (item) => + item.label === categoryLabel || + item.customProps.category_id === categoryCustomId + )?.items +} + +export default function getFirstCategoryItem( + options: Options +): PropSidebarItem | undefined { + return getCategoryItems(options)?.[0] +} diff --git a/www/apps/docs/src/utils/get-os-shortcut.ts b/www/apps/docs/src/utils/get-os-shortcut.ts new file mode 100644 index 0000000..7229c8b --- /dev/null +++ b/www/apps/docs/src/utils/get-os-shortcut.ts @@ -0,0 +1,8 @@ +export default function getOsShortcut() { + const isMacOs = + typeof navigator !== "undefined" + ? navigator.userAgent.toLowerCase().indexOf("mac") !== 0 + : true + + return isMacOs ? "⌘" : "Ctrl" +} diff --git a/www/apps/docs/src/utils/glossary.ts b/www/apps/docs/src/utils/glossary.ts new file mode 100644 index 0000000..8e2985e --- /dev/null +++ b/www/apps/docs/src/utils/glossary.ts @@ -0,0 +1,17 @@ +export type GlossaryType = { + matchTextRegex: RegExp + ignoreTextRegex?: RegExp + title: string + content: string + referenceLink: string +} + +const glossary: GlossaryType[] = [] + +export const getGlossary = () => [...glossary] + +export const getGlossaryByPath = (path: string): GlossaryType | undefined => { + return glossary.find( + (g) => g.matchTextRegex.test(path) && !g.ignoreTextRegex?.test(path) + ) +} diff --git a/www/apps/docs/src/utils/is-in-view.ts b/www/apps/docs/src/utils/is-in-view.ts new file mode 100644 index 0000000..67649a3 --- /dev/null +++ b/www/apps/docs/src/utils/is-in-view.ts @@ -0,0 +1,10 @@ +export default function isInView(element: Element): boolean { + const rect = element.getBoundingClientRect() + return ( + rect.top >= 0 && + rect.left >= 0 && + rect.bottom <= + (window.innerHeight || document.documentElement.clientHeight) && + rect.right <= (window.innerWidth || document.documentElement.clientWidth) + ) +} diff --git a/www/apps/docs/src/utils/reverse-sidebar.js b/www/apps/docs/src/utils/reverse-sidebar.js new file mode 100644 index 0000000..4d3b6c7 --- /dev/null +++ b/www/apps/docs/src/utils/reverse-sidebar.js @@ -0,0 +1,27 @@ +function reverseSidebarItems(sidebarItems, categoryItem) { + let result = sidebarItems + if (categoryItem.customProps?.reverse) { + // Reverse items in categories + result = result.map((item) => { + if (item.type === "category") { + return { ...item, items: reverseSidebarItems(item.items, categoryItem) } + } + return item + }) + // Reverse items at current level + // use localeCompare since the reverse array method doesn't account for + // numeric strings + result.sort((a, b) => { + const aToCompare = a.id || a.href || a.value || "" + const bToCompare = b.id || b.href || b.value || "" + const comparison = aToCompare.localeCompare(bToCompare, undefined, { + numeric: true, + }) + + return comparison < 0 ? 1 : comparison > 0 ? -1 : 0 + }) + } + return result +} + +export default reverseSidebarItems diff --git a/www/apps/docs/src/utils/specs.ts b/www/apps/docs/src/utils/specs.ts new file mode 100644 index 0000000..c148667 --- /dev/null +++ b/www/apps/docs/src/utils/specs.ts @@ -0,0 +1 @@ +export const specs = {} diff --git a/www/apps/docs/static/.nojekyll b/www/apps/docs/static/.nojekyll new file mode 100644 index 0000000..e69de29 diff --git a/www/apps/docs/static/android-chrome-192x192.png b/www/apps/docs/static/android-chrome-192x192.png new file mode 100644 index 0000000000000000000000000000000000000000..96eb6c23731b916d14b3c9bedbef7775daf2e722 GIT binary patch literal 9351 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 N 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 literal 0 HcmV?d00001 diff --git a/www/apps/docs/static/apple-touch-icon.png b/www/apps/docs/static/apple-touch-icon.png new file mode 100644 index 0000000000000000000000000000000000000000..f8bcfc2ec23b844cab97685594082af9d78fbdd9 GIT binary patch literal 8527 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 JPDHLkV1n+EVF>^L literal 0 HcmV?d00001 diff --git a/www/apps/docs/static/favicon.ico b/www/apps/docs/static/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..d636b882f84ef24a43966d7e091918b558f473ef GIT binary patch literal 8254 zcmeHKO=uHA6i$m!@uv#n&q;%*R1ie)P;Z{BdJ}0j6};)eL!lSDvsJnULCxkMR747v zSlZnUMXxG|sE8NsMNy=BP!TP$B)gmbWMk3sO`50MF*`|2@#3V+zM1#FpUvCtOdE+b z!A~?AfloBj25}S2+DfZPfsn1z%_aL_#C#)XSVDm5>p9gFq$mQ#`u7euVpU`|-+f}W1j(Khy{2mm8 zy{pCvs|PhobCaaQu$XsE^$f@Rfwg)gr^EJ>4|H5zC(?m);8l?4Sn3sq?=p(VPZ<7A z5tpw8b%Jvzt?tc_Xd4ip9n)LqV7~|NPeGh(lLgPzj>e6mq8L7nCH%S0i!&RMS1m5l z!oBx*oP_$_@_11R3uj@9c`)zNNcy*RoiQCdUp zeX3`@VthNLB>j73@B5U}Cgj!=!~9W0*Y#$4r@MvyErvPpER=m|ELoVynEf4~^BC*( z#4!JpNxE7wiYfHrW6UU=R}%B>@cvz88jhv))Z>fTFn`6EC%h-zPZn}hUxo%&eH}l$ zh2zfT(tUeSm+^5fik!x;^G`_>cgGAr1Ac?b<@q=p4~B0ZaxKk<@to(eb#|<`9laPI z=c35#h_I~YS!%y)tEYJ$Tjwq90P=Gq>Q^@*`*#5_P1n0!`aPL~YPf_IWUxXFaU~d`%tpfZ0A{<{^ zE`MIP*7g7HkN;a^thH|vCp#cJAUhyCAUhyCAUhyCAUhyCAUhyCAUhyCAUja013v)( C9$?u3 literal 0 HcmV?d00001 diff --git a/www/apps/docs/static/icon.svg b/www/apps/docs/static/icon.svg new file mode 100644 index 0000000..b6a3820 --- /dev/null +++ b/www/apps/docs/static/icon.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/www/apps/docs/static/img/.bak/admin-icon-dark.svg b/www/apps/docs/static/img/.bak/admin-icon-dark.svg new file mode 100644 index 0000000..b8b63d4 --- /dev/null +++ b/www/apps/docs/static/img/.bak/admin-icon-dark.svg @@ -0,0 +1,3 @@ + + + diff --git a/www/apps/docs/static/img/.bak/admin-icon.svg b/www/apps/docs/static/img/.bak/admin-icon.svg new file mode 100644 index 0000000..48a2194 --- /dev/null +++ b/www/apps/docs/static/img/.bak/admin-icon.svg @@ -0,0 +1,3 @@ + + + diff --git a/www/apps/docs/static/img/.bak/announcement-bg.svg b/www/apps/docs/static/img/.bak/announcement-bg.svg new file mode 100644 index 0000000..e74f491 --- /dev/null +++ b/www/apps/docs/static/img/.bak/announcement-bg.svg @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + diff --git a/www/apps/docs/static/img/.bak/bell-dark.png b/www/apps/docs/static/img/.bak/bell-dark.png new file mode 100644 index 0000000000000000000000000000000000000000..2ec20b343593b85c269baefdd0939d2c34e5b36e GIT binary patch literal 1540 zcmeAS@N?(olHy`uVBq!ia0vp^${@_a1|;QfZjJ;}Ea{HEjtmSN`?>!lvI6-E$sR$z z3=CCj3=9n|3=F@3LJcn%7)lKo7+xhXFj&oCU=S~uvn$XBDAAG{;hE;^%b*2hb1<+n z3NbJPS&Tr)z$nE4G7ZRL@M4sPvx68lplX;H7}_%#SfFa6fHVk90Ai3H2+h2J5n0+>{umUo3Q%e#RDspr3imfVamB1>jfNYSkzLEl1NlCV?QiN}Sf^&XRs)CuG zfu4bq9hZWFf=y9MnpKdC8&o@xXRDM^Qc_^0uU}qXu2*iXmtT~wZ)j<0sc&GUZ)Btk zRH0j3nOBlnp_^B%3^4>|j!SBBa#3bMNoIbY0?6FNr2NtnTO}osMQ{LdXGvxn!lt}p zsJDO~)CbAv8|oS8!_5Y2wE>A*`4?rT0&NDFZ)a!&R*518wZ}#uWI2*!AU*|)0=;U- zWup%dHajlKxQFZv49u;bE{-7)oNs6B4Z7_haQts5)8aji6-^zJ7IwV2#5#|mf{CZi zYT2R(htCNgd3h<(p3#q0wvKs@6#dn?d^hiiPyyV2WIpz7~`QO*?omx_~ z@(X|9P7d$Aar_&2Z@(=Id7^AvSGP9ovub>N{ONjyogE*(f8gii=l>l!KgOWfEm`=u znX;9Y)vWV+N(m8b!|WG{C+H{38@<1O_wLue{(fu8=*}C{U(~#bzA^RiC1!(NK|-01 zoveb~IubdI+r*Xyd=u2zwR2}=+3MYU_tr-0O|MTeEV2+qA5? zVmH+ z)MT-yg^!EHQ5t)rITO1`F(uge-@JL#+-lnmV}ta|_vg6pFHX9C`C`4QMeVQR{QCO;F+X!s?>u=W>(F{9RK9@k z!M^PI4sx5edB4dI4-b!(-Eb#jXF?47NzY{V4(%S(mkT-`sxqgYRGHv=CGpFTI;jaZ zPI^lw9++{p;gb6uSEKl+*_*R-^vcgWg_wSS^XQkfWvRL3Q)Qc?oQ2BEUAC3o)ksTA zV{@zP>JODl4Z9&;%2xC zOcVROUQFgKe;fSi#?-(APmF(jPCm%Eed2fhBgxsv-p;g`HmTt1=a41yh4=L5CdMdq veO_~F2g8erKhDel4Q#PHWoI38fB6%83%*cY6~P0GL1mk#tDnm{r-UW|qg6~% literal 0 HcmV?d00001 diff --git a/www/apps/docs/static/img/.bak/cart-icon-dark.svg b/www/apps/docs/static/img/.bak/cart-icon-dark.svg new file mode 100644 index 0000000..7c2ef9b --- /dev/null +++ b/www/apps/docs/static/img/.bak/cart-icon-dark.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/www/apps/docs/static/img/.bak/cart-icon.svg b/www/apps/docs/static/img/.bak/cart-icon.svg new file mode 100644 index 0000000..98ac450 --- /dev/null +++ b/www/apps/docs/static/img/.bak/cart-icon.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/www/apps/docs/static/img/.bak/dev-env-icon-dark.svg b/www/apps/docs/static/img/.bak/dev-env-icon-dark.svg new file mode 100644 index 0000000..caad3c7 --- /dev/null +++ b/www/apps/docs/static/img/.bak/dev-env-icon-dark.svg @@ -0,0 +1,3 @@ + + + diff --git a/www/apps/docs/static/img/.bak/dev-env-icon.svg b/www/apps/docs/static/img/.bak/dev-env-icon.svg new file mode 100644 index 0000000..149d9df --- /dev/null +++ b/www/apps/docs/static/img/.bak/dev-env-icon.svg @@ -0,0 +1,3 @@ + + + diff --git a/www/apps/docs/static/img/.bak/docs-meta.jpg b/www/apps/docs/static/img/.bak/docs-meta.jpg new file mode 100644 index 0000000000000000000000000000000000000000..33e20116c7f84600cf90002e9babda68ea10b3c0 GIT binary patch literal 260101 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

i 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%0AAOSq{y+FDE0D6wV-JLd5uT!iwh+T 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∋;Xj3+yB4bvV<$ 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 + + + + + + + diff --git a/www/apps/docs/static/img/.bak/fast-delivery-icon.svg b/www/apps/docs/static/img/.bak/fast-delivery-icon.svg new file mode 100644 index 0000000..b538501 --- /dev/null +++ b/www/apps/docs/static/img/.bak/fast-delivery-icon.svg @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/www/apps/docs/static/img/.bak/favicon.ico b/www/apps/docs/static/img/.bak/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..bebbf17e40c11dec45b5382f0bcf9d84b6bab58f GIT binary patch literal 103548 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 literal 0 HcmV?d00001 diff --git a/www/apps/docs/static/img/.bak/gatsby-icon-dark.svg b/www/apps/docs/static/img/.bak/gatsby-icon-dark.svg new file mode 100644 index 0000000..92a8c31 --- /dev/null +++ b/www/apps/docs/static/img/.bak/gatsby-icon-dark.svg @@ -0,0 +1,3 @@ + + + diff --git a/www/apps/docs/static/img/.bak/gatsby-icon.svg b/www/apps/docs/static/img/.bak/gatsby-icon.svg new file mode 100644 index 0000000..0017f78 --- /dev/null +++ b/www/apps/docs/static/img/.bak/gatsby-icon.svg @@ -0,0 +1,3 @@ + + + diff --git a/www/apps/docs/static/img/.bak/learning-path-img.png b/www/apps/docs/static/img/.bak/learning-path-img.png new file mode 100644 index 0000000000000000000000000000000000000000..1536b3170f444a463c1eae83131754d92941dad2 GIT binary patch literal 1842 zcmV-22hI42P)TeoiC zs$tk9*|uBaESP1&xL*h{3x*Gh z@Uehy2+(P?<^|^m7-Pjg;Cg~yV9>xs2b_qh)BF_471$j0 z$}-)hpdQL*Qu{_p_ED9V)bhM9NVjFdZ>k zt*`%PrBkzr0Dy=nk&6^T5$a-k#@K?29>BybI?Pn*@n+Loo+xDZ^kOl3J8auIND{Nk zdl*wbWXM9#hQSmV*)Q8n_eowgW*BXL)|O!rp0G%HRqJ`7=b~3G*>%!A%7SZa^*O=V zhe5zm$XQx}UJ2H-d_r3e=-mVTkw*;D)*a)5qrUDUkw{R3?VFs;9_j;Fb=_$r;73Vd z+V_1V$Qs#fhU$a@f*##sfT9qv_W!tJ0s})PMF`jgE(ii7lS$cC<9=&r=#OT|m%6dLOjw?VX z*MJ)*`uoX>Q__lRlSu2~3emGi0(|->@9Q_rl#0J?6l^n{vKjt3 zpTWv;AA5ItNRVr#Qkiggp2`8!w(SzvzSn9skffb7bGgnts1RN|yM#|}!-f2uE|jqm?+8jrri&Z9{fldMsg$c((H}|iW!E-cbP-w zc=cYZk6#+5 zTB}j2m+bb@fnUi*V`06%2G`Mf;7}TQG}3i<{JHOn`1xECuisI}+%9+Uj4DCSAxEFu zb_c6W=CeDs$MPi#+bZSC=OP&ZR&AROD#m=+Znj!fyw2xi*qJw^0mqHVSnth4x8Gn1 z^8Exd>2!BqhQky2+>0?C+KMvmFRDWmeLC`4d9pKxsE_mwbxDEPu~5sk&&KU8d4hD@ zhT0@5lOo^a9@`_WC%HQxFq!{zE*4d%bXY5c@N!7bB~vj~!asp-n@7fkZqpxc3$}T~ zF?Gxosz^S0CeD$r@DN5o7ejCuV3y8OXESLHjrB3c?a_aO6>Uc?+IKvT+^+r)w8pA=7>n!DSmb|sCVFMaJw4;4RlA!Bg zgQ=VS>G(8*mONGy7`Eh-#iqsp7M*ERRHXwy{k%}331$SNMUyFWuPT0((xz{Ls- gQJyLkmaz%?7w$G#tZk@#%m4rY07*qoM6N<$f>aKL`~Uy| literal 0 HcmV?d00001 diff --git a/www/apps/docs/static/img/.bak/light-beam.png b/www/apps/docs/static/img/.bak/light-beam.png new file mode 100644 index 0000000000000000000000000000000000000000..e1c07d07af59f87324155b8979a6899031d27e0d GIT binary patch literal 34642 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%0A=m~4mmy)xQ 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 IM6N<$f;Xy$!~g&Q literal 0 HcmV?d00001 diff --git a/www/apps/docs/static/img/.bak/link-icon-light.svg b/www/apps/docs/static/img/.bak/link-icon-light.svg new file mode 100644 index 0000000..d8c0811 --- /dev/null +++ b/www/apps/docs/static/img/.bak/link-icon-light.svg @@ -0,0 +1,4 @@ + + + + diff --git a/www/apps/docs/static/img/.bak/link-icon.svg b/www/apps/docs/static/img/.bak/link-icon.svg new file mode 100644 index 0000000..1a29eba --- /dev/null +++ b/www/apps/docs/static/img/.bak/link-icon.svg @@ -0,0 +1,4 @@ + + + + diff --git a/www/apps/docs/static/img/.bak/logo-icon-dark.png b/www/apps/docs/static/img/.bak/logo-icon-dark.png new file mode 100644 index 0000000000000000000000000000000000000000..1d155bd664da993ea89e3ede81c82f63952e3b31 GIT binary patch literal 570 zcmV-A0>%A_P)gOCa|6=(;h1MC1hFsT4ifu@4ZUSLK>5$^2~_~LJ7hhex| z-u<0-2i%z$5lJ-G8ikxWXl&g#OojeD*2twFS0=_-=+9<#kFjk3U8w%xRpTgj3XK#) zBh@@BWH<_q1ws-3d1fUO>#$4sa55}eaZ4E=KapB+F4Hl;)DyJ`Ec6kB$rtPH_Re%2O}!d)jctFSb_VxCqmdWg;{|= z2#3nS3Or(DSb;AH=ZPuI3XFX==N_m=vI3pB1&l~#QmF=7wwYx>FLJ&Q*8+XE5GQU6 z5^dBPyi2+g_zgei;%V1wv)~%!dszDFO2*o)LMlsj%WkC-Xt&x7YYv;)+~aHp+)9l> zE(r7)R)?V%ha`ayT5u)fvjT%u^JfhHjt#IN)xq7@30trq+%JRh($07*qo IM6N<$f&#Mbs{jB1 literal 0 HcmV?d00001 diff --git a/www/apps/docs/static/img/.bak/logo-icon.png b/www/apps/docs/static/img/.bak/logo-icon.png new file mode 100644 index 0000000000000000000000000000000000000000..40efd0a95805a6e25efd21c78238032733f462a4 GIT binary patch literal 921 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 A!2kdN literal 0 HcmV?d00001 diff --git a/www/apps/docs/static/img/.bak/logo-mobile.png b/www/apps/docs/static/img/.bak/logo-mobile.png new file mode 100644 index 0000000000000000000000000000000000000000..4dea6521bdac9276f64cbe778f14a5b247208aec GIT binary patch literal 8186 zcma)hby!qi)GnozzziuR3=G|kC^ggoLya_ubT`r+Dka_BNK3bbgunnlLP~N#I;0T> z`G)V_|L@(;b7HUc?zPuGd!KXG+HaJmx)Koq4FLuQ29YvU9*%*5MT));!F!56n>-6y zMPKk;p#~lp7?doJ2c|L{{0A+>^nfctFls00_Rtj^8(B4342=4CLX_DP3=D>NWqDa` zAIziN9&hsDv|$&|NxaZCe`mtGobhGUleETkUpz5L1Yg4qVeg`|CAl+>Wj5#^7UQp2 zw-##m7V0C!P8XXmHzti;*@5#)Rw4k)uA{1|vr1_#o-nBn%eLI13zR##XbA;u~@ALP6IJd!g{vOiWQzZ0}xGKtd7 z`#juZ^XOBE#%^^208yq}7j~1)Ynf+RKd%b>)R$)jmg5_lnd)CsQN8(P%rg-++cQRbIGP0vp z##UjJq^F;=X;aRbE2WA1Q)8p@c8j}*aWLAZ2j-o>aUQsj$6uwL;Yqa_%9Asa;+o-F zO-yna13@L$ls@F|jQlOarO|GMa4Bj+Aj{8BN5{(%w>pG9`v+h ztVaVP&;tV2RNn{u33^bwLqpa-<1_RC1#o217S=ic>qtltj|~5QKd&@e3}IC=(VZA7aeHMfGlG9xhgf)bzwDw@#?d?S5 z2B1jrr(!tn`Phk#fgz*!hY1`@yZKG`FBhvJnzdY(`L1{bAfYXAwg*t&r9$30;gXgq*(0@5EHsZO=9|5WiyjT{Uu!=qpW z0c&dSp8==nm{^hD!*?E?!BMmWfvBk|X5_GlzGExbsi9>uGAX2_qIOBv+}1pxy=FII za@Wxvf;35RaG;~ylmL}RL&y7)6nZHT*ZkEN_QX}rQWm>~R# z%HfU3kmb?g&R+_vDA}(6SpNoGRkz$}1#^+hf(QXZ4~L5ic2o-qOTKAKOQ_6$KO+

LG%+gA)HE6kG-=Ajkm)UC~+8z}i-5{@4T%X=S%ny!nVEgwicuM$e=eA=Fu ziV8ohos~8@X4@1Yl?XB-cgshnRxJoZI3Y~m+&sd|jFlK&=JdE)`DnSX8a@0;IZCrk z%Rb%uxWpJj)QuKp_OdK;mYjDCN+Jv5E{d~$p%M#167*v=KvSAM6R@6D=Z1HxxhxvA zl^+%a{5M@RDxINJPmLP3O{v}h0qxVRWt%I%q{c>(Jy0sJuRHGmgM5nyM>g}0p;O!pZJU%a9Wp#hZ+dL%6o&iNnQSv9zQ z+5k6l61{xO=gsO0SyiW_GzpO4q{t|tw1SSWrvOfuyY{dw{4cM=sSb)HS9!yv3sA6H zb0i$pxA6?YZ4>AZ=O^gV9at&6a3YY0@$aR`Xu%1JHOf6H%(BnijszG=`O^v{c=*ei zu&BM$X?}e=9EmmkIycCv+Zuk2t04!IG~HxXamJv;!@s0&o^;&Ei|von!c&3aoW{!7 z`KPEr{obp-Lp^O_8u&sxkK8J{7Vn$q0GsO(MjhB#>eRP6L1$IlR7}4K5IG7^P*$$?bI0|ex423 z$$w|>K>`lM@Ks1(dCkiNZaiUwCS;v*NS~*gX;t%Wc?V_L^ht($jWOY&lFsYzCf+8I zD~?{g{HHK&mLFg=tt!-5zs6zy z0!S7R=%i`~@%7Yz1_3OJg6GNu#HHB4clVZ(@kOD)_Uno(6p8(p%y+fy_eCuSrr8&c z*_@{1-zt~7#qAubFZtu_EPrK#l^^I!>8=sxmAFX~UC{^f8Z5HpD`n9?y61Ij_(Tb7 zX|g^_XV$8F^FCWo!_g!sLFh>@%`O$VS^src`Q6#LP~ts*xv9|imlq$8E0tZ-ek^iU zsg~*TP(L@o3};~RYP?ZcHIRwHql7#%XWIN=q|{(&)SBx8n#ORnQbY`_3$O}kuB6D< z!}|~%aFNRzhK$2Mzm)o|*(LO)xiEuA!qqoU3Vji`UK)LaN-PqQvF<4 ztDVv8oUT|r2tHIPR+p^9^3BpRZ&5F1Rl6ViUTwYI1zROZP4d|GS1Ahei%Pa$vuu;8IkZYizDsFZ+E< zwS(qz+22Hj8Y*lV8jX|ukqsQXzi<6=J5j68Ir%_mI2vz+1R3&-JZ_imEX07$`>a^{ zxPx0zP+%eB1+IPt!;er-SzCB{smkTT-qb3#m_T2+%AU{L50N;|{t^)0exP{~^{6ft zMdchrhiy31`S&qyp9+9AzK_?d zE8P*ADIvn}VdgDe7(kR5Gbs`GQ2(Dk46%*7HUi+2zEA)Ax_Q@LWImd*>^U9``e&>_ z!;TwAH)k6C5~7etDdW@*Ho6WpVT1z_50meW@>9y<+C{~e%Hk|)NDJ5v zjya6>5EnbIEBrg-7JI$h;$HLqCXCZ_6s$@ah3mNHen0)jX0<}wc$nctSgtXmb1WGN z43HVDJY;3AFdRAKHa|+qs8|wf+Zl+6T$7NRu?j?DVHSe$qqwE7dK_$DEWWi!hvO*h zv-pBZW72+ocs9b!JHL^D8ZV9LlJ0x|wEWIQu=hPA8Ga%?*ywtTlX;lCY*2ug8~|T3 zO=M&@OPbT|ji}Ts)5tVikDCs69lNf7ld4qNb zNqFAhxWtC=HsVMHmj^&S z*Db?-Ck@|@ep^#_9v|Rp?`V_}NO8|(gA0}AsZ0Pz&XF@Km{Kemh&106?>|3woSPExP+kv3w05gKS`hU80=Hjzjti-?(pAqw=cX{3W+stV9Ki zC|5j<%N)JBw)|;4)|P;$yd_npotF1v8YmK`4-%OQ3GwD!{q;VLTm6CVSGz3HcwE46 zY<_yM0BvUC$;&UYy3#^vf)%|}Hxm_nV>m<8HA;c*n7wbeW| zwFeH2rQ*K`T&E!-^|8`tE6JR&VT}qW2Q^nPf00x$ml3Rj!2Cn(OGp-qCWCJ8$cN=N zvujpz15@=s-kI?5?|~JI4P;uvTN%N72mdC}L8oG9BG}HIUur?K`dhL-=eg4KyX;fc zolFBI`T}5tBEy`2BycZ7w#cBNFBM*F-(+zUdq+`8jdm@u*s%p(a zzjnV$p^&omWVKwsF5QLaK}C&;wlLLQmtB+mWlP&tN!AI1|X<_N27BC0@8g$Ny$R=`k`(f?EMfSwr>ucI3O@2 z6A{>toVS2Rt!wR*?7vX0*QcP+xVkYIDJ;=G&nEN8&8*a%eP$d>XC$l}b>~Saa)(OM zNBPVg9tsJ4aH*5$n#^j@URZj0yPIfmBbM^^D6keZL}L;0!37Ay0Xo{DzEfjj5SUS} z|6aIk;G8A)ii~%Sgw@4n-efn28FMJM0H{P%?eq5JIHIZQmM{EEF6hid`R5XpS}@+J z4l+~$hAM~#bBTP~0iU%O3q;etGZnVEhS=?`t$a+7@k1E`_2e8x)X7~&6XA^u(u|WA zcWc$OgaZy19Dn|GW;6ZR&mRjptv7>XHoN{-$FAp0w>SQ)X@?GE{M+|#NJtw7Q&5an=`ZF{fyjNnRieueq(_zS3jRyqQgCl^B73qA_ znQqUX%|^)8qWCKWL{*wifm>DE?)J1s+2+?*UCZ8zBhZ{0MMjQ>8-a6~8 zmo_$p@Mq9Fakp+Ba|KpaZK`IjSTD|8z&J}kCR((6=1k!ZX6VHSf$Y{TqHzaq8V<{OYfp#Wp%IAK`^;8?PO9{9d zO=_yWU5zC;GW1Y{%t&gpt;9ZHDru<8(p~KQ_#;o4a+sxdC?jwDq9Ic-l)%ew?m(sD zl?cyQevMS^MUDS z{k}Gs1(e2KyNSpqD7ud*q^*+1m`S$*KNwJ3h@}{JDbqpJsCwEqlv&=9Chb*NC#P=< z_x=)+z)x_kvMt}nL0^fr2eMg^c z|NBoEU-0LC&qzBobS9|_`d&}ce<}`Ac0sk&kK-SF+~%XY){Y{*98^xKePKjyRv3Tv zVh5eO{5@UOQ&DJDd+<|C<@T};;CbB#(s3M%{~j+dPXSv?^m;?Iw<)IrP34vwzgb)~ zUuDFwXOf=yq)l@fUI&(_S?B*N(0I+HK~+RUZqK5SS_#6_=H_n#M}FlGGZ*Tq?Ws#T zv`=*P?6S$E0%{4#TD3U7U!TWWrYQ(gWd6ilFc+^%w9&~Ms?Ad}{ik5!7LN^4eD%g2 zk2h0xrYm@*HPR7*H3J@^U>vD+FLg-__k>i=np}0LCP5lyqzj1w`q7Rr-mh}ju8C13uW*85#<_@L|Pa8k*z zuKEQFt7C7DsuccUwx_fD(hq!7%9688sm1)x<|AKq`H0!_b*S_oE?sHH`*HpIQ68j7 zir?;(a4|8!bgI_bkY$@g!|XH0=k<=SDpQ63sMcn;*H(jr|Lh(L2<4kY6r8P1tnZuR zZUEHh(R(0~XPpBvQ2x$O{)~|NabNZ0_PDbhw$MDOyLsQ(-{s3Um7q5Vs0FV-I0pBP zwW06WJjm=-FoYux`YX%-daTuBH}np0iRE)yV2VFv!LFnb|IO5!1auvrLpe9gw-U*& ziJE29dHY&Y1{Aln6s}0Fjk0$pmd`H^uMbGcl1yU_6@AqmZN>Hur47u#SPjgqcDCj& zt{A;pvtiZ5*dO4ncBTMWL4w|jHlHX&R{ULeeQ2h}rplTeeC8CPI5-#}oW(HX5h8ZD zjZHoD{Hn&)XD&6@71@4X=Cf1U!R=!Zj8Z{O&@o~Wkle3QR z`c?|pfz2bY@9wOV|5e6WbfyzV&5brqu)W}Dq!GUYIn=W4mOrnNWd2XIII&8npOJOH zyrHc_UEBOaLT-V8NKYA4Or^mO%Z9p!jGe@w-Pe30J9^v?bZc$x0#n0-OGeCz?qu4? zCHKYdY=vDdT4y@+XL^&!H=iW*khElsFd|}m>|IaDmcDr$XDoF+B*X1mg+e*w_m5IY z(V+nI3BPphOukX-4DqV7IVD~c7h-uiKatDYO(gK3NZ@)|@wq2BTTj30jSi)XPlQ095e{oRub!6$zneh3o&b_sw{C%^u zlF%m+1NEgCl(`x{J&lMN5K>#X*_&a(Nh3($(<(?!+9VDOT?y4hG<39zaGh_ID( z3inmeiyzqxjNRJ*zIyz}V}eNbYcc`tzfreCIifi#94l!8*sa=g+a0x?hn^XPixb2C zrSX0|Oj&B*?4lS(9G}SHT83q+Q3fU0dODQ-jt?IOGlUNNks1WuyR3DVepOGpG29yD zWOVwBD5_R|pv-+~KMZ8cX~cP>G9LH2V<6mjdqTNPa(ptA8t0YDX58v(~FcUz1iU$<{FkCvkGzO3YuGuyO)L7!+4J;jPZ|zSJJl zw&@@0U%Z`;@cl>01hRLfYKqqztHYA?ad#x17i*OycS;u>q?l z`Jb<1;r3(PFR&{WRlI;jLZ>|EcmKKnDz~h%EYqfbkx>@8z?w%&54*PdZuU;#Tzvf5 zx#NR}Q=`E$VS84r>b})r2fSjhjs*4)(7Quv^XpSZt{-1|hbR-TZ(NI1*V9irvRGq= zL`@Q(Qj%C)e`mfpl4K7&?iRUG_}SExJYxHa`8KMSU+7H-&2$oz0c+=f<)tOpOszxs z6j&wU+i;M8*6ouI;Y7q$2MAXncwdLKP?M1f5{aaPVCgqadvpAOZwT&f&o9PsDKi{P z>e4HNjHwbQ(hXsI%sj`Fu~^m;wBAoD$QkLm)AN@SR6If}$`=Llo5j?gnniPM3h#?l zM|&@Bt>8hh5d51WdK>CpUOQeZ#%s1)PU=9_Sb?#Zxu*J0)7AuqXr8Q;XSR&$TGr4p z(lZjCL)jHT#M9au=kq#owGXlY7_^h8mT{6v-`fUVb7;?Asi!cQ<=hG za2*r}l7({fS||Ngro5AoAHYXyxV(X}`%jljCVK`UuCwCUG(QLB)x+qHR*4n)qxq$l zJf%n-EI3o_RbiG}nI9lUWSEkQnm{S6wXeM(Oal$A4oDLqYyhkH>`Fk{L%yXXF~efnxo|1mr^Vw zPe+#`OL~bK!S#QS4rvW$TDP0!Czi9W%h=XPZkpzY**&e)+6%-5Pp9o0=ntUW4&#>5 zB4lYeDT|ZN&!edMjlxg-tERB6E5-PKsUw<1UakhhhPT(M9A3M8|(H4E@+<^+P8b?_r*6Ly9K=Of$+k z)W>f>KStj4+Jf`nIry_+YL)c3j4r`H&a@;e9Sn>#b~|%Rv4j&IAWL#R(&37ppfIgv z4|GsyUyt?cc|y05$AOvR3m_(lGH1`{+ADXmCPSg$MDzWm&DCqoP(Tf^vg9siEFDt2 zDUs2h7Gc6ks;Zx<9IDzi56t}f18?`|mKp4{H(*DpGV4Dmq5;^Q;FCL(yOh!2>+P?> z%~N%Ix`UK-tofjcRbb=P^g*-Y)la#*LZ)A4okmE#d_f`3(yR5X611yaYKjGuvuIIXJ%1M=i+H$NS7 zAJije=u8rdy(BN=1G=u){+AhoS%E;VK{vt6Jy(L}m#IMVni93QlwdN0+KZm^4Tc9* zv{{*TA0TPko{uHYV9b|bIeWv%j1bQvI_klFlc2V{e0RP__G%ZS`R5n=!U7dBg9Ielc$+1kFVCJimJUi7`IafC{4N+kz_LHzId2mXdjjlNH&iqTR)gW*p5w+a=IC zjNX@7KvECn&+P2f$}CTM4y7tvu7TE(J`WQrv#`Ox$d~w+H z(Dzmfy0Of&e^pw$lb=DqgQ`Q>p44iqJTj7|QFd>kIgAx8oq6T45~8s-i{E;Y8*#j%&bf3vv(<}W3KVvvT9dS0^*Q7I+HVFkAwGIae$#yesl$LII< zQ;r~cqG62;+GaVUn!WI{aw*3E9=(is*ALe^aNNXpD9vdhtsLR(vOvC;M8{0;w literal 0 HcmV?d00001 diff --git a/www/apps/docs/static/img/.bak/magnifying-glass-dark.svg b/www/apps/docs/static/img/.bak/magnifying-glass-dark.svg new file mode 100644 index 0000000..ae81c80 --- /dev/null +++ b/www/apps/docs/static/img/.bak/magnifying-glass-dark.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/www/apps/docs/static/img/.bak/magnifying-glass.svg b/www/apps/docs/static/img/.bak/magnifying-glass.svg new file mode 100644 index 0000000..c46314a --- /dev/null +++ b/www/apps/docs/static/img/.bak/magnifying-glass.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/www/apps/docs/static/img/.bak/nextjs-icon-dark.svg b/www/apps/docs/static/img/.bak/nextjs-icon-dark.svg new file mode 100644 index 0000000..ce51ce8 --- /dev/null +++ b/www/apps/docs/static/img/.bak/nextjs-icon-dark.svg @@ -0,0 +1,3 @@ + + + diff --git a/www/apps/docs/static/img/.bak/nextjs-icon.svg b/www/apps/docs/static/img/.bak/nextjs-icon.svg new file mode 100644 index 0000000..2492f21 --- /dev/null +++ b/www/apps/docs/static/img/.bak/nextjs-icon.svg @@ -0,0 +1,3 @@ + + + diff --git a/www/apps/docs/static/img/.bak/payment-accepted-icon-dark.svg b/www/apps/docs/static/img/.bak/payment-accepted-icon-dark.svg new file mode 100644 index 0000000..2cad4d9 --- /dev/null +++ b/www/apps/docs/static/img/.bak/payment-accepted-icon-dark.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/www/apps/docs/static/img/.bak/payment-accepted-icon.svg b/www/apps/docs/static/img/.bak/payment-accepted-icon.svg new file mode 100644 index 0000000..279d781 --- /dev/null +++ b/www/apps/docs/static/img/.bak/payment-accepted-icon.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/www/apps/docs/static/img/.bak/search-hit-arrow-light.svg b/www/apps/docs/static/img/.bak/search-hit-arrow-light.svg new file mode 100644 index 0000000..8b119c3 --- /dev/null +++ b/www/apps/docs/static/img/.bak/search-hit-arrow-light.svg @@ -0,0 +1,4 @@ + + + + diff --git a/www/apps/docs/static/img/.bak/search-hit-arrow.svg b/www/apps/docs/static/img/.bak/search-hit-arrow.svg new file mode 100644 index 0000000..5738538 --- /dev/null +++ b/www/apps/docs/static/img/.bak/search-hit-arrow.svg @@ -0,0 +1,4 @@ + + + + diff --git a/www/apps/docs/static/img/.bak/search-hit-light.svg b/www/apps/docs/static/img/.bak/search-hit-light.svg new file mode 100644 index 0000000..0c8b06d --- /dev/null +++ b/www/apps/docs/static/img/.bak/search-hit-light.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/www/apps/docs/static/img/.bak/search-hit.png b/www/apps/docs/static/img/.bak/search-hit.png new file mode 100644 index 0000000000000000000000000000000000000000..3099be91c117d618925dfefa80c0130c824d6a07 GIT binary patch literal 774 zcmV+h1Nr=kP)nmj`WQ>SljJ=}mBG`Rss;JsMtE&(Dt z7Gn~uNiz9nGJ{vv_>XqA+7w0{{VJyZ + + + + diff --git a/www/apps/docs/static/img/.bak/search-no-result-light.svg b/www/apps/docs/static/img/.bak/search-no-result-light.svg new file mode 100644 index 0000000..5de948e --- /dev/null +++ b/www/apps/docs/static/img/.bak/search-no-result-light.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/www/apps/docs/static/img/.bak/search-no-result.svg b/www/apps/docs/static/img/.bak/search-no-result.svg new file mode 100644 index 0000000..ed49a6f --- /dev/null +++ b/www/apps/docs/static/img/.bak/search-no-result.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/www/apps/docs/static/img/.bak/server-icon-dark.svg b/www/apps/docs/static/img/.bak/server-icon-dark.svg new file mode 100644 index 0000000..23680ed --- /dev/null +++ b/www/apps/docs/static/img/.bak/server-icon-dark.svg @@ -0,0 +1,3 @@ + + + diff --git a/www/apps/docs/static/img/.bak/server-icon.svg b/www/apps/docs/static/img/.bak/server-icon.svg new file mode 100644 index 0000000..2a7cf43 --- /dev/null +++ b/www/apps/docs/static/img/.bak/server-icon.svg @@ -0,0 +1,3 @@ + + + diff --git a/www/apps/docs/static/img/.bak/stardust.png b/www/apps/docs/static/img/.bak/stardust.png new file mode 100644 index 0000000000000000000000000000000000000000..a3fd965c9c23506c6a9c99c50da2a573758b62fa GIT binary patch literal 2089 zcmbVN2~ZPB6z$=Pa_*uW0>!GR$RZdMi^Bi{iU%l1z<@y@>k^_Oii-wAAVe&27Z5Dv znh1&@>WV}#poE|aKqo z16>PU0D!^jRm;f$XiDH1o1z2n4a%kz_?Q~MYJCC#dehVw0(eE{(1|3FS9$|}i`8TJ zqQ&r9>jgk{j-K)tZ2)kWS1f$cljnMS&E5f` zmL34Kl(?T2Z&7JtFz@jqZHS+i(v7ClJ&fQKbHO&tmxH0HBI&~*8Gc2RE*=0$YoPC+ z4vUg+pbS*Nd_>MVh^s{a*wo9Er$%4Cm36#L^MhjFGHheag*YNl*Isz4xPq1D67*J- zvr|uv9vhJM7eYX7W|c~nokB#*qE4jnSjNw;E{5@!3mG0*@{FuIvlTmJU*hm>qpJh} zx6|@x?PXy{Q<6*oX~>EOfHjqrq_~9rbY5Si(qdkp465Nx%u)F8!9vI=0J~j|B2Xl> z*m@zTaO{oI?C3ELFM%L?GWbeshCfk&vBv97)NFvhorfmY$_V+xp_5Z`WoTxYskGAY zx9G zSO-T{sr8kOb6-h3-tk3Uan4H(xAkbi>ZH4Qjg&wR%BnGHy`E3r;`h9yUR(}UFqp2P z4}hps_xTYtif*XkRMsE;dZyz2V0tAEX0z$146a0-3Eilfa7mI$6;e?tquh@Q;v#^y z|NM!Xb<%taS+<^H3K{;$*peR>K+x=wllJH8a}y5WqF>_Tpt`pDhH`QU;+q&zdiBK= zdmT?T^>w1od$+gK9f_m&W3+eAoKAx?MX`Ow;Sbz%=*Usr-Ul|E;~opt0NmORYF}-~j+jVap&>|$ zGX~&nERVHN;UAigj8t!i?D2hMWtd_E!vB;VNij;90&Ke0&WlWuhVJEo9>z&eP06ZV z!{hjbyBw^D5rY7>FQUWUL27E4(L5y5&FYGE=ERie`hbQQV<4HotFQPkG!vsQXg#~H zI@UQw#dFo;j#b0ee8|jWSvNbhQBv>WM#q$5wBXb7-;VUFkuO6a)!gt7>h?F@cI7(y zMQRx-JwrK0L|fEH=H~a@jV3t>3&)EnoSztcq998HE3uQnZIQEi-#FZKi9h1wFL**p zTs%{2{m9RctxAma4NCj3SFUxHwgni;>z>!@=xZkcTmw`Kc#3Og6$cOlG=S61>6<{w z_TG+rIfN)E)Q_!f*nAG)?itDcof;wTB>NfwIR@jo$Vk&zkZf`O;q$G;meo3SICy5# zT>J^*mJJNPH=A%Y_sqc-JFJ%nKoA5SW0}rti?7uli2WN#rC0u6C>D-UD7B#zV%bsnCOLPD| z_43(6`21zb8{9w}yFanp61`DfbY0~pzT%kXRjqBojo3sws48TUV2iy817`gdcF#1U z^%etBo1=wC3skH*_rf*z+83f;VKff@1wS`QNe9&yZO>|70-P}QVfpU2LRLP@8T8Cg zggf?4d9lNrG3`|zt@Cl?jU-aJhkykqiM zMM8Ng{4evY_G$t5&Nx=&)ruE-K&emRA|+DCjq5qF^BX_!>H9p&y6uQtP3d8uxn(MK OhSfg)%lY24w0{7LSFsBK literal 0 HcmV?d00001 diff --git a/www/apps/docs/static/img/.bak/stripe-icon-dark.svg b/www/apps/docs/static/img/.bak/stripe-icon-dark.svg new file mode 100644 index 0000000..ff2c081 --- /dev/null +++ b/www/apps/docs/static/img/.bak/stripe-icon-dark.svg @@ -0,0 +1,3 @@ + + + diff --git a/www/apps/docs/static/img/.bak/stripe-icon.svg b/www/apps/docs/static/img/.bak/stripe-icon.svg new file mode 100644 index 0000000..1d5dd40 --- /dev/null +++ b/www/apps/docs/static/img/.bak/stripe-icon.svg @@ -0,0 +1,3 @@ + + + diff --git a/www/apps/docs/static/img/.bak/tee-icon-dark.svg b/www/apps/docs/static/img/.bak/tee-icon-dark.svg new file mode 100644 index 0000000..3537f92 --- /dev/null +++ b/www/apps/docs/static/img/.bak/tee-icon-dark.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/www/apps/docs/static/img/.bak/tee-icon.svg b/www/apps/docs/static/img/.bak/tee-icon.svg new file mode 100644 index 0000000..fc03a4c --- /dev/null +++ b/www/apps/docs/static/img/.bak/tee-icon.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/www/apps/docs/static/img/.bak/terminal-icon-dark.svg b/www/apps/docs/static/img/.bak/terminal-icon-dark.svg new file mode 100644 index 0000000..f27e06d --- /dev/null +++ b/www/apps/docs/static/img/.bak/terminal-icon-dark.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/www/apps/docs/static/img/.bak/terminal-icon.svg b/www/apps/docs/static/img/.bak/terminal-icon.svg new file mode 100644 index 0000000..7c9051d --- /dev/null +++ b/www/apps/docs/static/img/.bak/terminal-icon.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/www/apps/docs/static/img/.bak/user-guide-dark.svg b/www/apps/docs/static/img/.bak/user-guide-dark.svg new file mode 100644 index 0000000..40771ae --- /dev/null +++ b/www/apps/docs/static/img/.bak/user-guide-dark.svg @@ -0,0 +1,3 @@ + + + diff --git a/www/apps/docs/static/img/.bak/user-guide.svg b/www/apps/docs/static/img/.bak/user-guide.svg new file mode 100644 index 0000000..7462995 --- /dev/null +++ b/www/apps/docs/static/img/.bak/user-guide.svg @@ -0,0 +1,3 @@ + + + diff --git a/www/apps/docs/static/img/diagrams-bg.png b/www/apps/docs/static/img/diagrams-bg.png new file mode 100644 index 0000000000000000000000000000000000000000..33d55ab5cbd051d361e9d028b7bed9782dc50dcb GIT binary patch literal 2620 zcmeAS@N?(olHy`uVBq!ia0y~yV7kD-z&MqI4JdM5>)1UY#aZAHSWld`v<~^@jziBfJ{JwRL9jLwO@vix%3=9prc9?pIFglvi_WaMd z)N~m5zI84?$YsY%?X!VyjjqAr9Q;OaW2&0>dGD!nFz_zhS{~$^zSnivKq2r0pHFcb zox}RY=6UthxiE0|dKuW$GS~mEVPs&)`PfJ(5V0A3gX=}*x$j!mFtB_5Td=1s*8PrT zW?;DSh?%JPK{I-T=!MU7-iMaKLHzBXAWs*>eBTUAYa5P&;tov@uBb;SOVD2M-17eF zH*m0T+h>rcAMALS4s>NgH#qJ{NL65?4~99MFWwh^6Ao%~pMyMo5SnVmz;QR4U2J1vvhtz>FzgXz{U!Lr>mdKI;Vst0MF6Cz5oCK literal 0 HcmV?d00001 diff --git a/www/apps/docs/static/img/logo-icon-dark.svg b/www/apps/docs/static/img/logo-icon-dark.svg new file mode 100644 index 0000000..b6a3820 --- /dev/null +++ b/www/apps/docs/static/img/logo-icon-dark.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/www/apps/docs/static/img/logo-icon.svg b/www/apps/docs/static/img/logo-icon.svg new file mode 100644 index 0000000..6788bea --- /dev/null +++ b/www/apps/docs/static/img/logo-icon.svg @@ -0,0 +1,7 @@ + + + + + + + diff --git a/www/apps/docs/static/img/side-menu-light.svg b/www/apps/docs/static/img/side-menu-light.svg new file mode 100644 index 0000000..b204a38 --- /dev/null +++ b/www/apps/docs/static/img/side-menu-light.svg @@ -0,0 +1,3 @@ + + + diff --git a/www/apps/docs/static/img/side-menu.svg b/www/apps/docs/static/img/side-menu.svg new file mode 100644 index 0000000..1f785a5 --- /dev/null +++ b/www/apps/docs/static/img/side-menu.svg @@ -0,0 +1,3 @@ + + + diff --git a/www/apps/docs/static/img/small-squares-bg-light.svg b/www/apps/docs/static/img/small-squares-bg-light.svg new file mode 100644 index 0000000..b857078 --- /dev/null +++ b/www/apps/docs/static/img/small-squares-bg-light.svg @@ -0,0 +1,47 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/www/apps/docs/static/img/small-squares-bg.svg b/www/apps/docs/static/img/small-squares-bg.svg new file mode 100644 index 0000000..5e7d44a --- /dev/null +++ b/www/apps/docs/static/img/small-squares-bg.svg @@ -0,0 +1,47 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/www/apps/docs/static/img/squares-bg-light.svg b/www/apps/docs/static/img/squares-bg-light.svg new file mode 100644 index 0000000..6277534 --- /dev/null +++ b/www/apps/docs/static/img/squares-bg-light.svg @@ -0,0 +1,32 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/www/apps/docs/static/img/squares-bg.svg b/www/apps/docs/static/img/squares-bg.svg new file mode 100644 index 0000000..3713461 --- /dev/null +++ b/www/apps/docs/static/img/squares-bg.svg @@ -0,0 +1,32 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/www/apps/docs/static/manifest.webmanifest b/www/apps/docs/static/manifest.webmanifest new file mode 100644 index 0000000..19e8c3f --- /dev/null +++ b/www/apps/docs/static/manifest.webmanifest @@ -0,0 +1,14 @@ +{ + "icons": [ + { + "src": "/android-chrome-192x192.png", + "sizes": "192x192", + "type": "image/png" + }, + { + "src": "/android-chrome-512x512.png", + "sizes": "512x512", + "type": "image/png" + } + ] +} diff --git a/www/apps/docs/static/robots.txt b/www/apps/docs/static/robots.txt new file mode 100644 index 0000000..1dae859 --- /dev/null +++ b/www/apps/docs/static/robots.txt @@ -0,0 +1,4 @@ +User-agent: * +Allow: / + +Sitemap: http://arg.sh/sitemap.xml \ No newline at end of file diff --git a/www/apps/docs/tailwind.config.js b/www/apps/docs/tailwind.config.js new file mode 100644 index 0000000..2867fa0 --- /dev/null +++ b/www/apps/docs/tailwind.config.js @@ -0,0 +1,30 @@ +import coreConfig from "tailwind" + +/** @type {import('tailwindcss').Config} */ +module.exports = { + ...coreConfig, + // prefix: "tw-", + corePlugins: { + preflight: false, // disable Tailwind's reset + }, + content: [ + ...coreConfig.content, + "./src/**/*.{js,jsx,ts,tsx}", + "./content/**/*.{mdx,md}", + "docusaurus.config.js", + "sidebars.js", + ], + theme: { + ...coreConfig.theme, + extend: { + ...coreConfig.theme.extend, + screens: { + ...coreConfig.theme.screens, + xs: "576px", + lg: "996px", + xl: "1419px", + xxl: "1440px", + }, + }, + }, +} diff --git a/www/ignore-build-script.sh b/www/ignore-build-script.sh new file mode 100644 index 0000000..f47d02d --- /dev/null +++ b/www/ignore-build-script.sh @@ -0,0 +1,22 @@ +#!/bin/bash + +echo "VERCEL_ENV: $VERCEL_ENV" +echo "VERCEL_GIT_COMMIT_REF: $VERCEL_GIT_COMMIT_REF" + +SCRIPT_DIR=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd ) +echo "SCRIPT_DIR: $SCRIPT_DIR" + +$(git diff HEAD^ HEAD --quiet ${SCRIPT_DIR}) +diffResult=$? + +echo "DIFF RESULT: $diffResult" + +if [[ ("$VERCEL_ENV" == "production" && $diffResult -eq 1) || "$VERCEL_GIT_COMMIT_REF" = "docs/"* ]] ; then + # Proceed with the build + echo "✅ - Build can proceed" + exit 1; +else + # Don't build + echo "🛑 - Build cancelled: Conditions don't match" + exit 0; +fi \ No newline at end of file diff --git a/www/package.json b/www/package.json new file mode 100644 index 0000000..cec223d --- /dev/null +++ b/www/package.json @@ -0,0 +1,34 @@ +{ + "name": "docs-root", + "private": true, + "workspaces": { + "packages": [ + "apps/*", + "packages/*" + ] + }, + "scripts": { + "build": "turbo run build", + "build:docs": "turbo run build --filter=docs", + "start": "turbo run start:monorepo", + "dev": "turbo run dev:monorepo", + "lint": "turbo run lint", + "lint:content": "turbo run lint:content" + }, + "dependencies": { + "autoprefixer": "10.4.18", + "eslint": "^8.57.0", + "postcss": "8.4.35", + "prettier": "^3.2.5", + "tailwindcss": "3.4.1", + "tsconfig": "*", + "turbo": "latest" + }, + "engines": { + "node": ">=18.17.0" + }, + "resolutions": { + "string-width": "4.2.3", + "jackspeak": "2.1.1" + } +} diff --git a/www/packages/docs-ui/.eslintrc.js b/www/packages/docs-ui/.eslintrc.js new file mode 100644 index 0000000..c95714e --- /dev/null +++ b/www/packages/docs-ui/.eslintrc.js @@ -0,0 +1,10 @@ +module.exports = { + root: true, + extends: [ + "docs" + ], + parserOptions: { + project: true, + tsconfigRootDir: __dirname, + }, +} diff --git a/www/packages/docs-ui/.gitignore b/www/packages/docs-ui/.gitignore new file mode 100644 index 0000000..76add87 --- /dev/null +++ b/www/packages/docs-ui/.gitignore @@ -0,0 +1,2 @@ +node_modules +dist \ No newline at end of file diff --git a/www/packages/docs-ui/package.json b/www/packages/docs-ui/package.json new file mode 100644 index 0000000..20ea400 --- /dev/null +++ b/www/packages/docs-ui/package.json @@ -0,0 +1,74 @@ +{ + "name": "docs-ui", + "version": "0.0.0", + "private": true, + "license": "MIT", + "publishConfig": { + "access": "public" + }, + "main": "./dist/cjs/index.js", + "types": "./dist/cjs/index.d.ts", + "module": "./dist/esm/index.js", + "exports": { + ".": { + "require": { + "types": "./dist/cjs/index.d.ts", + "default": "./dist/cjs/index.js" + }, + "import": { + "types": "./dist/esm/index.d.ts", + "default": "./dist/esm/index.js" + } + } + }, + "sideEffects": false, + "files": [ + "dist/**" + ], + "scripts": { + "build": "yarn clean && yarn build:js:cjs && yarn build:js:esm", + "build:js:cjs": "tsc --project tsconfig.cjs.json && tsc-alias -p tsconfig.cjs.json", + "build:js:esm": "tsc --project tsconfig.esm.json && tsc-alias -p tsconfig.esm.json", + "clean": "rimraf dist", + "dev": "yarn build:js:cjs && yarn build:js:esm" + }, + "devDependencies": { + "@types/react": "^18.2.65", + "@types/react-dom": "^18.2.21", + "@types/react-google-recaptcha": "^2.1.9", + "clsx": "^2.1.0", + "cpy-cli": "^5.0.0", + "eslint-config-docs": "*", + "next": "latest", + "react": "^18.2.0", + "react-dom": "^18.2.0", + "rimraf": "^5.0.5", + "tailwind": "*", + "tailwindcss": "^3.4.1", + "tsc-alias": "^1.8.8", + "tsup": "^8.0.2", + "typescript": "^5.4.2" + }, + "peerDependencies": { + "@types/react": "^18.2.0", + "@types/react-dom": "^18.2.0", + "next": "*", + "react": "^18.2.0", + "react-dom": "^18.2.0" + }, + "dependencies": { + "@medusajs/icons": "^1.2.0", + "@medusajs/ui": "^2.4.1", + "@octokit/request": "^8.1.1", + "@react-hook/resize-observer": "^1.2.6", + "@segment/analytics-next": "^1.66.0", + "algoliasearch": "^4.22.1", + "prism-react-renderer": "2.3.1", + "react-google-recaptcha": "^3.1.0", + "react-instantsearch": "^7.7.0", + "react-markdown": "^8.0.7", + "react-tooltip": "^5.26.3", + "react-transition-group": "^4.4.5", + "react-uuid": "^2.0.0" + } +} diff --git a/www/packages/docs-ui/postcss.config.js b/www/packages/docs-ui/postcss.config.js new file mode 100644 index 0000000..73368e6 --- /dev/null +++ b/www/packages/docs-ui/postcss.config.js @@ -0,0 +1 @@ +module.exports = require("tailwind/postcss.config") diff --git a/www/packages/docs-ui/src/components/Badge/index.tsx b/www/packages/docs-ui/src/components/Badge/index.tsx new file mode 100644 index 0000000..3a33e67 --- /dev/null +++ b/www/packages/docs-ui/src/components/Badge/index.tsx @@ -0,0 +1,41 @@ +import React from "react" +import clsx from "clsx" + +export type BadgeVariant = + | "purple" + | "orange" + | "green" + | "blue" + | "red" + | "neutral" + +export type BadgeProps = { + className?: string + variant: BadgeVariant +} & React.HTMLAttributes + +export const Badge = ({ className, variant, children }: BadgeProps) => { + return ( + + {children} + + ) +} diff --git a/www/packages/docs-ui/src/components/Bordered/index.tsx b/www/packages/docs-ui/src/components/Bordered/index.tsx new file mode 100644 index 0000000..ebe6723 --- /dev/null +++ b/www/packages/docs-ui/src/components/Bordered/index.tsx @@ -0,0 +1,21 @@ +import clsx from "clsx" +import React from "react" + +export type BorderedProps = { + wrapperClassName?: string +} & React.HTMLAttributes + +export const Bordered = ({ wrapperClassName, children }: BorderedProps) => { + return ( + + {children} + + ) +} diff --git a/www/packages/docs-ui/src/components/BorderedIcon/index.tsx b/www/packages/docs-ui/src/components/BorderedIcon/index.tsx new file mode 100644 index 0000000..ffd66a6 --- /dev/null +++ b/www/packages/docs-ui/src/components/BorderedIcon/index.tsx @@ -0,0 +1,51 @@ +import React from "react" +import { Bordered } from "@/components/Bordered" +import clsx from "clsx" +import { IconProps } from "@medusajs/icons/dist/types" + +export type BorderedIconProps = { + icon?: string + IconComponent?: React.FC | null + wrapperClassName?: string + iconWrapperClassName?: string + iconClassName?: string + iconColorClassName?: string +} & React.HTMLAttributes + +export const BorderedIcon = ({ + icon = "", + IconComponent = null, + wrapperClassName, + iconWrapperClassName, + iconClassName, + iconColorClassName = "", +}: BorderedIconProps) => { + return ( + + + {!IconComponent && ( + + )} + {IconComponent && ( + + )} + + + ) +} diff --git a/www/packages/docs-ui/src/components/Button/index.tsx b/www/packages/docs-ui/src/components/Button/index.tsx new file mode 100644 index 0000000..6977e09 --- /dev/null +++ b/www/packages/docs-ui/src/components/Button/index.tsx @@ -0,0 +1,79 @@ +import clsx from "clsx" +import React from "react" + +export type ButtonVariants = "primary" | "secondary" | "clear" + +export type ButtonType = "default" | "icon" + +export type ButtonProps = { + isSelected?: boolean + disabled?: boolean + variant?: ButtonVariants + className?: string + buttonType?: ButtonType + buttonRef?: React.LegacyRef +} & React.HTMLAttributes + +export const Button = ({ + className, + children, + variant = "primary", + buttonType = "default", + buttonRef, + ...props +}: ButtonProps) => { + const variantClasses = { + primary: [ + "py-[5px] px-docs_0.75 rounded-docs_sm cursor-pointer", + "bg-button-inverted bg-medusa-button-inverted dark:bg-button-inverted-dark", + "hover:bg-medusa-button-inverted-hover hover:bg-no-image hover:no-underline", + "active:bg-medusa-button-inverted-pressed active:bg-no-image", + "focus:bg-medusa-button-inverted-pressed focus:bg-no-image", + "shadow-button-colored active:shadow-button-colored-focused focus:shadow-button-colored-focused transition-shadow", + "dark:shadow-button-colored-dark dark:active:shadow-button-colored-focused-dark dark:focus:shadow-button-colored-focused-dark", + "disabled:!bg-no-image disabled:bg-medusa-bg-disabled", + "disabled:cursor-not-allowed disabled:border-medusa-border-base", + "text-compact-small-plus text-medusa-fg-on-inverted", + "[&_a]:text-medusa-fg-on-inverted", + "disabled:text-medusa-fg-disabled", + "[&_a]:disabled:text-medusa-fg-disabled", + "border border-medusa-border-loud", + "select-none", + ], + secondary: [ + "py-[5px] px-docs_0.75 rounded-docs_sm cursor-pointer", + "bg-button-neutral bg-medusa-button-neutral dark:bg-button-neutral-dark", + "hover:bg-medusa-button-neutral-hover hover:bg-no-image hover:no-underline", + "active:bg-medusa-button-neutral-pressed active:bg-no-image", + "focus:bg-medusa-button-neutral-pressed focus:bg-no-image", + "disabled:!bg-no-image disabled:bg-medusa-bg-disabled", + "disabled:cursor-not-allowed", + "border border-solid border-medusa-border-base", + "text-compact-small-plus text-medusa-fg-base", + "[&_a]:text-medusa-fg-base", + "shadow-button-neutral focus:shadow-button-neutral-focused active:shadow-button-neutral-focused transition-shadow", + "dark:shadow-button-neutral dark:focus:shadow-button-neutral-focused dark:active:shadow-button-neutral-focused", + "select-none", + ], + clear: [ + "bg-transparent shadow-none border-0 outline-none cursor-pointer text-fg-medusa-subtle", + ], + } + + return ( + + ) +} diff --git a/www/packages/docs-ui/src/components/Card/index.tsx b/www/packages/docs-ui/src/components/Card/index.tsx new file mode 100644 index 0000000..f59ccbe --- /dev/null +++ b/www/packages/docs-ui/src/components/Card/index.tsx @@ -0,0 +1,50 @@ +import React from "react" +import { ArrowUpRightOnBox } from "@medusajs/icons" +import clsx from "clsx" +import { Link } from "@/components" + +export type CardProps = { + icon?: React.ReactNode + title: string + text?: string + href?: string + className?: string +} + +export const Card = ({ icon, title, text, href, className }: CardProps) => { + return ( +

+ ) +} diff --git a/www/packages/docs-ui/src/components/CodeBlock/index.tsx b/www/packages/docs-ui/src/components/CodeBlock/index.tsx new file mode 100644 index 0000000..1fc5dbc --- /dev/null +++ b/www/packages/docs-ui/src/components/CodeBlock/index.tsx @@ -0,0 +1,124 @@ +"use client" + +import React from "react" +import clsx from "clsx" +import { HighlightProps, Highlight, themes } from "prism-react-renderer" +import { CopyButton, useColorMode } from "docs-ui" +import { SquareTwoStackSolid } from "@medusajs/icons" + +export type CodeBlockProps = { + source: string + lang?: string + className?: string + collapsed?: boolean +} & Omit + +export const CodeBlock = ({ + source, + lang = "", + className, + collapsed = false, + ...rest +}: CodeBlockProps) => { + const { colorMode } = useColorMode() + + if (!source.length) { + return <> + } + + return ( +
+ + {({ + className: preClassName, + style, + tokens, + getLineProps, + getTokenProps, + }) => ( + <> +
+               1 && "pt-docs_1 pr-docs_1",
+                  tokens.length <= 1 && "!py-docs_0.5 px-docs_1"
+                )}
+              >
+                {tokens.map((line, i) => {
+                  const lineProps = getLineProps({ line, key: i })
+                  return (
+                    
+                      {tokens.length > 1 && (
+                        
+                          {i + 1}
+                        
+                      )}
+                      
+                        {line.map((token, key) => (
+                          
+                        ))}
+                      
+                    
+                  )
+                })}
+              
+            
+ + + )} +
+
+ ) +} diff --git a/www/packages/docs-ui/src/components/CodeMdx/index.tsx b/www/packages/docs-ui/src/components/CodeMdx/index.tsx new file mode 100644 index 0000000..e2101f8 --- /dev/null +++ b/www/packages/docs-ui/src/components/CodeMdx/index.tsx @@ -0,0 +1,29 @@ +import React from "react" +import { CodeBlock, InlineCode } from "@/components" + +export type CodeMdxProps = { + className?: string + children?: React.ReactNode +} + +// due to how mdx handles code blocks +// it is required that a code block specify a language +// to be considered a block. Otherwise, it will be +// considered as inline code +export const CodeMdx = ({ className, children }: CodeMdxProps) => { + if (!children) { + return <> + } + + const match = /language-(\w+)/.exec(className || "") + + const codeContent = Array.isArray(children) + ? (children[0] as string) + : (children as string) + + if (match) { + return + } + + return {codeContent} +} diff --git a/www/packages/docs-ui/src/components/CodeTabs/index.tsx b/www/packages/docs-ui/src/components/CodeTabs/index.tsx new file mode 100644 index 0000000..47b0ad4 --- /dev/null +++ b/www/packages/docs-ui/src/components/CodeTabs/index.tsx @@ -0,0 +1,129 @@ +"use client" + +import React, { useCallback, useEffect, useMemo, useRef } from "react" +import clsx from "clsx" +import { CodeBlock, CodeBlockProps } from "@/components" +import { useTabs, BaseTabType, useScrollPositionBlocker } from "@/hooks" + +export type TabType = { + code?: CodeBlockProps + codeBlock?: React.ReactNode +} & BaseTabType + +export type CodeTabsProps = { + tabs: TabType[] + className?: string + group?: string +} + +export const CodeTabs = ({ + tabs, + className, + group = "client", +}: CodeTabsProps) => { + const { selectedTab, changeSelectedTab } = useTabs({ + tabs, + group, + }) + const tabRefs: (HTMLButtonElement | null)[] = useMemo(() => [], []) + const codeTabSelectorRef = useRef(null) + const codeTabsWrapperRef = useRef(null) + const { blockElementScrollPositionUntilNextRender } = + useScrollPositionBlocker() + + const changeTabSelectorCoordinates = useCallback( + (selectedTabElm: HTMLElement) => { + if (!codeTabSelectorRef?.current || !codeTabsWrapperRef?.current) { + return + } + const selectedTabsCoordinates = selectedTabElm.getBoundingClientRect() + const tabsWrapperCoordinates = + codeTabsWrapperRef.current.getBoundingClientRect() + codeTabSelectorRef.current.style.left = `${ + selectedTabsCoordinates.left - tabsWrapperCoordinates.left + }px` + codeTabSelectorRef.current.style.width = `${selectedTabsCoordinates.width}px` + codeTabSelectorRef.current.style.height = `${selectedTabsCoordinates.height}px` + }, + [] + ) + + useEffect(() => { + if (codeTabSelectorRef?.current && tabRefs.length) { + const selectedTabElm = tabRefs.find( + (tab) => tab?.getAttribute("aria-selected") === "true" + ) + if (selectedTabElm) { + changeTabSelectorCoordinates( + selectedTabElm.parentElement || selectedTabElm + ) + } + } + }, [codeTabSelectorRef, tabRefs, changeTabSelectorCoordinates, selectedTab]) + + return ( +
+ +
    + {tabs.map((tab, index) => ( +
  • + +
  • + ))} +
+ <> + {selectedTab?.code && ( + + )} + {selectedTab?.codeBlock && <>{selectedTab.codeBlock}} + +
+ ) +} diff --git a/www/packages/docs-ui/src/components/CopyButton/index.tsx b/www/packages/docs-ui/src/components/CopyButton/index.tsx new file mode 100644 index 0000000..39274b7 --- /dev/null +++ b/www/packages/docs-ui/src/components/CopyButton/index.tsx @@ -0,0 +1,44 @@ +"use client" + +import React from "react" +import clsx from "clsx" +import { Tooltip } from "@/components" +import { useCopy } from "../../hooks" + +export type CopyButtonProps = { + text: string + buttonClassName?: string + tooltipClassName?: string + tooltipText?: string + onCopy?: (e: React.MouseEvent) => void +} & Omit, "onCopy"> + +export const CopyButton = ({ + text, + buttonClassName = "", + tooltipClassName = "", + tooltipText = "Copy to Clipboard", + children, + className, + onCopy, +}: CopyButtonProps) => { + const { isCopied, handleCopy } = useCopy(text) + + return ( + + { + onCopy?.(e) + handleCopy() + }} + > + {children} + + + ) +} diff --git a/www/packages/docs-ui/src/components/Details/Summary/index.tsx b/www/packages/docs-ui/src/components/Details/Summary/index.tsx new file mode 100644 index 0000000..226c096 --- /dev/null +++ b/www/packages/docs-ui/src/components/Details/Summary/index.tsx @@ -0,0 +1,71 @@ +import React from "react" +import clsx from "clsx" +import { PlusMini } from "@medusajs/icons" + +export type DetailsSummaryProps = { + title?: React.ReactNode + subtitle?: React.ReactNode + badge?: React.ReactNode + expandable?: boolean + open?: boolean + className?: string + titleClassName?: string + hideExpandableIcon?: boolean + summaryRef?: React.LegacyRef +} & Omit, "title"> + +export const DetailsSummary = ({ + title, + subtitle, + children, + badge, + expandable = true, + open = false, + className, + titleClassName, + hideExpandableIcon = false, + summaryRef, + ...rest +}: DetailsSummaryProps) => { + return ( + + + + {title || children} + + {subtitle && ( + + {subtitle} + + )} + + {(badge || expandable) && ( + + {badge} + {expandable && !hideExpandableIcon && ( + + )} + + )} + + ) +} diff --git a/www/packages/docs-ui/src/components/Details/index.tsx b/www/packages/docs-ui/src/components/Details/index.tsx new file mode 100644 index 0000000..cbeec2a --- /dev/null +++ b/www/packages/docs-ui/src/components/Details/index.tsx @@ -0,0 +1,131 @@ +"use client" + +import React, { Suspense, cloneElement, useRef, useState } from "react" +import { Loading } from "@/components/Loading" +import clsx from "clsx" +import { CSSTransition } from "react-transition-group" +import { DetailsSummary } from "./Summary" + +export type DetailsProps = { + openInitial?: boolean + summaryContent?: React.ReactNode + summaryElm?: React.ReactNode + heightAnimation?: boolean +} & React.HTMLAttributes + +export const Details = ({ + openInitial = false, + summaryContent, + summaryElm, + children, + heightAnimation = false, + ...props +}: DetailsProps) => { + const [open, setOpen] = useState(openInitial) + const [showContent, setShowContent] = useState(openInitial) + const ref = useRef(null) + + const handleToggle = (e: React.MouseEvent) => { + const targetElm = e.target as HTMLElement + if (targetElm.tagName.toLowerCase() === "a") { + window.location.href = + targetElm.getAttribute("href") || window.location.href + return + } + if (targetElm.tagName.toLowerCase() === "code") { + return + } + if (open) { + setShowContent(false) + } else { + setOpen(true) + setShowContent(true) + } + } + + return ( +
{ + event.preventDefault() + }} + onToggle={(event) => { + // this is to avoid event propagation + // when details are nested, which is a bug + // in react. Learn more here: + // https://github.com/facebook/react/issues/22718 + event.stopPropagation() + }} + className={clsx( + "border-medusa-border-base border-y border-solid border-x-0", + "overflow-hidden [&>summary]:relative", + props.className + )} + > + {summaryContent && ( + + )} + {summaryElm && + cloneElement(summaryElm as React.ReactElement, { + open, + onClick: handleToggle, + })} + { + if (heightAnimation) { + node.classList.add("transition-[height]") + node.style.height = `0px` + } else { + node.classList.add( + "!mb-docs_2", + "!mt-0", + "translate-y-docs_1", + "transition-transform" + ) + } + }} + onEntering={(node: HTMLElement) => { + if (heightAnimation) { + node.style.height = `${node.scrollHeight}px` + } + }} + onEntered={(node: HTMLElement) => { + if (heightAnimation) { + node.style.height = `auto` + } + }} + onExit={(node: HTMLElement) => { + if (heightAnimation) { + node.style.height = `${node.scrollHeight}px` + } else { + node.classList.add("transition-transform", "!-translate-y-docs_1") + setTimeout(() => { + setOpen(false) + }, 100) + } + }} + onExiting={(node: HTMLElement) => { + if (heightAnimation) { + node.style.height = `0px` + setTimeout(() => { + setOpen(false) + }, 100) + } + }} + > + }> + {children} + + +
+ ) +} diff --git a/www/packages/docs-ui/src/components/ExpandableNotice/index.tsx b/www/packages/docs-ui/src/components/ExpandableNotice/index.tsx new file mode 100644 index 0000000..89f53ca --- /dev/null +++ b/www/packages/docs-ui/src/components/ExpandableNotice/index.tsx @@ -0,0 +1,34 @@ +import React from "react" +import { Badge, Link, Tooltip } from "@/components" + +export type ExpandableNoticeProps = { + type: "request" | "method" + link: string + badgeContent?: React.ReactNode + badgeClassName?: string +} + +export const ExpandableNotice = ({ + type = "request", + link, + badgeContent = "expandable", + badgeClassName, +}: ExpandableNoticeProps) => { + return ( + + If this {type} accepts an expand{" "} + {type === "request" ? "parameter" : "property or option"}, +
this field can be expanded into an + object. + + } + clickable + > + + {badgeContent} + +
+ ) +} diff --git a/www/packages/docs-ui/src/components/FeatureFlagNotice/index.tsx b/www/packages/docs-ui/src/components/FeatureFlagNotice/index.tsx new file mode 100644 index 0000000..d2ffaa0 --- /dev/null +++ b/www/packages/docs-ui/src/components/FeatureFlagNotice/index.tsx @@ -0,0 +1,40 @@ +import React from "react" +import { Badge, Link, Tooltip } from "@/components" + +export type FeatureFlagNoticeProps = { + featureFlag: string + type?: "endpoint" | "parameter" + tooltipTextClassName?: string + badgeClassName?: string + badgeContent?: React.ReactNode +} + +export const FeatureFlagNotice = ({ + featureFlag, + type = "endpoint", + tooltipTextClassName, + badgeClassName, + badgeContent = "feature flag", +}: FeatureFlagNoticeProps) => { + return ( + + To use this {type}, make sure to +
+ + enable its feature flag: {featureFlag} + + + } + clickable + > + + {badgeContent} + +
+ ) +} diff --git a/www/packages/docs-ui/src/components/Feedback/Solutions/index.tsx b/www/packages/docs-ui/src/components/Feedback/Solutions/index.tsx new file mode 100644 index 0000000..b451215 --- /dev/null +++ b/www/packages/docs-ui/src/components/Feedback/Solutions/index.tsx @@ -0,0 +1,92 @@ +"use client" + +import React, { useEffect, useState } from "react" +import { request } from "@octokit/request" +import { Link } from "@/components/Link" + +export type SolutionsProps = { + feedback: boolean + message?: string +} + +export type GitHubSearchItem = { + url: string + html_url: string + title: string + [key: string]: unknown +} + +export const Solutions = ({ feedback, message }: SolutionsProps) => { + const [possibleSolutionsQuery, setPossibleSolutionsQuery] = + useState("") + const [possibleSolutions, setPossibleSolutions] = useState< + GitHubSearchItem[] + >([]) + + function constructQuery(searchQuery: string) { + return `${searchQuery} repo:fentas/b is:closed is:issue` + } + + async function searchGitHub(query: string) { + return request(`GET /search/issues`, { + q: query, + sort: "updated", + per_page: 3, + }) + } + + useEffect(() => { + if (!feedback) { + let query = constructQuery( + // Github does not allow queries longer than 256 characters + message ? message.substring(0, 256) : document.title + ) + searchGitHub(query) + .then(async (result) => { + if (!result.data.items.length && message) { + query = constructQuery(document.title) + result = await searchGitHub(query) + } + + setPossibleSolutionsQuery(query) + setPossibleSolutions(result.data.items) + }) + .catch((err) => console.error(err)) + } else { + setPossibleSolutionsQuery("") + setPossibleSolutions([]) + } + }, [feedback, message]) + + return ( + <> + {possibleSolutions.length > 0 && ( +
+ )} + + ) +} diff --git a/www/packages/docs-ui/src/components/Feedback/index.tsx b/www/packages/docs-ui/src/components/Feedback/index.tsx new file mode 100644 index 0000000..874d435 --- /dev/null +++ b/www/packages/docs-ui/src/components/Feedback/index.tsx @@ -0,0 +1,268 @@ +"use client" + +import React, { useRef, useState } from "react" +import { CSSTransition, SwitchTransition } from "react-transition-group" +import { Solutions } from "./Solutions" +import { ExtraData, useAnalytics } from "@/providers/Analytics" +import clsx from "clsx" +import { TextArea } from "@/components/TextArea" +import { Label } from "@/components/Label" +import { Button } from "docs-ui" +import { Details } from "@/components/Details" +import { InputText } from "@/components/Input/Text" + +export type FeedbackProps = { + event: string + pathName: string + reportLink?: string + question?: string + positiveBtn?: string + negativeBtn?: string + positiveQuestion?: string + negativeQuestion?: string + submitBtn?: string + submitMessage?: string + showPossibleSolutions?: boolean + className?: string + extraData?: ExtraData + vertical?: boolean + showLongForm?: boolean +} & React.HTMLAttributes + +export const Feedback = ({ + event, + pathName, + reportLink, + question = "Was this section helpful?", + positiveBtn = "Yes", + negativeBtn = "No", + positiveQuestion = "What was most helpful?", + negativeQuestion = "What can we improve?", + submitBtn = "Submit", + submitMessage = "Thank you for helping improve our documentation!", + showPossibleSolutions = true, + className = "", + extraData = {}, + vertical = false, + showLongForm = false, +}: FeedbackProps) => { + const [showForm, setShowForm] = useState(false) + const [submittedFeedback, setSubmittedFeedback] = useState(false) + const [loading, setLoading] = useState(false) + const inlineFeedbackRef = useRef(null) + const inlineQuestionRef = useRef(null) + const inlineMessageRef = useRef(null) + const [positiveFeedback, setPositiveFeedback] = useState(false) + const [message, setMessage] = useState("") + const [steps, setSteps] = useState("") + const [medusaVersion, setMedusaVersion] = useState("") + const [errorFix, setErrorFix] = useState("") + const [contactInfo, setContactInfo] = useState("") + const nodeRef: React.RefObject = submittedFeedback + ? inlineMessageRef + : showForm + ? inlineQuestionRef + : inlineFeedbackRef + const { loaded, track } = useAnalytics() + + function handleFeedback(e: React.MouseEvent) { + if (!loaded) { + return + } + const feedback = (e.target as Element).classList.contains("positive") + setPositiveFeedback(feedback) + setShowForm(true) + submitFeedback(e, feedback) + } + + function submitFeedback( + e: React.MouseEvent, + feedback = false + ) { + if (showForm) { + setLoading(true) + } + track( + event, + { + url: pathName, + label: document.title, + feedback: + (feedback !== null && feedback) || + (feedback === null && positiveFeedback) + ? "yes" + : "no", + message: message?.length ? message : null, + os: window.navigator.userAgent, + steps, + medusaVersion, + errorFix, + contactInfo, + ...extraData, + }, + function () { + if (showForm) { + setLoading(false) + resetForm() + } + } + ) + } + + function resetForm() { + setShowForm(false) + setSubmittedFeedback(true) + } + + return ( +
+ + { + nodeRef.current?.addEventListener("transitionend", done, false) + }} + classNames={{ + enter: "animate-fadeIn animation-fill-forwards animate-fast", + exit: "animate-fadeOut animation-fill-forwards animate-fast", + }} + > + <> + {!showForm && !submittedFeedback && ( +
+ +
+ + + {reportLink && ( + + )} +
+
+ )} + {showForm && !submittedFeedback && ( +
+ +