docs: preparations for preview (#7267)
* configured base paths + added development banner * fix typelist site url * added navbar and sidebar badges * configure algolia filters * remove AI assistant * remove unused imports * change navbar text and badge * lint fixes * fix build error * add to api reference rewrites * fix build error * fix build errors in user-guide * fix feedback component * add parent title to pagination * added breadcrumbs component * remove user-guide links * resolve todos * fix details about authentication * change documentation title * lint content
This commit is contained in:
1 parent
3e3b8a483f
commit
728c5ee53c
62 files changed
+855
-506
No files matched your search
@@ -15,4 +15,5 @@ ANALYZE_BUNDLE=
|
|||||||
NEXT_PUBLIC_AI_ASSISTANT_URL=
|
NEXT_PUBLIC_AI_ASSISTANT_URL=
|
||||||
NEXT_PUBLIC_AI_WEBSITE_ID=
|
NEXT_PUBLIC_AI_WEBSITE_ID=
|
||||||
NEXT_PUBLIC_AI_API_ASSISTANT_RECAPTCHA_SITE_KEY=
|
NEXT_PUBLIC_AI_API_ASSISTANT_RECAPTCHA_SITE_KEY=
|
||||||
NEXT_PUBLIC_VERSIONING=
|
NEXT_PUBLIC_VERSIONING=
|
||||||
|
NEXT_PUBLIC_SHOW_V2=
|
||||||
@@ -24,6 +24,7 @@ const Navbar = () => {
|
|||||||
getNavbarItems({
|
getNavbarItems({
|
||||||
basePath: config.baseUrl,
|
basePath: config.baseUrl,
|
||||||
activePath: pathname,
|
activePath: pathname,
|
||||||
|
version: process.env.NEXT_PUBLIC_SHOW_V2 ? "v1" : "legacy",
|
||||||
}),
|
}),
|
||||||
[pathname]
|
[pathname]
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import { DocsConfig } from "types"
|
import { DocsConfig } from "types"
|
||||||
import { mobileSidebarItems } from "docs-ui"
|
import { mobileSidebarItemsV1, legacyMobileSidebarItems } from "docs-ui"
|
||||||
|
|
||||||
export const config: DocsConfig = {
|
export const config: DocsConfig = {
|
||||||
baseUrl: process.env.NEXT_PUBLIC_BASE_URL || "http://localhost:3000",
|
baseUrl: process.env.NEXT_PUBLIC_BASE_URL || "http://localhost:3000",
|
||||||
@@ -13,6 +13,6 @@ export const config: DocsConfig = {
|
|||||||
},
|
},
|
||||||
],
|
],
|
||||||
bottom: [],
|
bottom: [],
|
||||||
mobile: mobileSidebarItems,
|
mobile: process.env.NEXT_PUBLIC_SHOW_V2 ? mobileSidebarItemsV1 : legacyMobileSidebarItems,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
@@ -4,30 +4,44 @@ import bundleAnalyzer from "@next/bundle-analyzer"
|
|||||||
/** @type {import('next').NextConfig} */
|
/** @type {import('next').NextConfig} */
|
||||||
const nextConfig = {
|
const nextConfig = {
|
||||||
async rewrites() {
|
async rewrites() {
|
||||||
|
const fallbacks = [
|
||||||
|
{
|
||||||
|
source: "/ui",
|
||||||
|
destination: `${process.env.NEXT_PUBLIC_UI_URL}/ui`,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
source: "/ui/:path*",
|
||||||
|
destination: `${process.env.NEXT_PUBLIC_UI_URL}/ui/:path*`,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
source: "/:path*",
|
||||||
|
destination: `${process.env.NEXT_PUBLIC_DOCS_URL}/:path*`,
|
||||||
|
},
|
||||||
|
]
|
||||||
|
|
||||||
|
if (process.env.NEXT_PUBLIC_SHOW_V2) {
|
||||||
|
fallbacks.push(
|
||||||
|
{
|
||||||
|
source: "/v2/resources",
|
||||||
|
destination: `${process.env.NEXT_PUBLIC_DOCS_V2_URL}/v2/resources`,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
source: "/v2/resources/:path*",
|
||||||
|
destination: `${process.env.NEXT_PUBLIC_DOCS_V2_URL}/v2/resources/:path*`,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
source: "/v2",
|
||||||
|
destination: `${process.env.NEXT_PUBLIC_DOCS_V2_URL}/v2`,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
source: "/v2/:path*",
|
||||||
|
destination: `${process.env.NEXT_PUBLIC_DOCS_V2_URL}/v2/:path*`,
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
fallback: [
|
fallback: fallbacks,
|
||||||
{
|
|
||||||
source: "/ui",
|
|
||||||
destination: `${process.env.NEXT_PUBLIC_UI_URL}/ui`,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
source: "/ui/:path*",
|
|
||||||
destination: `${process.env.NEXT_PUBLIC_UI_URL}/ui/:path*`,
|
|
||||||
},
|
|
||||||
// TODO uncomment for v2
|
|
||||||
// {
|
|
||||||
// source: "/v2",
|
|
||||||
// destination: `${process.env.NEXT_PUBLIC_DOCS_V2_URL}/resources`,
|
|
||||||
// },
|
|
||||||
// {
|
|
||||||
// source: "/v2/:path*",
|
|
||||||
// destination: `${process.env.NEXT_PUBLIC_DOCS_V2_URL}/resources/:path*`,
|
|
||||||
// },
|
|
||||||
{
|
|
||||||
source: "/:path*",
|
|
||||||
destination: `${process.env.NEXT_PUBLIC_DOCS_URL}/:path*`,
|
|
||||||
},
|
|
||||||
],
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
webpack: (config) => {
|
webpack: (config) => {
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ import {
|
|||||||
SearchProvider as UiSearchProvider,
|
SearchProvider as UiSearchProvider,
|
||||||
AiAssistantCommandIcon,
|
AiAssistantCommandIcon,
|
||||||
AiAssistantProvider,
|
AiAssistantProvider,
|
||||||
searchFilters,
|
searchFiltersV1,
|
||||||
} from "docs-ui"
|
} from "docs-ui"
|
||||||
import { config } from "../config"
|
import { config } from "../config"
|
||||||
|
|
||||||
@@ -53,7 +53,7 @@ const SearchProvider = ({ children }: SearchProviderProps) => {
|
|||||||
checkInternalPattern: new RegExp(
|
checkInternalPattern: new RegExp(
|
||||||
`^${config.baseUrl}/api/(admin|store)`
|
`^${config.baseUrl}/api/(admin|store)`
|
||||||
),
|
),
|
||||||
filterOptions: searchFilters,
|
filterOptions: searchFiltersV1,
|
||||||
}}
|
}}
|
||||||
commands={[
|
commands={[
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
"use client"
|
"use client"
|
||||||
import {
|
import {
|
||||||
SidebarProvider as UiSidebarProvider,
|
SidebarProvider as UiSidebarProvider,
|
||||||
mobileSidebarItems,
|
|
||||||
usePageLoading,
|
usePageLoading,
|
||||||
useScrollController,
|
useScrollController,
|
||||||
} from "docs-ui"
|
} from "docs-ui"
|
||||||
|
|||||||
@@ -14,4 +14,5 @@ ANALYZE_BUNDLE=
|
|||||||
NEXT_PUBLIC_AI_ASSISTANT_URL=
|
NEXT_PUBLIC_AI_ASSISTANT_URL=
|
||||||
NEXT_PUBLIC_AI_WEBSITE_ID=
|
NEXT_PUBLIC_AI_WEBSITE_ID=
|
||||||
NEXT_PUBLIC_AI_API_ASSISTANT_RECAPTCHA_SITE_KEY=
|
NEXT_PUBLIC_AI_API_ASSISTANT_RECAPTCHA_SITE_KEY=
|
||||||
CLOUDINARY_CLOUD_NAME=
|
CLOUDINARY_CLOUD_NAME=
|
||||||
|
NEXT_PUBLIC_BASE_PATH=
|
||||||
@@ -118,36 +118,43 @@ In the route handler, you resolve the `UserService`, and then use it to retrieve
|
|||||||
|
|
||||||
## Protect Custom API Routes
|
## Protect Custom API Routes
|
||||||
|
|
||||||
To protect custom API Routes that don’t start with `/store/me` or `/admin`, apply one of the following middlewares exported by the `@medusajs/medusa` package on your routes:
|
To protect custom API Routes that don’t start with `/store/me` or `/admin`, use the `authenticate` middleware imported from `@medusajs/medusa`.
|
||||||
|
|
||||||
- `authenticate`: only authenticated admin users can access the API Route.
|
|
||||||
- `authenticateCustomer`: customer authentication isn’t required, but if a customer is logged in, it attaches their ID to the `MedusaRequest` object's `user.customer_id`.
|
|
||||||
- `requireCustomerAuthentication`: only authenticated customers can access the API Route.
|
|
||||||
|
|
||||||
For example:
|
For example:
|
||||||
|
|
||||||
export const highlights = [
|
export const highlights = [
|
||||||
["11", "authenticate", "Only authenticated admin users can access routes starting with `/custom/admin`"],
|
["11", "authenticate", "Only authenticated admin users can access routes starting with `/custom/admin`"],
|
||||||
["15", "requireCustomerAuthentication", "Only authenticated customers can access routes starting with `/custom/customers`"]
|
["17", "authenticate", "Only authenticated customers can access routes starting with `/custom/customers`"]
|
||||||
]
|
]
|
||||||
|
|
||||||
```ts title="src/api/middlewares.ts" highlights={highlights}
|
```ts title="src/api/middlewares.ts" highlights={highlights}
|
||||||
import {
|
// TODO update import
|
||||||
|
import {
|
||||||
authenticate,
|
authenticate,
|
||||||
requireCustomerAuthentication,
|
} from "@medusajs/medusa/dist/utils/authenticate-middleware"
|
||||||
type MiddlewaresConfig,
|
|
||||||
} from "@medusajs/medusa"
|
|
||||||
|
|
||||||
export const config: MiddlewaresConfig = {
|
export const config: MiddlewaresConfig = {
|
||||||
routes: [
|
routes: [
|
||||||
{
|
{
|
||||||
matcher: "/custom/admin*",
|
matcher: "/custom/admin*",
|
||||||
middlewares: [authenticate()],
|
middlewares: [
|
||||||
|
authenticate("admin", ["session", "bearer", "api-key"]),
|
||||||
|
],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
matcher: "/custom/customer*",
|
matcher: "/custom/customer*",
|
||||||
middlewares: [requireCustomerAuthentication()],
|
middlewares: [
|
||||||
|
authenticate("store", ["session", "bearer"]),
|
||||||
|
],
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
The `authenticate` middleware function accepts three parameters:
|
||||||
|
|
||||||
|
1. The scope of authentication. Use `admin` for authenticating admin users, and `store` for authenticating customers.
|
||||||
|
2. An array of the types of authentication methods allowed. Both `admin` and `store` scopes support `session` and `bearer`. The `admin` scope also supports the `api-key` authentication method.
|
||||||
|
3. An optional object of options having the following properties:
|
||||||
|
1. `allowUnauthenticated`: (default: `false`) A boolean indicating whether authentication is required. For example, you may have an API route where you want to access the logged-in customer if available, but guest customers can still access it too. In that case, enable the `allowUnauthenticated` option.
|
||||||
|
2. `allowUnregistered`: (default: `false`) A boolean indicating whether new users can be authenticated.
|
||||||
@@ -77,7 +77,7 @@ const deletedRecords = await helloModuleService
|
|||||||
.listMySoftDeletables({
|
.listMySoftDeletables({
|
||||||
// ...
|
// ...
|
||||||
}, {
|
}, {
|
||||||
withDeleted: true
|
withDeleted: true,
|
||||||
})
|
})
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|||||||
@@ -39,8 +39,6 @@ export const config: SubscriberConfig = {
|
|||||||
|
|
||||||
This logs the product ID received in the `ProductService.Events.CREATED` (`product-created`) event’s data payload to the console.
|
This logs the product ID received in the `ProductService.Events.CREATED` (`product-created`) event’s data payload to the console.
|
||||||
|
|
||||||
{/* TODO check first if the events list is still correct */}
|
## List of Events with Data Payload
|
||||||
|
|
||||||
{/* ## List of Events with Data Payload
|
Refer to [this reference](!resources!/events-reference) for a full list of events emitted by Medusa and their data payloads.
|
||||||
|
|
||||||
Refer to [this reference](!resources!/events-reference) for a full list of events emitted by Medusa and their data payloads. */}
|
|
||||||
@@ -79,9 +79,9 @@ The `CustomProductData` data model has a `product_id` field to reference the pro
|
|||||||
|
|
||||||
When you add a new data model, make sure to:
|
When you add a new data model, make sure to:
|
||||||
|
|
||||||
- Create a migration for it.
|
- [Create a migration for it.](../../../basics/data-models/page.mdx#create-a-migration)
|
||||||
- Add it to the second parameter of the main service's factory function.
|
- [Add it to the second parameter of the main service's factory function.](../service-factory/page.mdx#abstractModuleServiceFactory-parameters)
|
||||||
- Add it to the container and connection loaders.
|
- Add it to the [container](../container/page.mdx) and [connection](../connection-loader/page.mdx) loaders.
|
||||||
|
|
||||||
</Note>
|
</Note>
|
||||||
|
|
||||||
@@ -120,8 +120,8 @@ class HelloModuleService extends ModulesSdkUtils
|
|||||||
{
|
{
|
||||||
name: ["my_custom"],
|
name: ["my_custom"],
|
||||||
args: {
|
args: {
|
||||||
entity: MyCustom.name
|
entity: MyCustom.name,
|
||||||
}
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: ["custom_product_data"],
|
name: ["custom_product_data"],
|
||||||
@@ -157,23 +157,23 @@ This creates a relationship to the `Product` data model of the Product Module us
|
|||||||
name: "serviceName",
|
name: "serviceName",
|
||||||
type: "`string`",
|
type: "`string`",
|
||||||
optional: false,
|
optional: false,
|
||||||
description: "The name of the module (as added in `medusa-config.js`)."
|
description: "The name of your module (as added in `medusa-config.js`)."
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "primaryKeys",
|
name: "primaryKeys",
|
||||||
type: "`string[]`",
|
type: "`string[]`",
|
||||||
optional: false,
|
optional: false,
|
||||||
description: "The primary key field names used in the module's data models.",
|
description: "The primary key field names used in your module's data models.",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "alias",
|
name: "alias",
|
||||||
type: "`object[]`",
|
type: "`object[]`",
|
||||||
description: "The alias definitions for each data model in the module. This allows other modules to reference your module's data models in relationships.",
|
description: "The alias definitions for each data model in your module. This allows other modules to reference your module's data models in relationships.",
|
||||||
children: [
|
children: [
|
||||||
{
|
{
|
||||||
name: "name",
|
name: "name",
|
||||||
type: "`string[]`",
|
type: "`string[]`",
|
||||||
description: "The alias names used later when fetching or referencing the data in the model."
|
description: "The alias names of a data model used later when fetching or referencing the data model."
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "args",
|
name: "args",
|
||||||
@@ -197,19 +197,19 @@ This creates a relationship to the `Product` data model of the Product Module us
|
|||||||
{
|
{
|
||||||
name: "relationships",
|
name: "relationships",
|
||||||
type: "`object[]`",
|
type: "`object[]`",
|
||||||
description: "The module's relationships to other modules.",
|
description: "Your module's relationships to other modules.",
|
||||||
children: [
|
children: [
|
||||||
{
|
{
|
||||||
name: "serviceName",
|
name: "serviceName",
|
||||||
type: "`string`",
|
type: "`string`",
|
||||||
optional: false,
|
optional: false,
|
||||||
description: "The name of the module (as added in `medusa-config.js`) that this relationship is referencing. If you’re referencing a Medusa commerce module, use the `Modules` enum imported from `@medusajs/modules-sdk`."
|
description: "The name of the module (as added in `medusa-config.js`) that this relationship is referencing. When referencing a Medusa commerce module, use the `Modules` enum imported from `@medusajs/modules-sdk`."
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "alias",
|
name: "alias",
|
||||||
type: "`string`",
|
type: "`string`",
|
||||||
optional: false,
|
optional: false,
|
||||||
description: "The alias of the data model you’re referencing in the other module. You can find it in the `__joinerConfig` method of the other module."
|
description: "The alias of the data model you’re referencing in the other module. You can find it in the `__joinerConfig` method of the other module's service."
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "primaryKey",
|
name: "primaryKey",
|
||||||
|
|||||||
@@ -70,7 +70,7 @@ class HelloModuleService extends ModulesSdkUtils
|
|||||||
//...
|
//...
|
||||||
|
|
||||||
this.options_ = moduleOptions || {
|
this.options_ = moduleOptions || {
|
||||||
capitalize: false
|
capitalize: false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -98,14 +98,14 @@ const updateProduct = createStep(
|
|||||||
|
|
||||||
return {
|
return {
|
||||||
...variant,
|
...variant,
|
||||||
options: variantOptions
|
options: variantOptions,
|
||||||
}
|
}
|
||||||
}),
|
}),
|
||||||
options: options.map((option) => ({
|
options: options.map((option) => ({
|
||||||
...option,
|
...option,
|
||||||
values: option.values.map((value) => value.value)
|
values: option.values.map((value) => value.value),
|
||||||
})),
|
})),
|
||||||
type_id: type.id
|
type_id: type.id,
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ import { Inter, Roboto_Mono } from "next/font/google"
|
|||||||
import Navbar from "@/components/Navbar"
|
import Navbar from "@/components/Navbar"
|
||||||
import Providers from "@/providers"
|
import Providers from "@/providers"
|
||||||
import "./globals.css"
|
import "./globals.css"
|
||||||
import { TightLayout } from "docs-ui"
|
import { Bannerv2, TightLayout } from "docs-ui"
|
||||||
import { config } from "@/config"
|
import { config } from "@/config"
|
||||||
import clsx from "clsx"
|
import clsx from "clsx"
|
||||||
import Feedback from "@/components/Feedback"
|
import Feedback from "@/components/Feedback"
|
||||||
@@ -43,6 +43,7 @@ export default function RootLayout({
|
|||||||
NavbarComponent={Navbar}
|
NavbarComponent={Navbar}
|
||||||
sidebarProps={{
|
sidebarProps={{
|
||||||
expandItems: true,
|
expandItems: true,
|
||||||
|
banner: <Bannerv2 />,
|
||||||
}}
|
}}
|
||||||
showPagination={true}
|
showPagination={true}
|
||||||
bodyClassName={clsx(inter.variable, robotoMono.variable)}
|
bodyClassName={clsx(inter.variable, robotoMono.variable)}
|
||||||
|
|||||||
@@ -4,23 +4,34 @@ import {
|
|||||||
Feedback as UiFeedback,
|
Feedback as UiFeedback,
|
||||||
FeedbackProps as UiFeedbackProps,
|
FeedbackProps as UiFeedbackProps,
|
||||||
formatReportLink,
|
formatReportLink,
|
||||||
|
useIsBrowser,
|
||||||
} from "docs-ui"
|
} from "docs-ui"
|
||||||
import { usePathname } from "next/navigation"
|
import { usePathname } from "next/navigation"
|
||||||
import { config } from "../../config"
|
import { config } from "../../config"
|
||||||
|
import { basePathUrl } from "../../utils/base-path-url"
|
||||||
|
import { useMemo } from "react"
|
||||||
|
|
||||||
type FeedbackProps = Omit<UiFeedbackProps, "event" | "pathName">
|
type FeedbackProps = Omit<UiFeedbackProps, "event" | "pathName">
|
||||||
|
|
||||||
const Feedback = (props: FeedbackProps) => {
|
const Feedback = (props: FeedbackProps) => {
|
||||||
const pathname = usePathname()
|
const pathname = usePathname()
|
||||||
|
const isBrowser = useIsBrowser()
|
||||||
|
|
||||||
|
const feedbackPathname = useMemo(() => basePathUrl(pathname), [pathname])
|
||||||
|
const reportLink = useMemo(
|
||||||
|
() =>
|
||||||
|
formatReportLink(
|
||||||
|
config.titleSuffix || "",
|
||||||
|
isBrowser ? document.title : ""
|
||||||
|
),
|
||||||
|
[isBrowser]
|
||||||
|
)
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<UiFeedback
|
<UiFeedback
|
||||||
event="survey"
|
event="survey"
|
||||||
pathName={pathname}
|
pathName={feedbackPathname}
|
||||||
reportLink={formatReportLink(
|
reportLink={reportLink}
|
||||||
config.titleSuffix || "",
|
|
||||||
typeof document !== "undefined" ? document.title : ""
|
|
||||||
)}
|
|
||||||
question="Was this chapter helpful?"
|
question="Was this chapter helpful?"
|
||||||
{...props}
|
{...props}
|
||||||
/>
|
/>
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import { Navbar as UiNavbar, getNavbarItems } from "docs-ui"
|
|||||||
import { useSidebar } from "docs-ui"
|
import { useSidebar } from "docs-ui"
|
||||||
import { useMemo } from "react"
|
import { useMemo } from "react"
|
||||||
import { config } from "../../config"
|
import { config } from "../../config"
|
||||||
|
import { basePathUrl } from "../../utils/base-path-url"
|
||||||
|
|
||||||
const Navbar = () => {
|
const Navbar = () => {
|
||||||
const { setMobileSidebarOpen, mobileSidebarOpen } = useSidebar()
|
const { setMobileSidebarOpen, mobileSidebarOpen } = useSidebar()
|
||||||
@@ -12,7 +13,8 @@ const Navbar = () => {
|
|||||||
() =>
|
() =>
|
||||||
getNavbarItems({
|
getNavbarItems({
|
||||||
basePath: config.baseUrl,
|
basePath: config.baseUrl,
|
||||||
activePath: "/",
|
activePath: basePathUrl(""),
|
||||||
|
version: "v2",
|
||||||
}),
|
}),
|
||||||
[]
|
[]
|
||||||
)
|
)
|
||||||
@@ -20,8 +22,8 @@ const Navbar = () => {
|
|||||||
return (
|
return (
|
||||||
<UiNavbar
|
<UiNavbar
|
||||||
logo={{
|
logo={{
|
||||||
light: "/images/logo-icon.png",
|
light: basePathUrl("/images/logo-icon.png"),
|
||||||
dark: "/images/logo-icon-dark.png",
|
dark: basePathUrl("/images/logo-icon-dark.png"),
|
||||||
}}
|
}}
|
||||||
items={navbarItems}
|
items={navbarItems}
|
||||||
mobileMenuButton={{
|
mobileMenuButton={{
|
||||||
|
|||||||
@@ -2,7 +2,8 @@ import { DocsConfig } from "types"
|
|||||||
import { sidebarConfig } from "./sidebar"
|
import { sidebarConfig } from "./sidebar"
|
||||||
|
|
||||||
export const config: DocsConfig = {
|
export const config: DocsConfig = {
|
||||||
titleSuffix: "Medusa Book",
|
titleSuffix: "Medusa v2 Docs",
|
||||||
baseUrl: process.env.NEXT_PUBLIC_BASE_URL || "http://localhost:3000",
|
baseUrl: process.env.NEXT_PUBLIC_BASE_URL || "http://localhost:3000",
|
||||||
|
basePath: process.env.NEXT_PUBLIC_BASE_PATH,
|
||||||
sidebar: sidebarConfig,
|
sidebar: sidebarConfig,
|
||||||
}
|
}
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
import { Badge, mobileSidebarItems } from "docs-ui"
|
import { Badge, mobileSidebarItemsV2 } from "docs-ui"
|
||||||
import type { SidebarConfig, SidebarItemType } from "@/types"
|
import type { SidebarConfig, SidebarItemType } from "@/types"
|
||||||
import { sidebar } from "../sidebar.mjs"
|
import { sidebar } from "../sidebar.mjs"
|
||||||
|
|
||||||
@@ -20,5 +20,5 @@ const normalizeSidebarItems = (items: SidebarItemType[]) =>
|
|||||||
export const sidebarConfig: SidebarConfig = {
|
export const sidebarConfig: SidebarConfig = {
|
||||||
top: normalizeSidebarItems(sidebar),
|
top: normalizeSidebarItems(sidebar),
|
||||||
bottom: [],
|
bottom: [],
|
||||||
mobile: mobileSidebarItems,
|
mobile: mobileSidebarItemsV2,
|
||||||
}
|
}
|
||||||
@@ -14,7 +14,6 @@ const withMDX = mdx({
|
|||||||
extension: /\.mdx?$/,
|
extension: /\.mdx?$/,
|
||||||
options: {
|
options: {
|
||||||
rehypePlugins: [
|
rehypePlugins: [
|
||||||
// TODO add V2 to path if necessary
|
|
||||||
[
|
[
|
||||||
crossProjectLinksPlugin,
|
crossProjectLinksPlugin,
|
||||||
{
|
{
|
||||||
@@ -25,13 +24,14 @@ const withMDX = mdx({
|
|||||||
process.env.VERCEL_ENV !== "production"
|
process.env.VERCEL_ENV !== "production"
|
||||||
? process.env.NEXT_PUBLIC_RESOURCES_URL
|
? process.env.NEXT_PUBLIC_RESOURCES_URL
|
||||||
: undefined,
|
: undefined,
|
||||||
path: "resources",
|
path: "v2/resources",
|
||||||
},
|
},
|
||||||
"user-guide": {
|
"user-guide": {
|
||||||
url:
|
url:
|
||||||
process.env.VERCEL_ENV !== "production"
|
process.env.VERCEL_ENV !== "production"
|
||||||
? process.env.NEXT_PUBLIC_USER_GUIDE_URL
|
? process.env.NEXT_PUBLIC_USER_GUIDE_URL
|
||||||
: undefined,
|
: undefined,
|
||||||
|
path: "v2/user-guide",
|
||||||
},
|
},
|
||||||
ui: {
|
ui: {
|
||||||
url:
|
url:
|
||||||
@@ -90,31 +90,7 @@ const nextConfig = {
|
|||||||
pageExtensions: ["js", "jsx", "mdx", "ts", "tsx"],
|
pageExtensions: ["js", "jsx", "mdx", "ts", "tsx"],
|
||||||
|
|
||||||
transpilePackages: ["docs-ui"],
|
transpilePackages: ["docs-ui"],
|
||||||
// TODO uncomment if we decide on baes path
|
basePath: process.env.NEXT_PUBLIC_BASE_PATH || "/v2",
|
||||||
// basePath: process.env.NEXT_PUBLIC_BASE_PATH || "/v2",
|
|
||||||
async rewrites() {
|
|
||||||
return {
|
|
||||||
fallback: [
|
|
||||||
{
|
|
||||||
source: "/resources",
|
|
||||||
destination: `${process.env.NEXT_PUBLIC_RESOURCES_URL}/resources`,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
source: "/resources/:path*",
|
|
||||||
destination: `${process.env.NEXT_PUBLIC_RESOURCES_URL}/resources/:path*`,
|
|
||||||
},
|
|
||||||
// TODO comment out once we have the user guide published
|
|
||||||
// {
|
|
||||||
// source: "/user-guide",
|
|
||||||
// destination: `${process.env.NEXT_PUBLIC_USER_GUIDE_URL}/user-guide`,
|
|
||||||
// },
|
|
||||||
// {
|
|
||||||
// source: "/user-guide/:path*",
|
|
||||||
// destination: `${process.env.NEXT_PUBLIC_USER_GUIDE_URL}/user-guide/:path*`,
|
|
||||||
// },
|
|
||||||
],
|
|
||||||
}
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export default withMDX(nextConfig)
|
export default withMDX(nextConfig)
|
||||||
@@ -1,11 +1,6 @@
|
|||||||
"use client"
|
"use client"
|
||||||
|
|
||||||
import {
|
import { SearchProvider as UiSearchProvider, searchFiltersV2 } from "docs-ui"
|
||||||
SearchProvider as UiSearchProvider,
|
|
||||||
AiAssistantCommandIcon,
|
|
||||||
AiAssistantProvider,
|
|
||||||
searchFilters,
|
|
||||||
} from "docs-ui"
|
|
||||||
import { config } from "../config"
|
import { config } from "../config"
|
||||||
|
|
||||||
type SearchProviderProps = {
|
type SearchProviderProps = {
|
||||||
@@ -32,15 +27,15 @@ const SearchProvider = ({ children }: SearchProviderProps) => {
|
|||||||
title: "Getting started? Try one of the following terms.",
|
title: "Getting started? Try one of the following terms.",
|
||||||
items: [
|
items: [
|
||||||
"Install Medusa with create-medusa-app",
|
"Install Medusa with create-medusa-app",
|
||||||
"What is a Service?",
|
|
||||||
"What is an API route?",
|
"What is an API route?",
|
||||||
|
"What is a Module?",
|
||||||
"What is a Workflow?",
|
"What is a Workflow?",
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: "Developing with Medusa",
|
title: "Developing with Medusa",
|
||||||
items: [
|
items: [
|
||||||
"How to create a Service",
|
"How to create a Module",
|
||||||
"How to create an API route",
|
"How to create an API route",
|
||||||
"How to create a data model",
|
"How to create a data model",
|
||||||
"How to create an admin widget",
|
"How to create an admin widget",
|
||||||
@@ -48,32 +43,11 @@ const SearchProvider = ({ children }: SearchProviderProps) => {
|
|||||||
},
|
},
|
||||||
],
|
],
|
||||||
checkInternalPattern: new RegExp(
|
checkInternalPattern: new RegExp(
|
||||||
`^${config.baseUrl}/([^(api|ui|resources)]/)*`
|
`^${config.baseUrl}/v2/([^(resources)])*`
|
||||||
),
|
),
|
||||||
filterOptions: searchFilters,
|
filterOptions: searchFiltersV2,
|
||||||
}}
|
}}
|
||||||
initialDefaultFilters={["docs"]}
|
initialDefaultFilters={["book"]}
|
||||||
commands={[
|
|
||||||
{
|
|
||||||
name: "ai-assistant",
|
|
||||||
icon: <AiAssistantCommandIcon />,
|
|
||||||
component: (
|
|
||||||
<AiAssistantProvider
|
|
||||||
apiUrl={process.env.NEXT_PUBLIC_AI_ASSISTANT_URL || "temp"}
|
|
||||||
websiteId={process.env.NEXT_PUBLIC_AI_WEBSITE_ID || "temp"}
|
|
||||||
recaptchaSiteKey={
|
|
||||||
process.env.NEXT_PUBLIC_AI_API_ASSISTANT_RECAPTCHA_SITE_KEY ||
|
|
||||||
"temp"
|
|
||||||
}
|
|
||||||
/>
|
|
||||||
),
|
|
||||||
title: "AI Assistant",
|
|
||||||
badge: {
|
|
||||||
variant: "purple",
|
|
||||||
children: "Beta",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
]}
|
|
||||||
>
|
>
|
||||||
{children}
|
{children}
|
||||||
</UiSearchProvider>
|
</UiSearchProvider>
|
||||||
|
|||||||
@@ -0,0 +1,3 @@
|
|||||||
|
export function basePathUrl(path = "") {
|
||||||
|
return `${process.env.NEXT_PUBLIC_BASE_PATH || ""}${path}`
|
||||||
|
}
|
||||||
@@ -1,5 +1,4 @@
|
|||||||
import { Table } from "docs-ui"
|
import { Table, TypeList } from "docs-ui"
|
||||||
import TypeList from "@/components/TypeList"
|
|
||||||
|
|
||||||
export const metadata = {
|
export const metadata = {
|
||||||
title: `Medusa Admin Configurations`,
|
title: `Medusa Admin Configurations`,
|
||||||
|
|||||||
@@ -175,7 +175,9 @@ The client accepts the following options on initialization:
|
|||||||
</Table.Cell>
|
</Table.Cell>
|
||||||
<Table.Cell>
|
<Table.Cell>
|
||||||
|
|
||||||
A string indicating publishable API key used for storefront requests. You can create a publishable API key either using the [Medusa Admin](!user-guide!/settings/developer/api-key-management) or the [Admin API Routes](https://docs.medusajs.com/api/admin#publishable-api-keys).
|
{/* TODO add link [Medusa Admin](!user-guide!/settings/developer/api-key-management) */}
|
||||||
|
|
||||||
|
A string indicating publishable API key used for storefront requests. You can create a publishable API key either using the Medusa Admin or the [Admin API Routes](https://docs.medusajs.com/api/admin#publishable-api-keys).
|
||||||
|
|
||||||
</Table.Cell>
|
</Table.Cell>
|
||||||
<Table.Cell>
|
<Table.Cell>
|
||||||
@@ -408,7 +410,9 @@ You can learn more about publishable API keys and how to use them in [this docum
|
|||||||
|
|
||||||
### Create a Publishable API Key
|
### Create a Publishable API Key
|
||||||
|
|
||||||
You can create a publishable API key either using the [Admin API Routes](https://docs.medusajs.com/api/admin#publishable-api-keys), or using the [Medusa Admin](!user-guide!/settings/developer/api-key-management).
|
{/* TODO add link [Medusa Admin](!user-guide!/settings/developer/api-key-management) */}
|
||||||
|
|
||||||
|
You can create a publishable API key either using the [Admin API Routes](https://docs.medusajs.com/api/admin#publishable-api-keys), or using the Medusa Admin.
|
||||||
|
|
||||||
### Use a Publishable API Key
|
### Use a Publishable API Key
|
||||||
|
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ import { Inter, Roboto_Mono } from "next/font/google"
|
|||||||
import Navbar from "@/components/Navbar"
|
import Navbar from "@/components/Navbar"
|
||||||
import Providers from "@/providers"
|
import Providers from "@/providers"
|
||||||
import "./globals.css"
|
import "./globals.css"
|
||||||
import { TightLayout } from "docs-ui"
|
import { Bannerv2, Breadcrumbs, TightLayout } from "docs-ui"
|
||||||
import { config } from "@/config"
|
import { config } from "@/config"
|
||||||
import clsx from "clsx"
|
import clsx from "clsx"
|
||||||
import { Feedback } from "@/components/Feedback"
|
import { Feedback } from "@/components/Feedback"
|
||||||
@@ -44,9 +44,11 @@ export default function RootLayout({
|
|||||||
NavbarComponent={Navbar}
|
NavbarComponent={Navbar}
|
||||||
sidebarProps={{
|
sidebarProps={{
|
||||||
expandItems: true,
|
expandItems: true,
|
||||||
|
banner: <Bannerv2 />,
|
||||||
}}
|
}}
|
||||||
bodyClassName={clsx(inter.variable, robotoMono.variable)}
|
bodyClassName={clsx(inter.variable, robotoMono.variable)}
|
||||||
>
|
>
|
||||||
|
<Breadcrumbs />
|
||||||
{children}
|
{children}
|
||||||
<Feedback className="my-2" />
|
<Feedback className="my-2" />
|
||||||
<EditButton />
|
<EditButton />
|
||||||
|
|||||||
@@ -327,7 +327,9 @@ You can learn more about publishable API keys and how to use them in [this docum
|
|||||||
|
|
||||||
### Create a Publishable API Key
|
### Create a Publishable API Key
|
||||||
|
|
||||||
You can create a publishable API key either using the [Admin API Routes](https://docs.medusajs.com/api/admin#publishable-api-keys), or using the [Medusa Admin](!user-guide!/settings/developer/api-key-management).
|
{/* TODO add link [Medusa Admin](!user-guide!/settings/developer/api-key-management) */}
|
||||||
|
|
||||||
|
You can create a publishable API key either using the [Admin API Routes](https://docs.medusajs.com/api/admin#publishable-api-keys), or using the Medusa Admin.
|
||||||
|
|
||||||
### Use a Publishable API Key
|
### Use a Publishable API Key
|
||||||
|
|
||||||
|
|||||||
@@ -4,23 +4,34 @@ import {
|
|||||||
Feedback as UiFeedback,
|
Feedback as UiFeedback,
|
||||||
FeedbackProps as UiFeedbackProps,
|
FeedbackProps as UiFeedbackProps,
|
||||||
formatReportLink,
|
formatReportLink,
|
||||||
|
useIsBrowser,
|
||||||
} from "docs-ui"
|
} from "docs-ui"
|
||||||
import { usePathname } from "next/navigation"
|
import { usePathname } from "next/navigation"
|
||||||
import { config } from "../../config"
|
import { config } from "../../config"
|
||||||
|
import { useMemo } from "react"
|
||||||
|
import { basePathUrl } from "../../utils/base-path-url"
|
||||||
|
|
||||||
type FeedbackProps = Omit<UiFeedbackProps, "event" | "pathName">
|
type FeedbackProps = Omit<UiFeedbackProps, "event" | "pathName">
|
||||||
|
|
||||||
export const Feedback = (props: FeedbackProps) => {
|
export const Feedback = (props: FeedbackProps) => {
|
||||||
const pathname = usePathname()
|
const pathname = usePathname()
|
||||||
|
const isBrowser = useIsBrowser()
|
||||||
|
|
||||||
|
const feedbackPathname = useMemo(() => basePathUrl(pathname), [pathname])
|
||||||
|
const reportLink = useMemo(
|
||||||
|
() =>
|
||||||
|
formatReportLink(
|
||||||
|
config.titleSuffix || "",
|
||||||
|
isBrowser ? document.title : ""
|
||||||
|
),
|
||||||
|
[isBrowser]
|
||||||
|
)
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<UiFeedback
|
<UiFeedback
|
||||||
event="survey"
|
event="survey"
|
||||||
pathName={pathname}
|
pathName={feedbackPathname}
|
||||||
reportLink={formatReportLink(
|
reportLink={reportLink}
|
||||||
config.titleSuffix || "",
|
|
||||||
typeof document !== "undefined" ? document.title : ""
|
|
||||||
)}
|
|
||||||
question="Was this page helpful?"
|
question="Was this page helpful?"
|
||||||
{...props}
|
{...props}
|
||||||
/>
|
/>
|
||||||
|
|||||||
@@ -12,7 +12,8 @@ const Navbar = () => {
|
|||||||
() =>
|
() =>
|
||||||
getNavbarItems({
|
getNavbarItems({
|
||||||
basePath: config.baseUrl,
|
basePath: config.baseUrl,
|
||||||
activePath: process.env.NEXT_PUBLIC_BASE_PATH || "/resources",
|
activePath: basePathUrl(""),
|
||||||
|
version: "v2",
|
||||||
}),
|
}),
|
||||||
[]
|
[]
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -1,9 +0,0 @@
|
|||||||
import { TypeList as UiTypeList } from "docs-ui"
|
|
||||||
import { ComponentProps } from "react"
|
|
||||||
import { config } from "@/config"
|
|
||||||
|
|
||||||
const TypeList = (props: ComponentProps<typeof UiTypeList>) => {
|
|
||||||
return <UiTypeList {...props} siteUrl={config.baseUrl} />
|
|
||||||
}
|
|
||||||
|
|
||||||
export default TypeList
|
|
||||||
@@ -1,13 +1,14 @@
|
|||||||
import { DocsConfig } from "types"
|
import { DocsConfig } from "types"
|
||||||
import { mobileSidebarItems } from "docs-ui"
|
import { mobileSidebarItemsV2 } from "docs-ui"
|
||||||
import { generatedSidebar } from "../generated/sidebar.mjs"
|
import { generatedSidebar } from "../generated/sidebar.mjs"
|
||||||
|
|
||||||
export const config: DocsConfig = {
|
export const config: DocsConfig = {
|
||||||
titleSuffix: "Medusa Resources",
|
titleSuffix: "Medusa Resources",
|
||||||
baseUrl: process.env.NEXT_PUBLIC_BASE_URL || "http://localhost:3000",
|
baseUrl: process.env.NEXT_PUBLIC_BASE_URL || "http://localhost:3000",
|
||||||
|
basePath: process.env.NEXT_PUBLIC_BASE_PATH,
|
||||||
sidebar: {
|
sidebar: {
|
||||||
top: generatedSidebar,
|
top: generatedSidebar,
|
||||||
bottom: [],
|
bottom: [],
|
||||||
mobile: mobileSidebarItems,
|
mobile: mobileSidebarItemsV2,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
@@ -12,7 +12,6 @@ import remarkDirective from "remark-directive"
|
|||||||
const mdxPluginOptions = {
|
const mdxPluginOptions = {
|
||||||
options: {
|
options: {
|
||||||
rehypePlugins: [
|
rehypePlugins: [
|
||||||
// TODO add V2 to path if necessary
|
|
||||||
[
|
[
|
||||||
crossProjectLinksPlugin,
|
crossProjectLinksPlugin,
|
||||||
{
|
{
|
||||||
@@ -23,13 +22,14 @@ const mdxPluginOptions = {
|
|||||||
process.env.VERCEL_ENV !== "production"
|
process.env.VERCEL_ENV !== "production"
|
||||||
? process.env.NEXT_PUBLIC_DOCS_URL
|
? process.env.NEXT_PUBLIC_DOCS_URL
|
||||||
: undefined,
|
: undefined,
|
||||||
|
path: "v2",
|
||||||
},
|
},
|
||||||
"user-guide": {
|
"user-guide": {
|
||||||
url:
|
url:
|
||||||
process.env.VERCEL_ENV !== "production"
|
process.env.VERCEL_ENV !== "production"
|
||||||
? process.env.NEXT_PUBLIC_USER_GUIDE_URL
|
? process.env.NEXT_PUBLIC_USER_GUIDE_URL
|
||||||
: undefined,
|
: undefined,
|
||||||
path: "user-guide",
|
path: "v2/user-guide",
|
||||||
},
|
},
|
||||||
ui: {
|
ui: {
|
||||||
url:
|
url:
|
||||||
|
|||||||
@@ -28,9 +28,7 @@ const nextConfig = {
|
|||||||
|
|
||||||
transpilePackages: ["docs-ui"],
|
transpilePackages: ["docs-ui"],
|
||||||
|
|
||||||
// TODO uncomment if we decide on baes path
|
basePath: process.env.NEXT_PUBLIC_BASE_PATH || "/v2/resources",
|
||||||
// basePath: process.env.NEXT_PUBLIC_BASE_PATH || "/v2/resources",
|
|
||||||
basePath: process.env.NEXT_PUBLIC_BASE_PATH || "/resources",
|
|
||||||
async rewrites() {
|
async rewrites() {
|
||||||
return {
|
return {
|
||||||
fallback: [
|
fallback: [
|
||||||
|
|||||||
@@ -1,11 +1,6 @@
|
|||||||
"use client"
|
"use client"
|
||||||
|
|
||||||
import {
|
import { SearchProvider as UiSearchProvider, searchFiltersV2 } from "docs-ui"
|
||||||
SearchProvider as UiSearchProvider,
|
|
||||||
AiAssistantCommandIcon,
|
|
||||||
AiAssistantProvider,
|
|
||||||
searchFilters,
|
|
||||||
} from "docs-ui"
|
|
||||||
import { config } from "../config"
|
import { config } from "../config"
|
||||||
|
|
||||||
type SearchProviderProps = {
|
type SearchProviderProps = {
|
||||||
@@ -39,32 +34,10 @@ const SearchProvider = ({ children }: SearchProviderProps) => {
|
|||||||
],
|
],
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
checkInternalPattern: new RegExp(`^${config.baseUrl}/resources/.*`),
|
checkInternalPattern: new RegExp(`^${config.baseUrl}/v2/resources/.*`),
|
||||||
filterOptions: searchFilters,
|
filterOptions: searchFiltersV2,
|
||||||
}}
|
}}
|
||||||
// TODO change once we have a dedicated index
|
initialDefaultFilters={["resources"]}
|
||||||
initialDefaultFilters={["docs"]}
|
|
||||||
commands={[
|
|
||||||
{
|
|
||||||
name: "ai-assistant",
|
|
||||||
icon: <AiAssistantCommandIcon />,
|
|
||||||
component: (
|
|
||||||
<AiAssistantProvider
|
|
||||||
apiUrl={process.env.NEXT_PUBLIC_AI_ASSISTANT_URL || "temp"}
|
|
||||||
websiteId={process.env.NEXT_PUBLIC_AI_WEBSITE_ID || "temp"}
|
|
||||||
recaptchaSiteKey={
|
|
||||||
process.env.NEXT_PUBLIC_AI_API_ASSISTANT_RECAPTCHA_SITE_KEY ||
|
|
||||||
"temp"
|
|
||||||
}
|
|
||||||
/>
|
|
||||||
),
|
|
||||||
title: "AI Assistant",
|
|
||||||
badge: {
|
|
||||||
variant: "purple",
|
|
||||||
children: "Beta",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
]}
|
|
||||||
>
|
>
|
||||||
{children}
|
{children}
|
||||||
</UiSearchProvider>
|
</UiSearchProvider>
|
||||||
|
|||||||
@@ -8,4 +8,5 @@ NEXT_PUBLIC_ALGOLIA_APP_ID=
|
|||||||
NEXT_PUBLIC_SEGMENT_API_KEY=
|
NEXT_PUBLIC_SEGMENT_API_KEY=
|
||||||
NEXT_PUBLIC_AI_ASSISTANT_URL=
|
NEXT_PUBLIC_AI_ASSISTANT_URL=
|
||||||
NEXT_PUBLIC_AI_WEBSITE_ID=
|
NEXT_PUBLIC_AI_WEBSITE_ID=
|
||||||
NEXT_PUBLIC_AI_API_ASSISTANT_RECAPTCHA_SITE_KEY=
|
NEXT_PUBLIC_AI_API_ASSISTANT_RECAPTCHA_SITE_KEY=
|
||||||
|
NEXT_PUBLIC_SHOW_V2=
|
||||||
@@ -1,10 +1,15 @@
|
|||||||
import { ArrowUpRightOnBox } from "@medusajs/icons"
|
import { ArrowUpRightOnBox } from "@medusajs/icons"
|
||||||
import { NavbarLinkProps, getNavbarItems, mobileSidebarItems } from "docs-ui"
|
import {
|
||||||
|
NavbarItem,
|
||||||
|
getNavbarItems,
|
||||||
|
legacyMobileSidebarItems,
|
||||||
|
mobileSidebarItemsV1,
|
||||||
|
} from "docs-ui"
|
||||||
import { SidebarSectionItemsType } from "types"
|
import { SidebarSectionItemsType } from "types"
|
||||||
import { siteConfig } from "./site"
|
import { siteConfig } from "./site"
|
||||||
|
|
||||||
type DocsConfig = {
|
type DocsConfig = {
|
||||||
mainNav: NavbarLinkProps[]
|
mainNav: NavbarItem[]
|
||||||
sidebar: SidebarSectionItemsType
|
sidebar: SidebarSectionItemsType
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -12,6 +17,7 @@ export const docsConfig: DocsConfig = {
|
|||||||
mainNav: getNavbarItems({
|
mainNav: getNavbarItems({
|
||||||
basePath: siteConfig.baseUrl,
|
basePath: siteConfig.baseUrl,
|
||||||
activePath: process.env.NEXT_PUBLIC_BASE_PATH || "/ui",
|
activePath: process.env.NEXT_PUBLIC_BASE_PATH || "/ui",
|
||||||
|
version: process.env.NEXT_PUBLIC_SHOW_V2 ? "v1" : "legacy",
|
||||||
}),
|
}),
|
||||||
sidebar: {
|
sidebar: {
|
||||||
top: [
|
top: [
|
||||||
@@ -279,6 +285,8 @@ export const docsConfig: DocsConfig = {
|
|||||||
],
|
],
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
mobile: mobileSidebarItems,
|
mobile: process.env.NEXT_PUBLIC_SHOW_V2
|
||||||
|
? mobileSidebarItemsV1
|
||||||
|
: legacyMobileSidebarItems,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
@@ -11,6 +11,7 @@ const baseUrl = process.env.NEXT_PUBLIC_DOCS_URL || "http://localhost:3000"
|
|||||||
export const siteConfig: SiteConfig = {
|
export const siteConfig: SiteConfig = {
|
||||||
name: "Medusa UI",
|
name: "Medusa UI",
|
||||||
baseUrl,
|
baseUrl,
|
||||||
|
basePath: process.env.NEXT_PUBLIC_BASE_PATH,
|
||||||
url: `${baseUrl}/${process.env.NEXT_PUBLIC_BASE_PATH}`,
|
url: `${baseUrl}/${process.env.NEXT_PUBLIC_BASE_PATH}`,
|
||||||
description: "Primitives for building Medusa applications.",
|
description: "Primitives for building Medusa applications.",
|
||||||
// sidebar is defined in docs.tsx
|
// sidebar is defined in docs.tsx
|
||||||
|
|||||||
@@ -1,3 +1,3 @@
|
|||||||
export function basePathUrl(path = "") {
|
export function basePathUrl(path = "") {
|
||||||
return `${process.env.NEXT_PUBLIC_BASE_PATH}${path}`
|
return `${process.env.NEXT_PUBLIC_BASE_PATH || ""}${path}`
|
||||||
}
|
}
|
||||||
@@ -4,7 +4,7 @@ import {
|
|||||||
AiAssistantCommandIcon,
|
AiAssistantCommandIcon,
|
||||||
AiAssistantProvider,
|
AiAssistantProvider,
|
||||||
SearchProvider as UiSearchProvider,
|
SearchProvider as UiSearchProvider,
|
||||||
searchFilters,
|
searchFiltersV1,
|
||||||
} from "docs-ui"
|
} from "docs-ui"
|
||||||
import { absoluteUrl } from "../lib/absolute-url"
|
import { absoluteUrl } from "../lib/absolute-url"
|
||||||
|
|
||||||
@@ -34,7 +34,7 @@ const SearchProvider = ({ children }: SearchProviderProps) => {
|
|||||||
},
|
},
|
||||||
],
|
],
|
||||||
checkInternalPattern: new RegExp(`^${absoluteUrl()}/ui`),
|
checkInternalPattern: new RegExp(`^${absoluteUrl()}/ui`),
|
||||||
filterOptions: searchFilters,
|
filterOptions: searchFiltersV1,
|
||||||
}}
|
}}
|
||||||
initialDefaultFilters={["ui"]}
|
initialDefaultFilters={["ui"]}
|
||||||
commands={[
|
commands={[
|
||||||
|
|||||||
@@ -4,23 +4,34 @@ import {
|
|||||||
Feedback as UiFeedback,
|
Feedback as UiFeedback,
|
||||||
FeedbackProps as UiFeedbackProps,
|
FeedbackProps as UiFeedbackProps,
|
||||||
formatReportLink,
|
formatReportLink,
|
||||||
|
useIsBrowser,
|
||||||
} from "docs-ui"
|
} from "docs-ui"
|
||||||
import { usePathname } from "next/navigation"
|
import { usePathname } from "next/navigation"
|
||||||
import { config } from "../../config"
|
import { config } from "../../config"
|
||||||
|
import { basePathUrl } from "../../utils/base-path-url"
|
||||||
|
import { useMemo } from "react"
|
||||||
|
|
||||||
type FeedbackProps = Omit<UiFeedbackProps, "event" | "pathName">
|
type FeedbackProps = Omit<UiFeedbackProps, "event" | "pathName">
|
||||||
|
|
||||||
const Feedback = (props: FeedbackProps) => {
|
const Feedback = (props: FeedbackProps) => {
|
||||||
const pathname = usePathname()
|
const pathname = usePathname()
|
||||||
|
const isBrowser = useIsBrowser()
|
||||||
|
|
||||||
|
const feedbackPathname = useMemo(() => basePathUrl(pathname), [pathname])
|
||||||
|
const reportLink = useMemo(
|
||||||
|
() =>
|
||||||
|
formatReportLink(
|
||||||
|
config.titleSuffix || "",
|
||||||
|
isBrowser ? document.title : ""
|
||||||
|
),
|
||||||
|
[isBrowser]
|
||||||
|
)
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<UiFeedback
|
<UiFeedback
|
||||||
event="survey"
|
event="survey"
|
||||||
pathName={pathname}
|
pathName={feedbackPathname}
|
||||||
reportLink={formatReportLink(
|
reportLink={reportLink}
|
||||||
config.titleSuffix || "",
|
|
||||||
typeof document !== "undefined" ? document.title : ""
|
|
||||||
)}
|
|
||||||
question="Was this chapter helpful?"
|
question="Was this chapter helpful?"
|
||||||
{...props}
|
{...props}
|
||||||
/>
|
/>
|
||||||
|
|||||||
@@ -14,6 +14,7 @@ const Navbar = () => {
|
|||||||
getNavbarItems({
|
getNavbarItems({
|
||||||
basePath: config.baseUrl,
|
basePath: config.baseUrl,
|
||||||
activePath: process.env.NEXT_PUBLIC_BASE_PATH || "/user-guide",
|
activePath: process.env.NEXT_PUBLIC_BASE_PATH || "/user-guide",
|
||||||
|
version: "v2",
|
||||||
}),
|
}),
|
||||||
[]
|
[]
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -1,13 +1,14 @@
|
|||||||
import { DocsConfig } from "types"
|
import { DocsConfig } from "types"
|
||||||
import { mobileSidebarItems } from "docs-ui"
|
import { mobileSidebarItemsV2 } from "docs-ui"
|
||||||
import { generatedSidebar as sidebar } from "@/generated/sidebar.mjs"
|
import { generatedSidebar as sidebar } from "@/generated/sidebar.mjs"
|
||||||
|
|
||||||
export const config: DocsConfig = {
|
export const config: DocsConfig = {
|
||||||
titleSuffix: "Medusa Admin User Guide",
|
titleSuffix: "Medusa Admin User Guide",
|
||||||
baseUrl: process.env.NEXT_PUBLIC_BASE_URL || "http://localhost:3000",
|
baseUrl: process.env.NEXT_PUBLIC_BASE_URL || "http://localhost:3000",
|
||||||
|
basePath: process.env.NEXT_PUBLIC_BASE_PATH,
|
||||||
sidebar: {
|
sidebar: {
|
||||||
top: sidebar,
|
top: sidebar,
|
||||||
bottom: [],
|
bottom: [],
|
||||||
mobile: mobileSidebarItems,
|
mobile: mobileSidebarItemsV2,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
@@ -4,7 +4,7 @@ import {
|
|||||||
SearchProvider as UiSearchProvider,
|
SearchProvider as UiSearchProvider,
|
||||||
AiAssistantCommandIcon,
|
AiAssistantCommandIcon,
|
||||||
AiAssistantProvider,
|
AiAssistantProvider,
|
||||||
searchFilters,
|
searchFiltersV1,
|
||||||
} from "docs-ui"
|
} from "docs-ui"
|
||||||
import { config } from "../config"
|
import { config } from "../config"
|
||||||
|
|
||||||
@@ -42,7 +42,7 @@ const SearchProvider = ({ children }: SearchProviderProps) => {
|
|||||||
},
|
},
|
||||||
],
|
],
|
||||||
checkInternalPattern: new RegExp(`^${config.baseUrl}/user-guide`),
|
checkInternalPattern: new RegExp(`^${config.baseUrl}/user-guide`),
|
||||||
filterOptions: searchFilters,
|
filterOptions: searchFiltersV1,
|
||||||
}}
|
}}
|
||||||
initialDefaultFilters={["user-guide"]}
|
initialDefaultFilters={["user-guide"]}
|
||||||
commands={[
|
commands={[
|
||||||
|
|||||||
@@ -0,0 +1,15 @@
|
|||||||
|
import React from "react"
|
||||||
|
import { Card, Link } from "../.."
|
||||||
|
|
||||||
|
export const Bannerv2 = () => {
|
||||||
|
return (
|
||||||
|
<Card>
|
||||||
|
This documentation is for Medusa v2, which isn't ready for
|
||||||
|
production.
|
||||||
|
<br />
|
||||||
|
<br />
|
||||||
|
For production-use, refer to{" "}
|
||||||
|
<Link href="https://docs.medusajs.com">this documentation</Link> instead.
|
||||||
|
</Card>
|
||||||
|
)
|
||||||
|
}
|
||||||
@@ -0,0 +1,76 @@
|
|||||||
|
"use client"
|
||||||
|
|
||||||
|
import React, { useMemo } from "react"
|
||||||
|
import { CurrentItemsState, useSidebar } from "@/providers"
|
||||||
|
import { TriangleRightMini } from "@medusajs/icons"
|
||||||
|
import Link from "next/link"
|
||||||
|
import clsx from "clsx"
|
||||||
|
|
||||||
|
type BreadcrumbItem = Map<string, string>
|
||||||
|
|
||||||
|
export const Breadcrumbs = () => {
|
||||||
|
const { currentItems } = useSidebar()
|
||||||
|
|
||||||
|
const getBreadcrumbsOfItem = (item: CurrentItemsState): BreadcrumbItem => {
|
||||||
|
let tempBreadcrumbItems: BreadcrumbItem = new Map()
|
||||||
|
if (item.previousSidebar) {
|
||||||
|
tempBreadcrumbItems = getBreadcrumbsOfItem(item.previousSidebar)
|
||||||
|
}
|
||||||
|
|
||||||
|
tempBreadcrumbItems.set(
|
||||||
|
item.parentItem?.path || item.top[0].path || "/",
|
||||||
|
item.parentItem?.childSidebarTitle || item.parentItem?.title || ""
|
||||||
|
)
|
||||||
|
|
||||||
|
return tempBreadcrumbItems
|
||||||
|
}
|
||||||
|
|
||||||
|
const breadcrumbItems = useMemo(() => {
|
||||||
|
const tempBreadcrumbItems: BreadcrumbItem = new Map()
|
||||||
|
if (!currentItems) {
|
||||||
|
return tempBreadcrumbItems
|
||||||
|
}
|
||||||
|
|
||||||
|
tempBreadcrumbItems.set("/", "Home")
|
||||||
|
|
||||||
|
getBreadcrumbsOfItem(currentItems).forEach((value, key) =>
|
||||||
|
tempBreadcrumbItems.set(key, value)
|
||||||
|
)
|
||||||
|
|
||||||
|
return tempBreadcrumbItems
|
||||||
|
}, [currentItems])
|
||||||
|
|
||||||
|
const getBreadcrumbItemElms = (): React.ReactNode[] => {
|
||||||
|
const elms: React.ReactNode[] = []
|
||||||
|
breadcrumbItems.forEach((title, path) => {
|
||||||
|
elms.push(
|
||||||
|
<React.Fragment key={path}>
|
||||||
|
{elms.length !== 0 && (
|
||||||
|
<TriangleRightMini className={clsx("text-medusa-fg-muted")} />
|
||||||
|
)}
|
||||||
|
<Link
|
||||||
|
href={path}
|
||||||
|
className={clsx(
|
||||||
|
"text-compact-x-small-plus text-medusa-fg-muted",
|
||||||
|
"hover:text-medusa-fg-subtle transition-colors"
|
||||||
|
)}
|
||||||
|
>
|
||||||
|
{title}
|
||||||
|
</Link>
|
||||||
|
</React.Fragment>
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|
||||||
|
return elms
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
{breadcrumbItems.size > 0 && (
|
||||||
|
<div className="flex gap-docs_0.25 items-center mb-docs_1">
|
||||||
|
{...getBreadcrumbItemElms()}
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</>
|
||||||
|
)
|
||||||
|
}
|
||||||
@@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
import React from "react"
|
import React from "react"
|
||||||
import clsx from "clsx"
|
import clsx from "clsx"
|
||||||
import { Link, LinkProps } from "@/components"
|
import { Badge, BadgeProps, Link, LinkProps } from "@/components"
|
||||||
|
|
||||||
export type NavbarLinkProps = {
|
export type NavbarLinkProps = {
|
||||||
href: string
|
href: string
|
||||||
@@ -10,6 +10,7 @@ export type NavbarLinkProps = {
|
|||||||
className?: string
|
className?: string
|
||||||
activeValuePattern?: RegExp
|
activeValuePattern?: RegExp
|
||||||
isActive?: boolean
|
isActive?: boolean
|
||||||
|
badge?: BadgeProps
|
||||||
} & LinkProps
|
} & LinkProps
|
||||||
|
|
||||||
export const NavbarLink = ({
|
export const NavbarLink = ({
|
||||||
@@ -17,6 +18,7 @@ export const NavbarLink = ({
|
|||||||
label,
|
label,
|
||||||
className,
|
className,
|
||||||
isActive,
|
isActive,
|
||||||
|
badge
|
||||||
}: NavbarLinkProps) => {
|
}: NavbarLinkProps) => {
|
||||||
return (
|
return (
|
||||||
<Link
|
<Link
|
||||||
@@ -30,6 +32,10 @@ export const NavbarLink = ({
|
|||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
{label}
|
{label}
|
||||||
|
{badge && <Badge {...badge} className={clsx(
|
||||||
|
badge.className,
|
||||||
|
"ml-docs_0.5"
|
||||||
|
)} />}
|
||||||
</Link>
|
</Link>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -4,6 +4,7 @@ import React from "react"
|
|||||||
import { useColorMode } from "@/providers"
|
import { useColorMode } from "@/providers"
|
||||||
import Link from "next/link"
|
import Link from "next/link"
|
||||||
import clsx from "clsx"
|
import clsx from "clsx"
|
||||||
|
import Image from "next/image"
|
||||||
|
|
||||||
export type NavbarLogoProps = {
|
export type NavbarLogoProps = {
|
||||||
light: string
|
light: string
|
||||||
@@ -22,7 +23,7 @@ export const NavbarLogo = ({
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<Link href={`/`} className={clsx("flex-1", className)}>
|
<Link href={`/`} className={clsx("flex-1", className)}>
|
||||||
<img
|
<Image
|
||||||
src={colorMode === "light" ? light : dark || light}
|
src={colorMode === "light" ? light : dark || light}
|
||||||
alt="Medusa Logo"
|
alt="Medusa Logo"
|
||||||
height={20}
|
height={20}
|
||||||
|
|||||||
@@ -0,0 +1,11 @@
|
|||||||
|
import clsx from "clsx"
|
||||||
|
import React from "react"
|
||||||
|
|
||||||
|
export const NavbarDivider = () => {
|
||||||
|
return (
|
||||||
|
<div className={clsx(
|
||||||
|
"w-px h-1/2 bg-medusa-fg-disabled",
|
||||||
|
"mx-docs_0.5"
|
||||||
|
)}></div>
|
||||||
|
)
|
||||||
|
}
|
||||||
@@ -6,10 +6,19 @@ import { NavbarLogo, NavbarLogoProps } from "./Logo"
|
|||||||
import { NavbarMobileMenu } from "./MobileMenu"
|
import { NavbarMobileMenu } from "./MobileMenu"
|
||||||
import { NavbarSearchModalOpener } from "./SearchModalOpener"
|
import { NavbarSearchModalOpener } from "./SearchModalOpener"
|
||||||
import { NavbarMobileMenuButtonProps } from "./MobileMenu/Button"
|
import { NavbarMobileMenuButtonProps } from "./MobileMenu/Button"
|
||||||
|
import { NavbarDivider } from "./NavbarDivider"
|
||||||
|
|
||||||
|
export type NavbarItem = {
|
||||||
|
type: "link"
|
||||||
|
props: NavbarLinkProps
|
||||||
|
} | {
|
||||||
|
type: "divider"
|
||||||
|
props?: {}
|
||||||
|
}
|
||||||
|
|
||||||
export type NavbarProps = {
|
export type NavbarProps = {
|
||||||
logo: NavbarLogoProps
|
logo: NavbarLogoProps
|
||||||
items: NavbarLinkProps[]
|
items: NavbarItem[]
|
||||||
showSearchOpener?: boolean
|
showSearchOpener?: boolean
|
||||||
showColorModeToggle?: boolean
|
showColorModeToggle?: boolean
|
||||||
additionalActionsAfter?: React.ReactNode
|
additionalActionsAfter?: React.ReactNode
|
||||||
@@ -45,9 +54,14 @@ export const Navbar = ({
|
|||||||
>
|
>
|
||||||
<div className="hidden w-full items-center gap-docs_0.5 lg:flex lg:w-auto lg:gap-docs_1.5">
|
<div className="hidden w-full items-center gap-docs_0.5 lg:flex lg:w-auto lg:gap-docs_1.5">
|
||||||
<NavbarLogo {...logo} />
|
<NavbarLogo {...logo} />
|
||||||
{items.map((item, index) => (
|
{items.map(({type, props}, index) => {
|
||||||
<NavbarLink key={index} {...item} />
|
switch(type) {
|
||||||
))}
|
case "divider":
|
||||||
|
return <NavbarDivider key={index} />
|
||||||
|
default:
|
||||||
|
return <NavbarLink key={index} {...props} />
|
||||||
|
}
|
||||||
|
})}
|
||||||
</div>
|
</div>
|
||||||
<div className="hidden min-w-0 flex-1 items-center justify-end gap-docs_0.5 lg:flex">
|
<div className="hidden min-w-0 flex-1 items-center justify-end gap-docs_0.5 lg:flex">
|
||||||
{additionalActionsBefore}
|
{additionalActionsBefore}
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ export const Pagination = () => {
|
|||||||
{previousPage && (
|
{previousPage && (
|
||||||
<Card
|
<Card
|
||||||
title={previousPage.title}
|
title={previousPage.title}
|
||||||
|
text={previousPage.parentTitle}
|
||||||
startIcon={<ChevronLeft />}
|
startIcon={<ChevronLeft />}
|
||||||
showLinkIcon={false}
|
showLinkIcon={false}
|
||||||
href={previousPage.link}
|
href={previousPage.link}
|
||||||
@@ -22,6 +23,7 @@ export const Pagination = () => {
|
|||||||
{nextPage && (
|
{nextPage && (
|
||||||
<Card
|
<Card
|
||||||
title={nextPage.title}
|
title={nextPage.title}
|
||||||
|
text={nextPage.parentTitle}
|
||||||
endIcon={<ChevronRight />}
|
endIcon={<ChevronRight />}
|
||||||
showLinkIcon={false}
|
showLinkIcon={false}
|
||||||
href={nextPage.link}
|
href={nextPage.link}
|
||||||
|
|||||||
@@ -85,6 +85,9 @@ export const Search = ({
|
|||||||
<InstantSearch
|
<InstantSearch
|
||||||
indexName={algolia.mainIndexName}
|
indexName={algolia.mainIndexName}
|
||||||
searchClient={searchClient}
|
searchClient={searchClient}
|
||||||
|
future={{
|
||||||
|
preserveSharedStateOnUnmount: true
|
||||||
|
}}
|
||||||
>
|
>
|
||||||
<div className={clsx("bg-medusa-bg-base flex")}>
|
<div className={clsx("bg-medusa-bg-base flex")}>
|
||||||
<SearchBox
|
<SearchBox
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ export const SidebarBack = () => {
|
|||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
className={clsx(
|
className={clsx(
|
||||||
"my-docs_1.5 cursor-pointer",
|
"mb-docs_1.5 cursor-pointer",
|
||||||
"flex items-center gap-docs_0.5 rounded-docs_sm px-docs_0.5 py-[6px] hover:no-underline",
|
"flex items-center gap-docs_0.5 rounded-docs_sm px-docs_0.5 py-[6px] hover:no-underline",
|
||||||
"border border-transparent",
|
"border border-transparent",
|
||||||
"text-medusa-fg-subtle text-medium-plus"
|
"text-medusa-fg-subtle text-medium-plus"
|
||||||
|
|||||||
@@ -16,6 +16,8 @@ export type SidebarItemProps = {
|
|||||||
expandItems?: boolean
|
expandItems?: boolean
|
||||||
currentLevel?: number
|
currentLevel?: number
|
||||||
isSidebarTitle?: boolean
|
isSidebarTitle?: boolean
|
||||||
|
sidebarHasParent?: boolean
|
||||||
|
isMobile?: boolean
|
||||||
} & React.AllHTMLAttributes<HTMLLIElement>
|
} & React.AllHTMLAttributes<HTMLLIElement>
|
||||||
|
|
||||||
export const SidebarItem = ({
|
export const SidebarItem = ({
|
||||||
@@ -24,6 +26,8 @@ export const SidebarItem = ({
|
|||||||
expandItems = false,
|
expandItems = false,
|
||||||
className,
|
className,
|
||||||
currentLevel = 1,
|
currentLevel = 1,
|
||||||
|
sidebarHasParent = false,
|
||||||
|
isMobile = false
|
||||||
}: SidebarItemProps) => {
|
}: SidebarItemProps) => {
|
||||||
const [showLoading, setShowLoading] = useState(false)
|
const [showLoading, setShowLoading] = useState(false)
|
||||||
const {
|
const {
|
||||||
@@ -34,8 +38,8 @@ export const SidebarItem = ({
|
|||||||
sidebarRef,
|
sidebarRef,
|
||||||
} = useSidebar()
|
} = useSidebar()
|
||||||
const active = useMemo(
|
const active = useMemo(
|
||||||
() => isItemActive(item, nested),
|
() => !isMobile && isItemActive(item, nested),
|
||||||
[isItemActive, item, nested]
|
[isItemActive, item, nested, isMobile]
|
||||||
)
|
)
|
||||||
const collapsed = !expandItems && !isItemActive(item, true)
|
const collapsed = !expandItems && !isItemActive(item, true)
|
||||||
const ref = useRef<HTMLLIElement>(null)
|
const ref = useRef<HTMLLIElement>(null)
|
||||||
@@ -131,7 +135,11 @@ export const SidebarItem = ({
|
|||||||
return (
|
return (
|
||||||
<li
|
<li
|
||||||
className={clsx(
|
className={clsx(
|
||||||
canHaveTitleStyling && !collapsed && "my-docs_1.5",
|
canHaveTitleStyling &&
|
||||||
|
!collapsed && [
|
||||||
|
!sidebarHasParent && "my-docs_1.5",
|
||||||
|
sidebarHasParent && "[&:not(:first-child)]:my-docs_1.5",
|
||||||
|
],
|
||||||
!canHaveTitleStyling &&
|
!canHaveTitleStyling &&
|
||||||
!nested &&
|
!nested &&
|
||||||
active &&
|
active &&
|
||||||
|
|||||||
@@ -11,9 +11,9 @@ export const SidebarTitle = ({ item }: SidebarTitleProps) => {
|
|||||||
return (
|
return (
|
||||||
<Link
|
<Link
|
||||||
className={clsx(
|
className={clsx(
|
||||||
"flex items-center justify-between gap-docs_0.5 rounded-docs_sm px-docs_0.5 py-[6px] hover:no-underline",
|
"flex items-center justify-between gap-docs_0.5 rounded-docs_sm px-docs_0.5 pb-[6px] hover:no-underline",
|
||||||
"border border-transparent",
|
"border border-transparent",
|
||||||
"text-medusa-fg-subtle text-medium-plus"
|
"text-medusa-fg-subtle text-large-plus"
|
||||||
)}
|
)}
|
||||||
href={item.isPathHref && item.path ? item.path : `#${item.path}`}
|
href={item.isPathHref && item.path ? item.path : `#${item.path}`}
|
||||||
replace={!item.isPathHref}
|
replace={!item.isPathHref}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
"use client"
|
"use client"
|
||||||
|
|
||||||
import React, { useMemo } from "react"
|
import React, { useMemo, useRef } from "react"
|
||||||
import { useSidebar } from "@/providers"
|
import { useSidebar } from "@/providers"
|
||||||
import clsx from "clsx"
|
import clsx from "clsx"
|
||||||
import { Loading } from "@/components"
|
import { Loading } from "@/components"
|
||||||
@@ -12,11 +12,13 @@ import { CSSTransition, SwitchTransition } from "react-transition-group"
|
|||||||
export type SidebarProps = {
|
export type SidebarProps = {
|
||||||
className?: string
|
className?: string
|
||||||
expandItems?: boolean
|
expandItems?: boolean
|
||||||
|
banner?: React.ReactNode
|
||||||
}
|
}
|
||||||
|
|
||||||
export const Sidebar = ({
|
export const Sidebar = ({
|
||||||
className = "",
|
className = "",
|
||||||
expandItems = false,
|
expandItems = false,
|
||||||
|
banner,
|
||||||
}: SidebarProps) => {
|
}: SidebarProps) => {
|
||||||
const {
|
const {
|
||||||
items,
|
items,
|
||||||
@@ -32,6 +34,11 @@ export const Sidebar = ({
|
|||||||
[items, currentItems]
|
[items, currentItems]
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const sidebarHasParent = useMemo(
|
||||||
|
() => sidebarItems.parentItem !== undefined,
|
||||||
|
[sidebarItems]
|
||||||
|
)
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<aside
|
<aside
|
||||||
className={clsx(
|
className={clsx(
|
||||||
@@ -47,69 +54,76 @@ export const Sidebar = ({
|
|||||||
animationFillMode: "forwards",
|
animationFillMode: "forwards",
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<SwitchTransition>
|
<ul
|
||||||
<CSSTransition
|
className={clsx(
|
||||||
key={sidebarItems.parentItem?.title || "home"}
|
"sticky top-0 h-screen max-h-screen w-full list-none p-0",
|
||||||
nodeRef={sidebarRef}
|
"px-docs_1.5 pb-[57px] pt-docs_1.5",
|
||||||
classNames={{
|
"flex flex-col"
|
||||||
enter: "animate-fadeInLeft animate-fast",
|
)}
|
||||||
exit: "animate-fadeOutLeft animate-fast",
|
id="sidebar"
|
||||||
}}
|
>
|
||||||
timeout={200}
|
{banner && <div className="mb-docs_1">{banner}</div>}
|
||||||
>
|
{sidebarItems.parentItem && (
|
||||||
<ul
|
<div className={clsx("mb-docs_1", !banner && "mt-docs_1.5")}>
|
||||||
className={clsx(
|
<SidebarBack />
|
||||||
"sticky top-0 h-screen max-h-screen w-full list-none overflow-auto p-0",
|
<SidebarTitle item={sidebarItems.parentItem} />
|
||||||
"px-docs_1.5 pb-[57px] pt-docs_1.5"
|
</div>
|
||||||
)}
|
)}
|
||||||
id="sidebar"
|
<SwitchTransition>
|
||||||
ref={sidebarRef}
|
<CSSTransition
|
||||||
|
key={sidebarItems.parentItem?.title || "home"}
|
||||||
|
nodeRef={sidebarRef}
|
||||||
|
classNames={{
|
||||||
|
enter: "animate-fadeInLeft animate-fast",
|
||||||
|
exit: "animate-fadeOutLeft animate-fast",
|
||||||
|
}}
|
||||||
|
timeout={200}
|
||||||
>
|
>
|
||||||
{sidebarItems.parentItem && (
|
<div className="overflow-auto" ref={sidebarRef}>
|
||||||
<>
|
<div className={clsx("mb-docs_1.5 lg:hidden")}>
|
||||||
<SidebarBack />
|
{!sidebarItems.mobile.length && !staticSidebarItems && (
|
||||||
<SidebarTitle item={sidebarItems.parentItem} />
|
<Loading className="px-0" />
|
||||||
</>
|
)}
|
||||||
)}
|
{sidebarItems.mobile.map((item, index) => (
|
||||||
<div className="mb-docs_1.5 lg:hidden">
|
<SidebarItem
|
||||||
{!sidebarItems.mobile.length && !staticSidebarItems && (
|
item={item}
|
||||||
<Loading className="px-0" />
|
key={index}
|
||||||
)}
|
expandItems={expandItems}
|
||||||
{sidebarItems.mobile.map((item, index) => (
|
sidebarHasParent={sidebarHasParent}
|
||||||
<SidebarItem
|
isMobile={true}
|
||||||
item={item}
|
/>
|
||||||
key={index}
|
))}
|
||||||
expandItems={expandItems}
|
</div>
|
||||||
/>
|
<div className={clsx("mb-docs_1.5")}>
|
||||||
))}
|
{!sidebarItems.top.length && !staticSidebarItems && (
|
||||||
|
<Loading className="px-0" />
|
||||||
|
)}
|
||||||
|
{sidebarItems.top.map((item, index) => (
|
||||||
|
<SidebarItem
|
||||||
|
item={item}
|
||||||
|
key={index}
|
||||||
|
expandItems={expandItems}
|
||||||
|
sidebarHasParent={sidebarHasParent}
|
||||||
|
/>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
<div className="mb-docs_1.5">
|
||||||
|
{!sidebarItems.bottom.length && !staticSidebarItems && (
|
||||||
|
<Loading className="px-0" />
|
||||||
|
)}
|
||||||
|
{sidebarItems.bottom.map((item, index) => (
|
||||||
|
<SidebarItem
|
||||||
|
item={item}
|
||||||
|
key={index}
|
||||||
|
expandItems={expandItems}
|
||||||
|
sidebarHasParent={sidebarHasParent}
|
||||||
|
/>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="mb-docs_1.5">
|
</CSSTransition>
|
||||||
{!sidebarItems.top.length && !staticSidebarItems && (
|
</SwitchTransition>
|
||||||
<Loading className="px-0" />
|
</ul>
|
||||||
)}
|
|
||||||
{sidebarItems.top.map((item, index) => (
|
|
||||||
<SidebarItem
|
|
||||||
item={item}
|
|
||||||
key={index}
|
|
||||||
expandItems={expandItems}
|
|
||||||
/>
|
|
||||||
))}
|
|
||||||
</div>
|
|
||||||
<div className="mb-docs_1.5">
|
|
||||||
{!sidebarItems.bottom.length && !staticSidebarItems && (
|
|
||||||
<Loading className="px-0" />
|
|
||||||
)}
|
|
||||||
{sidebarItems.bottom.map((item, index) => (
|
|
||||||
<SidebarItem
|
|
||||||
item={item}
|
|
||||||
key={index}
|
|
||||||
expandItems={expandItems}
|
|
||||||
/>
|
|
||||||
))}
|
|
||||||
</div>
|
|
||||||
</ul>
|
|
||||||
</CSSTransition>
|
|
||||||
</SwitchTransition>
|
|
||||||
</aside>
|
</aside>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -21,7 +21,7 @@ import {
|
|||||||
} from "@medusajs/icons"
|
} from "@medusajs/icons"
|
||||||
import { decodeStr, isInView } from "@/utils"
|
import { decodeStr, isInView } from "@/utils"
|
||||||
import { usePathname } from "next/navigation"
|
import { usePathname } from "next/navigation"
|
||||||
import { useIsBrowser } from "../../.."
|
import { useIsBrowser, useSiteConfig } from "../../.."
|
||||||
|
|
||||||
type CommonProps = ParentCommonProps & {
|
type CommonProps = ParentCommonProps & {
|
||||||
level?: number
|
level?: number
|
||||||
@@ -39,10 +39,11 @@ const TypeListItem = ({
|
|||||||
expandUrl,
|
expandUrl,
|
||||||
elementKey,
|
elementKey,
|
||||||
sectionTitle,
|
sectionTitle,
|
||||||
siteUrl = "",
|
|
||||||
}: TypeListItemProps) => {
|
}: TypeListItemProps) => {
|
||||||
const isBrowser = useIsBrowser()
|
const isBrowser = useIsBrowser()
|
||||||
const pathname = usePathname()
|
const pathname = usePathname()
|
||||||
|
const { config: { baseUrl, basePath } } = useSiteConfig()
|
||||||
|
const siteUrl = `${baseUrl}${basePath}`
|
||||||
|
|
||||||
const groupName = useMemo(() => {
|
const groupName = useMemo(() => {
|
||||||
switch (level) {
|
switch (level) {
|
||||||
|
|||||||
@@ -5,7 +5,6 @@ import { Loading } from "@/components"
|
|||||||
export type CommonProps = {
|
export type CommonProps = {
|
||||||
expandUrl?: string
|
expandUrl?: string
|
||||||
sectionTitle?: string
|
sectionTitle?: string
|
||||||
siteUrl?: string
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export type Type = {
|
export type Type = {
|
||||||
@@ -30,7 +29,6 @@ const TypeListItems = lazy(async () => import("./Items"))
|
|||||||
export const TypeList = ({
|
export const TypeList = ({
|
||||||
types,
|
types,
|
||||||
className,
|
className,
|
||||||
siteUrl,
|
|
||||||
sectionTitle,
|
sectionTitle,
|
||||||
expandUrl,
|
expandUrl,
|
||||||
...props
|
...props
|
||||||
@@ -48,7 +46,6 @@ export const TypeList = ({
|
|||||||
types={types}
|
types={types}
|
||||||
expandUrl={expandUrl}
|
expandUrl={expandUrl}
|
||||||
sectionTitle={sectionTitle}
|
sectionTitle={sectionTitle}
|
||||||
siteUrl={siteUrl}
|
|
||||||
/>
|
/>
|
||||||
</Suspense>
|
</Suspense>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -1,8 +1,10 @@
|
|||||||
export * from "./AiAssistant"
|
export * from "./AiAssistant"
|
||||||
export * from "./AiAssistant/CommandIcon"
|
export * from "./AiAssistant/CommandIcon"
|
||||||
export * from "./Badge"
|
export * from "./Badge"
|
||||||
|
export * from "./Bannerv2"
|
||||||
export * from "./Bordered"
|
export * from "./Bordered"
|
||||||
export * from "./BorderedIcon"
|
export * from "./BorderedIcon"
|
||||||
|
export * from "./Breadcrumbs"
|
||||||
export * from "./Button"
|
export * from "./Button"
|
||||||
export * from "./Card"
|
export * from "./Card"
|
||||||
export * from "./CardList"
|
export * from "./CardList"
|
||||||
|
|||||||
@@ -1,198 +0,0 @@
|
|||||||
import { NavbarLinkProps } from "@/components"
|
|
||||||
import { OptionType } from "./hooks"
|
|
||||||
import { SidebarItemType } from "types"
|
|
||||||
|
|
||||||
export const GITHUB_ISSUES_PREFIX = `https://github.com/medusajs/medusa/issues/new?assignees=&labels=type%3A+docs&template=docs.yml`
|
|
||||||
export const GITHUB_UI_ISSUES_PREFIX = `https://github.com/medusajs/ui/issues/new?labels=documentation`
|
|
||||||
|
|
||||||
export const navbarItems: NavbarLinkProps[] = [
|
|
||||||
{
|
|
||||||
label: "Docs",
|
|
||||||
target: "_blank",
|
|
||||||
rel: "noreferrer",
|
|
||||||
href: `/`,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: "Resources",
|
|
||||||
target: "_blank",
|
|
||||||
rel: "noreferrer",
|
|
||||||
href: `/resources`,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: "User Guide",
|
|
||||||
target: "_blank",
|
|
||||||
rel: "noreferrer",
|
|
||||||
href: `/user-guide`,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: "Store API",
|
|
||||||
target: "_blank",
|
|
||||||
rel: "noreferrer",
|
|
||||||
href: `/api/store`,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: "Admin API",
|
|
||||||
target: "_blank",
|
|
||||||
rel: "noreferrer",
|
|
||||||
href: `/api/admin`,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: "UI",
|
|
||||||
target: "_blank",
|
|
||||||
rel: "noreferrer",
|
|
||||||
href: `/ui`,
|
|
||||||
},
|
|
||||||
]
|
|
||||||
|
|
||||||
/**
|
|
||||||
* TODO Uncomment for V2
|
|
||||||
*
|
|
||||||
* export const navbarItems: NavbarLinkProps[] = [
|
|
||||||
{
|
|
||||||
label: "Docs",
|
|
||||||
target: "_blank",
|
|
||||||
rel: "noreferrer",
|
|
||||||
href: `/`,
|
|
||||||
activeValuePattern: /^\/(?!api\/|ui\/|user-guide\/|resources\/)/,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: "User Guide",
|
|
||||||
target: "_blank",
|
|
||||||
rel: "noreferrer",
|
|
||||||
href: `/user-guide`,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: "Store API",
|
|
||||||
target: "_blank",
|
|
||||||
rel: "noreferrer",
|
|
||||||
href: `/api/store`,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: "Admin API",
|
|
||||||
target: "_blank",
|
|
||||||
rel: "noreferrer",
|
|
||||||
href: `/api/admin`,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: "UI",
|
|
||||||
target: "_blank",
|
|
||||||
rel: "noreferrer",
|
|
||||||
href: `/ui`,
|
|
||||||
activeValuePattern: /^\/ui\//,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: "V2 Docs",
|
|
||||||
target: "_blank",
|
|
||||||
rel: "noreferrer",
|
|
||||||
href: `/v2`,
|
|
||||||
},
|
|
||||||
]
|
|
||||||
|
|
||||||
export const navbarItemsV2: NavbarLinkProps[] = [
|
|
||||||
{
|
|
||||||
label: "Docs",
|
|
||||||
target: "_blank",
|
|
||||||
rel: "noreferrer",
|
|
||||||
href: `/v2`,
|
|
||||||
activeValuePattern: /^\/v2\/(?!api\/|ui\/|user-guide\/|resources\/)/,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: "Resources",
|
|
||||||
target: "_blank",
|
|
||||||
rel: "noreferrer",
|
|
||||||
href: `/v2/resources`,
|
|
||||||
activeValuePattern: /^\/v2\/resources\//,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: "User Guide",
|
|
||||||
target: "_blank",
|
|
||||||
rel: "noreferrer",
|
|
||||||
href: `/v2/user-guide`,
|
|
||||||
activeValuePattern: /^\/v2\/user-guide/,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: "Store API",
|
|
||||||
target: "_blank",
|
|
||||||
rel: "noreferrer",
|
|
||||||
href: `/api/store`,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: "Admin API",
|
|
||||||
target: "_blank",
|
|
||||||
rel: "noreferrer",
|
|
||||||
href: `/api/admin`,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: "UI",
|
|
||||||
target: "_blank",
|
|
||||||
rel: "noreferrer",
|
|
||||||
href: `/ui`,
|
|
||||||
activeValuePattern: /^\/ui\//,
|
|
||||||
},
|
|
||||||
]
|
|
||||||
*/
|
|
||||||
|
|
||||||
export const mobileSidebarItems: SidebarItemType[] = [
|
|
||||||
{
|
|
||||||
title: "Docs",
|
|
||||||
path: `/`,
|
|
||||||
loaded: true,
|
|
||||||
isPathHref: true,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: "User Guide",
|
|
||||||
path: `/user-guide`,
|
|
||||||
loaded: true,
|
|
||||||
isPathHref: true,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: "Store API",
|
|
||||||
path: `/api/store`,
|
|
||||||
loaded: true,
|
|
||||||
isPathHref: true,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: "Admin API",
|
|
||||||
path: `/api/admin`,
|
|
||||||
loaded: true,
|
|
||||||
isPathHref: true,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: "UI",
|
|
||||||
path: `/ui`,
|
|
||||||
loaded: true,
|
|
||||||
isPathHref: true,
|
|
||||||
},
|
|
||||||
]
|
|
||||||
|
|
||||||
// TODO add resources once we create index
|
|
||||||
export const searchFilters: OptionType[] = [
|
|
||||||
{
|
|
||||||
value: "admin",
|
|
||||||
label: "Admin API",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
value: "store",
|
|
||||||
label: "Store API",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
value: "docs",
|
|
||||||
label: "Docs",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
value: "user-guide",
|
|
||||||
label: "User Guide",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
value: "plugins",
|
|
||||||
label: "Plugins",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
value: "reference",
|
|
||||||
label: "References",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
value: "ui",
|
|
||||||
label: "UI",
|
|
||||||
},
|
|
||||||
]
|
|
||||||
@@ -0,0 +1,368 @@
|
|||||||
|
import React from "react"
|
||||||
|
import { Badge, NavbarItem } from "@/components"
|
||||||
|
import { OptionType } from "./hooks"
|
||||||
|
import { SidebarItemType } from "types"
|
||||||
|
|
||||||
|
export const GITHUB_ISSUES_PREFIX = `https://github.com/medusajs/medusa/issues/new?assignees=&labels=type%3A+docs&template=docs.yml`
|
||||||
|
export const GITHUB_UI_ISSUES_PREFIX = `https://github.com/medusajs/ui/issues/new?labels=documentation`
|
||||||
|
|
||||||
|
export const navbarItemsV1: NavbarItem[] = [
|
||||||
|
{
|
||||||
|
type: "link",
|
||||||
|
props: {
|
||||||
|
label: "Docs",
|
||||||
|
target: "_blank",
|
||||||
|
rel: "noreferrer",
|
||||||
|
href: `/`,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: "link",
|
||||||
|
props: {
|
||||||
|
label: "User Guide",
|
||||||
|
target: "_blank",
|
||||||
|
rel: "noreferrer",
|
||||||
|
href: `/user-guide`,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: "link",
|
||||||
|
props: {
|
||||||
|
label: "Store API",
|
||||||
|
target: "_blank",
|
||||||
|
rel: "noreferrer",
|
||||||
|
href: `/api/store`,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: "link",
|
||||||
|
props: {
|
||||||
|
label: "Admin API",
|
||||||
|
target: "_blank",
|
||||||
|
rel: "noreferrer",
|
||||||
|
href: `/api/admin`,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: "link",
|
||||||
|
props: {
|
||||||
|
label: "UI",
|
||||||
|
target: "_blank",
|
||||||
|
rel: "noreferrer",
|
||||||
|
href: `/ui`,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: "divider",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: "link",
|
||||||
|
props: {
|
||||||
|
label: "Learn Medusa v2",
|
||||||
|
target: "_blank",
|
||||||
|
rel: "noreferrer",
|
||||||
|
href: `/v2`,
|
||||||
|
badge: {
|
||||||
|
variant: "blue",
|
||||||
|
children: "New",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
]
|
||||||
|
|
||||||
|
export const navbarItemsV2: NavbarItem[] = [
|
||||||
|
{
|
||||||
|
type: "link",
|
||||||
|
props: {
|
||||||
|
label: "Docs",
|
||||||
|
target: "_blank",
|
||||||
|
rel: "noreferrer",
|
||||||
|
href: `/v2`,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: "link",
|
||||||
|
props: {
|
||||||
|
label: "Learning Resources",
|
||||||
|
target: "_blank",
|
||||||
|
rel: "noreferrer",
|
||||||
|
href: `/v2/resources`,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: "divider",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: "link",
|
||||||
|
props: {
|
||||||
|
label: "Docs",
|
||||||
|
target: "_blank",
|
||||||
|
rel: "noreferrer",
|
||||||
|
href: `/`,
|
||||||
|
badge: {
|
||||||
|
variant: "neutral",
|
||||||
|
children: "v1",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: "link",
|
||||||
|
props: {
|
||||||
|
label: "User Guide",
|
||||||
|
target: "_blank",
|
||||||
|
rel: "noreferrer",
|
||||||
|
href: `/user-guide`,
|
||||||
|
badge: {
|
||||||
|
variant: "neutral",
|
||||||
|
children: "v1",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: "link",
|
||||||
|
props: {
|
||||||
|
label: "Store API",
|
||||||
|
target: "_blank",
|
||||||
|
rel: "noreferrer",
|
||||||
|
href: `/api/store`,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: "link",
|
||||||
|
props: {
|
||||||
|
label: "Admin API",
|
||||||
|
target: "_blank",
|
||||||
|
rel: "noreferrer",
|
||||||
|
href: `/api/admin`,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: "link",
|
||||||
|
props: {
|
||||||
|
label: "UI",
|
||||||
|
target: "_blank",
|
||||||
|
rel: "noreferrer",
|
||||||
|
href: `/ui`,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
]
|
||||||
|
|
||||||
|
export const legacyNavbarItems: NavbarItem[] = [
|
||||||
|
{
|
||||||
|
type: "link",
|
||||||
|
props: {
|
||||||
|
label: "Docs",
|
||||||
|
target: "_blank",
|
||||||
|
rel: "noreferrer",
|
||||||
|
href: `/`,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: "link",
|
||||||
|
props: {
|
||||||
|
label: "Resources",
|
||||||
|
target: "_blank",
|
||||||
|
rel: "noreferrer",
|
||||||
|
href: `/resources`,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: "link",
|
||||||
|
props: {
|
||||||
|
label: "User Guide",
|
||||||
|
target: "_blank",
|
||||||
|
rel: "noreferrer",
|
||||||
|
href: `/user-guide`,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: "link",
|
||||||
|
props: {
|
||||||
|
label: "Store API",
|
||||||
|
target: "_blank",
|
||||||
|
rel: "noreferrer",
|
||||||
|
href: `/api/store`,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: "link",
|
||||||
|
props: {
|
||||||
|
label: "Admin API",
|
||||||
|
target: "_blank",
|
||||||
|
rel: "noreferrer",
|
||||||
|
href: `/api/admin`,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: "link",
|
||||||
|
props: {
|
||||||
|
label: "UI",
|
||||||
|
target: "_blank",
|
||||||
|
rel: "noreferrer",
|
||||||
|
href: `/ui`,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
]
|
||||||
|
|
||||||
|
export const mobileSidebarItemsV1: SidebarItemType[] = [
|
||||||
|
{
|
||||||
|
title: "Docs",
|
||||||
|
path: `/`,
|
||||||
|
loaded: true,
|
||||||
|
isPathHref: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: "User Guide",
|
||||||
|
path: `/user-guide`,
|
||||||
|
loaded: true,
|
||||||
|
isPathHref: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: "Store API",
|
||||||
|
path: `/api/store`,
|
||||||
|
loaded: true,
|
||||||
|
isPathHref: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: "Admin API",
|
||||||
|
path: `/api/admin`,
|
||||||
|
loaded: true,
|
||||||
|
isPathHref: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: "UI",
|
||||||
|
path: `/ui`,
|
||||||
|
loaded: true,
|
||||||
|
isPathHref: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: "Book",
|
||||||
|
path: `/v2`,
|
||||||
|
loaded: true,
|
||||||
|
isPathHref: true,
|
||||||
|
additionalElms: <Badge variant="blue">v2</Badge>,
|
||||||
|
},
|
||||||
|
]
|
||||||
|
|
||||||
|
export const mobileSidebarItemsV2: SidebarItemType[] = [
|
||||||
|
{
|
||||||
|
title: "Book",
|
||||||
|
path: `/v2`,
|
||||||
|
loaded: true,
|
||||||
|
isPathHref: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: "Learning Resources",
|
||||||
|
path: `/v2/resources`,
|
||||||
|
loaded: true,
|
||||||
|
isPathHref: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: "Docs",
|
||||||
|
path: `/`,
|
||||||
|
loaded: true,
|
||||||
|
isPathHref: true,
|
||||||
|
additionalElms: <Badge variant="neutral">v1</Badge>,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: "User Guide",
|
||||||
|
path: `/user-guide`,
|
||||||
|
loaded: true,
|
||||||
|
isPathHref: true,
|
||||||
|
additionalElms: <Badge variant="neutral">v1</Badge>,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: "Store API",
|
||||||
|
path: `/api/store`,
|
||||||
|
loaded: true,
|
||||||
|
isPathHref: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: "Admin API",
|
||||||
|
path: `/api/admin`,
|
||||||
|
loaded: true,
|
||||||
|
isPathHref: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: "UI",
|
||||||
|
path: `/ui`,
|
||||||
|
loaded: true,
|
||||||
|
isPathHref: true,
|
||||||
|
},
|
||||||
|
]
|
||||||
|
|
||||||
|
export const legacyMobileSidebarItems: SidebarItemType[] = [
|
||||||
|
{
|
||||||
|
title: "Docs",
|
||||||
|
path: `/`,
|
||||||
|
loaded: true,
|
||||||
|
isPathHref: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: "User Guide",
|
||||||
|
path: `/user-guide`,
|
||||||
|
loaded: true,
|
||||||
|
isPathHref: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: "Store API",
|
||||||
|
path: `/api/store`,
|
||||||
|
loaded: true,
|
||||||
|
isPathHref: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: "Admin API",
|
||||||
|
path: `/api/admin`,
|
||||||
|
loaded: true,
|
||||||
|
isPathHref: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: "UI",
|
||||||
|
path: `/ui`,
|
||||||
|
loaded: true,
|
||||||
|
isPathHref: true,
|
||||||
|
},
|
||||||
|
]
|
||||||
|
|
||||||
|
export const searchFiltersV2: OptionType[] = [
|
||||||
|
{
|
||||||
|
value: "book",
|
||||||
|
label: "Book",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: "resources",
|
||||||
|
label: "Resources",
|
||||||
|
},
|
||||||
|
// TODO add more filters once V2 become the main docs
|
||||||
|
]
|
||||||
|
|
||||||
|
export const searchFiltersV1: OptionType[] = [
|
||||||
|
{
|
||||||
|
value: "admin",
|
||||||
|
label: "Admin API",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: "store",
|
||||||
|
label: "Store API",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: "docs",
|
||||||
|
label: "Docs",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: "user-guide",
|
||||||
|
label: "User Guide",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: "plugins",
|
||||||
|
label: "Plugins",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: "reference",
|
||||||
|
label: "References",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: "ui",
|
||||||
|
label: "UI",
|
||||||
|
},
|
||||||
|
]
|
||||||
@@ -14,6 +14,7 @@ import { SidebarItemType } from "types"
|
|||||||
export type Page = {
|
export type Page = {
|
||||||
title: string
|
title: string
|
||||||
description?: string
|
description?: string
|
||||||
|
parentTitle?: string
|
||||||
link: string
|
link: string
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -26,10 +27,14 @@ export const PaginationContext = createContext<PaginationContextType | null>(
|
|||||||
null
|
null
|
||||||
)
|
)
|
||||||
|
|
||||||
|
type SidebarItemWithParent = SidebarItemType & {
|
||||||
|
parent?: SidebarItemType
|
||||||
|
}
|
||||||
|
|
||||||
type SearchItemsResult = {
|
type SearchItemsResult = {
|
||||||
foundActive: boolean
|
foundActive: boolean
|
||||||
prevItem?: SidebarItemType
|
prevItem?: SidebarItemWithParent
|
||||||
nextItem?: SidebarItemType
|
nextItem?: SidebarItemWithParent
|
||||||
}
|
}
|
||||||
|
|
||||||
export type PaginationProviderProps = {
|
export type PaginationProviderProps = {
|
||||||
@@ -66,14 +71,20 @@ export const PaginationProvider = ({ children }: PaginationProviderProps) => {
|
|||||||
const getPrevItem = (
|
const getPrevItem = (
|
||||||
items: SidebarItemType[],
|
items: SidebarItemType[],
|
||||||
index: number
|
index: number
|
||||||
): SidebarItemType | undefined => {
|
): SidebarItemWithParent | undefined => {
|
||||||
let foundItem: SidebarItemType | undefined
|
let foundItem: SidebarItemWithParent | undefined
|
||||||
items
|
items
|
||||||
.slice(0, index)
|
.slice(0, index)
|
||||||
.reverse()
|
.reverse()
|
||||||
.some((item) => {
|
.some((item) => {
|
||||||
if (item.children?.length) {
|
if (item.children?.length) {
|
||||||
foundItem = getPrevItem(item.children, item.children.length)
|
const childItem = getPrevItem(item.children, item.children.length)
|
||||||
|
if (childItem) {
|
||||||
|
foundItem = {
|
||||||
|
...childItem,
|
||||||
|
parent: item,
|
||||||
|
}
|
||||||
|
}
|
||||||
} else if (item.path) {
|
} else if (item.path) {
|
||||||
foundItem = item
|
foundItem = item
|
||||||
}
|
}
|
||||||
@@ -87,13 +98,19 @@ export const PaginationProvider = ({ children }: PaginationProviderProps) => {
|
|||||||
const getNextItem = (
|
const getNextItem = (
|
||||||
items: SidebarItemType[],
|
items: SidebarItemType[],
|
||||||
index: number
|
index: number
|
||||||
): SidebarItemType | undefined => {
|
): SidebarItemWithParent | undefined => {
|
||||||
let foundItem: SidebarItemType | undefined
|
let foundItem: SidebarItemWithParent | undefined
|
||||||
items.slice(index + 1).some((item) => {
|
items.slice(index + 1).some((item) => {
|
||||||
if (item.path) {
|
if (item.path) {
|
||||||
foundItem = item
|
foundItem = item
|
||||||
} else if (item.children?.length) {
|
} else if (item.children?.length) {
|
||||||
foundItem = getNextItem(item.children, -1)
|
const childItem = getNextItem(item.children, -1)
|
||||||
|
if (childItem) {
|
||||||
|
foundItem = {
|
||||||
|
...childItem,
|
||||||
|
parent: item,
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return foundItem !== undefined
|
return foundItem !== undefined
|
||||||
@@ -157,6 +174,7 @@ export const PaginationProvider = ({ children }: PaginationProviderProps) => {
|
|||||||
? {
|
? {
|
||||||
title: result.prevItem.title,
|
title: result.prevItem.title,
|
||||||
link: result.prevItem.path || "",
|
link: result.prevItem.path || "",
|
||||||
|
parentTitle: result.prevItem.parent?.title,
|
||||||
}
|
}
|
||||||
: undefined
|
: undefined
|
||||||
)
|
)
|
||||||
@@ -165,6 +183,7 @@ export const PaginationProvider = ({ children }: PaginationProviderProps) => {
|
|||||||
? {
|
? {
|
||||||
title: result.nextItem.title,
|
title: result.nextItem.title,
|
||||||
link: result.nextItem.path || "",
|
link: result.nextItem.path || "",
|
||||||
|
parentTitle: result.nextItem.parent?.title,
|
||||||
}
|
}
|
||||||
: undefined
|
: undefined
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -59,7 +59,7 @@ export type SidebarContextType = {
|
|||||||
setDesktopSidebarOpen: React.Dispatch<React.SetStateAction<boolean>>
|
setDesktopSidebarOpen: React.Dispatch<React.SetStateAction<boolean>>
|
||||||
staticSidebarItems?: boolean
|
staticSidebarItems?: boolean
|
||||||
shouldHandleHashChange: boolean
|
shouldHandleHashChange: boolean
|
||||||
sidebarRef: React.RefObject<HTMLUListElement>
|
sidebarRef: React.RefObject<HTMLDivElement>
|
||||||
goBack: () => void
|
goBack: () => void
|
||||||
} & SidebarStyleOptions
|
} & SidebarStyleOptions
|
||||||
|
|
||||||
@@ -198,7 +198,7 @@ export const SidebarProvider = ({
|
|||||||
const [activePath, setActivePath] = useState<string | null>("")
|
const [activePath, setActivePath] = useState<string | null>("")
|
||||||
const [mobileSidebarOpen, setMobileSidebarOpen] = useState<boolean>(false)
|
const [mobileSidebarOpen, setMobileSidebarOpen] = useState<boolean>(false)
|
||||||
const [desktopSidebarOpen, setDesktopSidebarOpen] = useState(true)
|
const [desktopSidebarOpen, setDesktopSidebarOpen] = useState(true)
|
||||||
const sidebarRef = useRef<HTMLUListElement>(null)
|
const sidebarRef = useRef<HTMLDivElement>(null)
|
||||||
|
|
||||||
const pathname = usePathname()
|
const pathname = usePathname()
|
||||||
const router = useRouter()
|
const router = useRouter()
|
||||||
@@ -311,7 +311,7 @@ export const SidebarProvider = ({
|
|||||||
}
|
}
|
||||||
|
|
||||||
setActivePath(backItem.path!)
|
setActivePath(backItem.path!)
|
||||||
setCurrentItems(currentItems.previousSidebar)
|
setCurrentItems(previousSidebar)
|
||||||
router.replace(backItem.path!)
|
router.replace(backItem.path!)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -405,7 +405,10 @@ export const SidebarProvider = ({
|
|||||||
bottom: [],
|
bottom: [],
|
||||||
mobile: items.mobile,
|
mobile: items.mobile,
|
||||||
parentItem: parentItem,
|
parentItem: parentItem,
|
||||||
previousSidebar: currentItems,
|
previousSidebar:
|
||||||
|
currentItems?.previousSidebar?.parentItem?.path !== parentItem.path
|
||||||
|
? currentItems
|
||||||
|
: undefined,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}, [getCurrentSidebar, activePath])
|
}, [getCurrentSidebar, activePath])
|
||||||
|
|||||||
@@ -1,17 +1,29 @@
|
|||||||
import { NavbarLinkProps, navbarItems } from ".."
|
import { NavbarItem, legacyNavbarItems, navbarItemsV1, navbarItemsV2 } from ".."
|
||||||
|
|
||||||
type Options = {
|
type Options = {
|
||||||
basePath: string
|
basePath: string
|
||||||
activePath: string
|
activePath: string
|
||||||
|
version?: "v1" | "v2" | "legacy"
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getNavbarItems({
|
export function getNavbarItems({
|
||||||
basePath,
|
basePath,
|
||||||
activePath,
|
activePath,
|
||||||
}: Options): NavbarLinkProps[] {
|
version = "legacy"
|
||||||
return navbarItems.map((item) => ({
|
}: Options): NavbarItem[] {
|
||||||
...item,
|
const navbarItems = version === "v2" ? navbarItemsV2 : version === "v1" ? navbarItemsV1 : legacyNavbarItems
|
||||||
isActive: activePath === item.href,
|
return navbarItems.map((item) => {
|
||||||
href: `${basePath}${item.href}`,
|
if (item.type === "divider") {
|
||||||
}))
|
return item
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
...item,
|
||||||
|
props: {
|
||||||
|
...item.props,
|
||||||
|
isActive: activePath === item.props?.href,
|
||||||
|
href: `${basePath}${item.props?.href}`,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
}
|
}
|
||||||
@@ -3,6 +3,7 @@ import { SidebarSectionItemsType } from "./sidebar.js"
|
|||||||
export declare type DocsConfig = {
|
export declare type DocsConfig = {
|
||||||
titleSuffix?: string
|
titleSuffix?: string
|
||||||
baseUrl: string
|
baseUrl: string
|
||||||
|
basePath?: string
|
||||||
sidebar: SidebarSectionItemsType
|
sidebar: SidebarSectionItemsType
|
||||||
filesBasePath?: string
|
filesBasePath?: string
|
||||||
useNextLinks?: boolean
|
useNextLinks?: boolean
|
||||||
|
|||||||
Reference in new issue
Block a user