docs: create docs workspace (#5174)
* docs: migrate ui docs to docs universe * created yarn workspace * added eslint and tsconfig configurations * fix eslint configurations * fixed eslint configurations * shared tailwind configurations * added shared ui package * added more shared components * migrating more components * made details components shared * move InlineCode component * moved InputText * moved Loading component * Moved Modal component * moved Select components * Moved Tooltip component * moved Search components * moved ColorMode provider * Moved Notification components and providers * used icons package * use UI colors in api-reference * moved Navbar component * used Navbar and Search in UI docs * added Feedback to UI docs * general enhancements * fix color mode * added copy colors file from ui-preset * added features and enhancements to UI docs * move Sidebar component and provider * general fixes and preparations for deployment * update docusaurus version * adjusted versions * fix output directory * remove rootDirectory property * fix yarn.lock * moved code component * added vale for all docs MD and MDX * fix tests * fix vale error * fix deployment errors * change ignore commands * add output directory * fix docs test * general fixes * content fixes * fix announcement script * added changeset * fix vale checks * added nofilter option * fix vale error
This commit is contained in:
5
.changeset/rich-pillows-act.md
Normal file
5
.changeset/rich-pillows-act.md
Normal file
@@ -0,0 +1,5 @@
|
||||
---
|
||||
"@medusajs/oas-github-ci": patch
|
||||
---
|
||||
|
||||
feat(@medusajs/oas-github-ci): changed output path to match new docs workspace
|
||||
2
.github/workflows/docs-new-announcement.yml
vendored
2
.github/workflows/docs-new-announcement.yml
vendored
@@ -43,6 +43,6 @@ jobs:
|
||||
base: "develop"
|
||||
title: "chore(docs): Generated Docs Announcement Bar (automated)"
|
||||
labels: "type: chore"
|
||||
add-paths: www/docs/**
|
||||
add-paths: www/apps/docs/**
|
||||
branch: "chore/generate-announcement"
|
||||
branch-suffix: "timestamp"
|
||||
|
||||
@@ -41,6 +41,6 @@ jobs:
|
||||
base: "develop"
|
||||
title: "chore(docs): Removed Docs Announcement Bar (automated)"
|
||||
labels: "type: chore"
|
||||
add-paths: www/docs/**
|
||||
add-paths: www/apps/docs/**
|
||||
branch: "chore/remove-announcement"
|
||||
branch-suffix: "timestamp"
|
||||
|
||||
115
.github/workflows/docs-test.yml
vendored
115
.github/workflows/docs-test.yml
vendored
@@ -2,8 +2,8 @@ name: Documentation Tests
|
||||
on:
|
||||
pull_request:
|
||||
paths:
|
||||
- www/docs/**
|
||||
- www/api-reference/**
|
||||
- www/**
|
||||
|
||||
jobs:
|
||||
docs-test:
|
||||
runs-on: ubuntu-latest
|
||||
@@ -29,17 +29,17 @@ jobs:
|
||||
with:
|
||||
extension: docs
|
||||
|
||||
- name: Install Docusaurus dependencies
|
||||
working-directory: www/docs
|
||||
- name: Install Workspace dependencies
|
||||
working-directory: www
|
||||
run: yarn install
|
||||
- name: Build Docusaurus website
|
||||
working-directory: www/docs
|
||||
working-directory: www
|
||||
env:
|
||||
NODE_OPTIONS: "--max-old-space-size=8192"
|
||||
API_URL: "https://docs.medusajs.com"
|
||||
run: yarn build
|
||||
run: yarn build:docs
|
||||
|
||||
lint:
|
||||
vale-docs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Cancel Previous Runs
|
||||
@@ -53,8 +53,8 @@ jobs:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Get Directories to Scan
|
||||
working-directory: www/docs/vale
|
||||
run: ./get-files.sh
|
||||
working-directory: www/vale
|
||||
run: ./get-files.sh docs content references
|
||||
id: directories
|
||||
|
||||
- name: Vale Linter
|
||||
@@ -63,8 +63,71 @@ jobs:
|
||||
files: ${{ steps.directories.outputs.LIST }}
|
||||
fail_on_error: true
|
||||
vale_flags: '--minAlertLevel=error'
|
||||
reporter: github-pr-check
|
||||
token: ${{ github.token }}
|
||||
filter_mode: nofilter
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ github.token }}
|
||||
REVIEWDOG_GITHUB_API_TOKEN: ${{ github.token }}
|
||||
|
||||
vale-ui:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Cancel Previous Runs
|
||||
uses: styfle/cancel-workflow-action@0.11.0
|
||||
with:
|
||||
access_token: ${{ github.token }}
|
||||
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Get Directories to Scan
|
||||
working-directory: www/vale
|
||||
run: ./get-files.sh ui src/content/docs
|
||||
id: directories
|
||||
|
||||
- name: Vale Linter
|
||||
uses: errata-ai/vale-action@reviewdog
|
||||
with:
|
||||
files: ${{ steps.directories.outputs.LIST }}
|
||||
fail_on_error: true
|
||||
vale_flags: '--minAlertLevel=error'
|
||||
reporter: github-pr-check
|
||||
token: ${{ github.token }}
|
||||
filter_mode: nofilter
|
||||
env:
|
||||
REVIEWDOG_GITHUB_API_TOKEN: ${{ github.token }}
|
||||
|
||||
vale-api:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Cancel Previous Runs
|
||||
uses: styfle/cancel-workflow-action@0.11.0
|
||||
with:
|
||||
access_token: ${{ github.token }}
|
||||
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Get Directories to Scan
|
||||
working-directory: www/vale
|
||||
run: ./get-files.sh api-reference app/_mdx
|
||||
id: directories
|
||||
|
||||
- name: Vale Linter
|
||||
uses: errata-ai/vale-action@reviewdog
|
||||
with:
|
||||
files: ${{ steps.directories.outputs.LIST }}
|
||||
fail_on_error: true
|
||||
vale_flags: '--minAlertLevel=error'
|
||||
reporter: github-pr-check
|
||||
token: ${{ github.token }}
|
||||
filter_mode: nofilter
|
||||
env:
|
||||
REVIEWDOG_GITHUB_API_TOKEN: ${{ github.token }}
|
||||
|
||||
eslint:
|
||||
runs-on: ubuntu-latest
|
||||
@@ -80,11 +143,11 @@ jobs:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Install dependencies
|
||||
working-directory: www/docs
|
||||
working-directory: www
|
||||
run: yarn install
|
||||
|
||||
- name: Run Eslint
|
||||
working-directory: www/docs
|
||||
working-directory: www
|
||||
run: yarn lint:content
|
||||
|
||||
code-docs-eslint:
|
||||
@@ -104,33 +167,9 @@ jobs:
|
||||
run: yarn install
|
||||
|
||||
- name: Install dependencies
|
||||
working-directory: www/docs
|
||||
working-directory: www
|
||||
run: yarn install
|
||||
|
||||
- name: Run Eslint
|
||||
working-directory: www/docs
|
||||
run: yarn lint
|
||||
|
||||
code-api-ref-eslint:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Cancel Previous Runs
|
||||
uses: styfle/cancel-workflow-action@0.11.0
|
||||
with:
|
||||
access_token: ${{ github.token }}
|
||||
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Install Monorepo dependencies
|
||||
run: yarn install
|
||||
|
||||
- name: Install dependencies
|
||||
working-directory: www/api-reference
|
||||
run: yarn install
|
||||
|
||||
- name: Run Eslint
|
||||
working-directory: www/api-reference
|
||||
working-directory: www
|
||||
run: yarn lint
|
||||
2
.github/workflows/generate-api-reference.yml
vendored
2
.github/workflows/generate-api-reference.yml
vendored
@@ -43,6 +43,6 @@ jobs:
|
||||
base: "develop"
|
||||
title: "chore(docs): Updated API Reference"
|
||||
labels: "type: chore"
|
||||
add-paths: www/api-reference/specs
|
||||
add-paths: www/apps/api-reference/specs
|
||||
branch: "chore/generate-api-ref"
|
||||
branch-suffix: "timestamp"
|
||||
|
||||
@@ -42,6 +42,6 @@ jobs:
|
||||
base: "develop"
|
||||
title: "chore(docs): Generated Entities Reference (automated)"
|
||||
labels: "type: chore"
|
||||
add-paths: www/docs/content/references/entities/**
|
||||
add-paths: www/apps/docs/content/references/entities/**
|
||||
branch: "chore/generate-entities"
|
||||
branch-suffix: "timestamp"
|
||||
|
||||
2
.github/workflows/generate-js-reference.yml
vendored
2
.github/workflows/generate-js-reference.yml
vendored
@@ -42,6 +42,6 @@ jobs:
|
||||
base: "develop"
|
||||
title: "chore(docs): Generated JS Client Reference"
|
||||
labels: "type: chore"
|
||||
add-paths: www/docs/content/references/js-client/**
|
||||
add-paths: www/apps/docs/content/references/js-client/**
|
||||
branch: "chore/generate-js-client"
|
||||
branch-suffix: "timestamp"
|
||||
|
||||
2
.github/workflows/generate-reference.yml
vendored
2
.github/workflows/generate-reference.yml
vendored
@@ -42,6 +42,6 @@ jobs:
|
||||
base: "develop"
|
||||
title: "chore(docs): Generated Services Reference (automated)"
|
||||
labels: "type: chore"
|
||||
add-paths: www/docs/content/references/services/**
|
||||
add-paths: www/apps/docs/content/references/services/**
|
||||
branch: "chore/generate-services"
|
||||
branch-suffix: "timestamp"
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
StylesPath = www/docs/vale/styles
|
||||
StylesPath = www/vale/styles
|
||||
|
||||
MinAlertLevel = suggestion
|
||||
Vocab = Base
|
||||
|
||||
@@ -8,7 +8,7 @@ const execa = require("execa")
|
||||
const isDryRun = process.argv.indexOf("--dry-run") !== -1
|
||||
const basePath = path.resolve(__dirname, `../`)
|
||||
const repoRootPath = path.resolve(basePath, `../../../`)
|
||||
const docsApiPath = path.resolve(repoRootPath, "www/api-reference/specs")
|
||||
const docsApiPath = path.resolve(repoRootPath, "www/apps/api-reference/specs")
|
||||
|
||||
const run = async () => {
|
||||
const oasOutDir = isDryRun ? await getTmpDirectory() : docsApiPath
|
||||
|
||||
@@ -18,7 +18,7 @@ async function main () {
|
||||
const commitResponse = await octokit.request('GET /repos/{owner}/{repo}/commits', {
|
||||
owner: 'medusajs',
|
||||
repo: 'medusa',
|
||||
path: path.join('www', 'docs', 'announcement.json'),
|
||||
path: path.join('www', "apps", 'docs', 'announcement.json'),
|
||||
per_page: 1
|
||||
})
|
||||
|
||||
@@ -47,7 +47,7 @@ async function main () {
|
||||
}
|
||||
|
||||
//write new config file
|
||||
fs.writeFileSync(path.join(__dirname, '..', 'www', 'docs', 'announcement.json'), JSON.stringify(announcement));
|
||||
fs.writeFileSync(path.join(__dirname, '..', 'www', "apps", 'docs', 'announcement.json'), JSON.stringify(announcement));
|
||||
console.log(`Announcement Bar has been ${shouldExpire ? 'removed' : 'added'}`);
|
||||
}
|
||||
|
||||
|
||||
@@ -13,7 +13,7 @@ const linearClient = new LinearClient({
|
||||
apiKey: process.env.LINEAR_API_KEY
|
||||
});
|
||||
|
||||
const repoPath = path.join('docs', 'content');
|
||||
const repoPath = path.join('www', 'apps', 'docs', 'content');
|
||||
let freshnessCheckLabelId = "";
|
||||
let documentationTeamId = "";
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@ const globalTypedocOptions = require("./typedoc")
|
||||
module.exports = {
|
||||
...globalTypedocOptions,
|
||||
entryPoints: ["packages/medusa/src/models/index.ts"],
|
||||
out: ["www/docs/content/references/entities"],
|
||||
out: ["www/apps/docs/content/references/entities"],
|
||||
tsconfig: "packages/medusa/tsconfig.json",
|
||||
name: "Entities Reference",
|
||||
indexTitle: "Entities Reference",
|
||||
|
||||
@@ -4,7 +4,7 @@ module.exports = {
|
||||
...globalTypedocOptions,
|
||||
entryPoints: ["packages/medusa-js/src/resources"],
|
||||
entryPointStrategy: "expand",
|
||||
out: ["www/docs/content/references/js-client"],
|
||||
out: ["www/apps/docs/content/references/js-client"],
|
||||
tsconfig: "packages/medusa-js/tsconfig.json",
|
||||
name: "JS Client Reference",
|
||||
indexTitle: "JS Client Reference",
|
||||
|
||||
@@ -3,7 +3,7 @@ const globalTypedocOptions = require("./typedoc")
|
||||
module.exports = {
|
||||
...globalTypedocOptions,
|
||||
entryPoints: ["packages/medusa/src/services/index.ts"],
|
||||
out: ["www/docs/content/references/services"],
|
||||
out: ["www/apps/docs/content/references/services"],
|
||||
tsconfig: "packages/medusa/tsconfig.json",
|
||||
name: "Services Reference",
|
||||
indexTitle: "Services Reference",
|
||||
|
||||
129
www/.eslintrc.js
129
www/.eslintrc.js
@@ -1,127 +1,10 @@
|
||||
module.exports = {
|
||||
root: true,
|
||||
parser: "@babel/eslint-parser",
|
||||
parserOptions: {
|
||||
requireConfigFile: false,
|
||||
ecmaFeatures: {
|
||||
experimentalDecorators: true,
|
||||
jsx: true
|
||||
},
|
||||
},
|
||||
plugins: [
|
||||
"prettier"
|
||||
],
|
||||
extends: [
|
||||
"eslint:recommended",
|
||||
"plugin:prettier/recommended",
|
||||
"plugin:react/recommended",
|
||||
"plugin:react/jsx-runtime",
|
||||
],
|
||||
// This tells ESLint to load the config from the package `eslint-config-docs`
|
||||
extends: ["docs"],
|
||||
settings: {
|
||||
react: {
|
||||
version: "detect"
|
||||
}
|
||||
},
|
||||
rules: {
|
||||
curly: ["error", "all"],
|
||||
"new-cap": "off",
|
||||
"require-jsdoc": "off",
|
||||
"no-unused-expressions": "off",
|
||||
"no-unused-vars": "off",
|
||||
camelcase: "off",
|
||||
"no-invalid-this": "off",
|
||||
"max-len": [
|
||||
"error",
|
||||
{
|
||||
code: 80,
|
||||
ignoreStrings: true,
|
||||
ignoreRegExpLiterals: true,
|
||||
ignoreComments: true,
|
||||
ignoreTrailingComments: true,
|
||||
ignoreUrls: true,
|
||||
ignoreTemplateLiterals: true,
|
||||
},
|
||||
],
|
||||
semi: ["error", "never"],
|
||||
quotes: [
|
||||
"error",
|
||||
"double",
|
||||
{
|
||||
allowTemplateLiterals: true,
|
||||
},
|
||||
],
|
||||
"comma-dangle": [
|
||||
"error",
|
||||
{
|
||||
arrays: "always-multiline",
|
||||
objects: "always-multiline",
|
||||
imports: "always-multiline",
|
||||
exports: "always-multiline",
|
||||
functions: "never",
|
||||
},
|
||||
],
|
||||
"object-curly-spacing": ["error", "always"],
|
||||
"arrow-parens": ["error", "always"],
|
||||
"linebreak-style": 0,
|
||||
"no-confusing-arrow": [
|
||||
"error",
|
||||
{
|
||||
allowParens: false,
|
||||
},
|
||||
],
|
||||
"space-before-function-paren": [
|
||||
"error",
|
||||
{
|
||||
anonymous: "always",
|
||||
named: "never",
|
||||
asyncArrow: "always",
|
||||
},
|
||||
],
|
||||
"space-infix-ops": "error",
|
||||
"eol-last": ["error", "always"],
|
||||
"no-console": [
|
||||
"error",
|
||||
{
|
||||
allow: [
|
||||
"error",
|
||||
"warn"
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
env: {
|
||||
es6: true,
|
||||
node: true,
|
||||
jest: true,
|
||||
browser: true,
|
||||
},
|
||||
ignorePatterns: [],
|
||||
overrides: [
|
||||
{
|
||||
files: ["*.ts", "*.tsx", "*.js", "*.jsx"],
|
||||
plugins: ["@typescript-eslint/eslint-plugin"],
|
||||
extends: ["plugin:@typescript-eslint/recommended", "plugin:react/recommended"],
|
||||
parser: "@typescript-eslint/parser",
|
||||
parserOptions: {
|
||||
project: "./tsconfig.json",
|
||||
},
|
||||
rules: {
|
||||
"valid-jsdoc": "off",
|
||||
"@typescript-eslint/no-non-null-assertion": "off",
|
||||
"@typescript-eslint/no-floating-promises": "error",
|
||||
"@typescript-eslint/await-thenable": "error",
|
||||
"@typescript-eslint/promise-function-async": "error",
|
||||
"@typescript-eslint/keyword-spacing": "error",
|
||||
"@typescript-eslint/space-before-function-paren": [
|
||||
"error",
|
||||
{
|
||||
anonymous: "always",
|
||||
named: "never",
|
||||
asyncArrow: "always",
|
||||
},
|
||||
],
|
||||
"@typescript-eslint/space-infix-ops": "error",
|
||||
},
|
||||
next: {
|
||||
rootDir: ["apps/*/"],
|
||||
},
|
||||
],
|
||||
}
|
||||
},
|
||||
};
|
||||
10
www/.gitignore
vendored
10
www/.gitignore
vendored
@@ -1,2 +1,10 @@
|
||||
.vercel
|
||||
build
|
||||
build
|
||||
node_modules
|
||||
.yarn/*
|
||||
.yarn/install-state.gz
|
||||
!.yarn/patches
|
||||
!.yarn/plugins
|
||||
!.yarn/releases
|
||||
!.yarn/sdks
|
||||
!.yarn/versions
|
||||
@@ -1,4 +0,0 @@
|
||||
next.config.js
|
||||
specs
|
||||
node_modules
|
||||
public
|
||||
@@ -1,16 +0,0 @@
|
||||
{
|
||||
"extends": [
|
||||
"next/core-web-vitals",
|
||||
"google",
|
||||
"../.eslintrc.js"
|
||||
],
|
||||
"rules": {
|
||||
"react/react-in-jsx-scope": "off",
|
||||
"@typescript-eslint/prefer-ts-expect-error": "off"
|
||||
},
|
||||
"settings": {
|
||||
"next": {
|
||||
"rootDir": "."
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,21 +0,0 @@
|
||||
import Feedback from "@/components/Feedback"
|
||||
|
||||
This API reference includes Medusa's Admin APIs, which are REST APIs exposed by the Medusa backend. They are typically used to perform admin functionalities or create an admin dashboard to access and manipulate your commerce store's data.
|
||||
|
||||
All endpoints are prefixed with `/admin`. So, during development, the endpoints will be available under the path `http://localhost:9000/admin`. For production, replace `http://localhost:9000` with your Medusa backend URL.
|
||||
|
||||
There are different ways you can send requests to these endpoints, including:
|
||||
|
||||
- Using Medusa's [JavaScript Client](https://docs.medusajs.com/js-client/overview)
|
||||
- Using the [Medusa React](https://docs.medusajs.com/medusa-react/overview) library
|
||||
- Using cURL
|
||||
|
||||
Aside from this API reference, check out the [Commerce Modules](https://docs.medusajs.com/modules/overview) section of the documentation for guides on how to use these APIs in different scenarios.
|
||||
|
||||
<Feedback
|
||||
event="survey_api-ref"
|
||||
extraData={{
|
||||
area: "admin",
|
||||
section: "introduction"
|
||||
}}
|
||||
/>
|
||||
@@ -1,21 +0,0 @@
|
||||
import Feedback from "@/components/Feedback"
|
||||
|
||||
This API reference includes Medusa's Store APIs, which are REST APIs exposed by the Medusa backend. They are typically used to create a storefront for your commerce store, such as a webshop or a commerce mobile app.
|
||||
|
||||
All endpoints are prefixed with `/store`. So, during development, the endpoints will be available under the path `http://localhost:9000/store`. For production, replace `http://localhost:9000` with your Medusa backend URL.
|
||||
|
||||
There are different ways you can send requests to these endpoints, including:
|
||||
|
||||
- Using Medusa's [JavaScript Client](https://docs.medusajs.com/js-client/overview)
|
||||
- Using the [Medusa React](https://docs.medusajs.com/medusa-react/overview) library
|
||||
- Using cURL
|
||||
|
||||
Aside from this API reference, check out the [Commerce Modules](https://docs.medusajs.com/modules/overview) section of the documentation for guides on how to use these APIs in different scenarios.
|
||||
|
||||
<Feedback
|
||||
event="survey_api-ref"
|
||||
extraData={{
|
||||
area: "store",
|
||||
section: "introduction"
|
||||
}}
|
||||
/>
|
||||
@@ -1,81 +0,0 @@
|
||||
import SidebarProvider from "@/providers/sidebar"
|
||||
import Sidebar from "@/components/Sidebar"
|
||||
import clsx from "clsx"
|
||||
import "../../../css/globals.css"
|
||||
import BaseSpecsProvider from "@/providers/base-specs"
|
||||
import Navbar from "@/components/Navbar"
|
||||
import ColorModeProvider from "@/providers/color-mode"
|
||||
import { Inter } from "next/font/google"
|
||||
import { Roboto_Mono } from "next/font/google"
|
||||
import AnalyticsProvider from "@/providers/analytics"
|
||||
import NavbarProvider from "@/providers/navbar"
|
||||
import ModalProvider from "../../../providers/modal"
|
||||
import SearchProvider from "../../../providers/search"
|
||||
import { ScrollControllerProvider } from "../../../hooks/scroll-utils"
|
||||
import MobileProvider from "../../../providers/mobile"
|
||||
import PageLoadingProvider from "../../../providers/page-loading"
|
||||
|
||||
export const metadata = {
|
||||
title: "Medusa API Reference",
|
||||
description: "Check out Medusa's API reference",
|
||||
}
|
||||
|
||||
const inter = Inter({
|
||||
subsets: ["latin"],
|
||||
variable: "--font-inter",
|
||||
weight: ["400", "500"],
|
||||
})
|
||||
|
||||
const robotoMono = Roboto_Mono({
|
||||
subsets: ["latin"],
|
||||
variable: "--font-roboto-mono",
|
||||
})
|
||||
|
||||
export default function RootLayout({
|
||||
children,
|
||||
}: {
|
||||
children: React.ReactNode
|
||||
}) {
|
||||
return (
|
||||
<html lang="en" className={clsx("h-full w-full")}>
|
||||
<body
|
||||
className={clsx(
|
||||
inter.variable,
|
||||
robotoMono.variable,
|
||||
"bg-docs-bg dark:bg-docs-bg-dark font-base text-medium h-full w-full",
|
||||
"text-medusa-fg-subtle dark:text-medusa-fg-subtle-dark"
|
||||
)}
|
||||
>
|
||||
<AnalyticsProvider>
|
||||
<PageLoadingProvider>
|
||||
<ModalProvider>
|
||||
<ColorModeProvider>
|
||||
<BaseSpecsProvider>
|
||||
<SidebarProvider>
|
||||
<NavbarProvider>
|
||||
<ScrollControllerProvider>
|
||||
<SearchProvider>
|
||||
<MobileProvider>
|
||||
<div className="w-full">
|
||||
<Navbar />
|
||||
<div className="max-w-xxl mx-auto flex w-full px-1.5">
|
||||
<Sidebar />
|
||||
<main className="lg:w-api-ref-main relative mt-4 w-full flex-1 lg:mt-7">
|
||||
{children}
|
||||
</main>
|
||||
</div>
|
||||
</div>
|
||||
</MobileProvider>
|
||||
</SearchProvider>
|
||||
</ScrollControllerProvider>
|
||||
</NavbarProvider>
|
||||
</SidebarProvider>
|
||||
</BaseSpecsProvider>
|
||||
</ColorModeProvider>
|
||||
</ModalProvider>
|
||||
</PageLoadingProvider>
|
||||
</AnalyticsProvider>
|
||||
</body>
|
||||
</html>
|
||||
)
|
||||
}
|
||||
@@ -1,53 +0,0 @@
|
||||
import React from "react"
|
||||
import clsx from "clsx"
|
||||
|
||||
export type BadgeProps = {
|
||||
className?: string
|
||||
variant:
|
||||
| "purple"
|
||||
| "purple-dark"
|
||||
| "orange"
|
||||
| "orange-dark"
|
||||
| "green"
|
||||
| "green-dark"
|
||||
| "blue"
|
||||
| "blue-dark"
|
||||
| "red"
|
||||
| "neutral"
|
||||
} & React.HTMLAttributes<HTMLSpanElement>
|
||||
|
||||
const Badge: React.FC<BadgeProps> = ({ className, variant, children }) => {
|
||||
return (
|
||||
<span
|
||||
className={clsx(
|
||||
"text-compact-x-small-plus px-0.4 rounded-sm border border-solid py-px text-center",
|
||||
variant === "purple" &&
|
||||
"bg-medusa-tag-purple-bg dark:bg-medusa-tag-purple-bg-dark text-medusa-tag-purple-text dark:text-medusa-tag-purple-text-dark border-medusa-tag-purple-border dark:border-medusa-tag-purple-border-dark",
|
||||
variant === "purple-dark" &&
|
||||
"bg-medusa-tag-purple-bg-dark text-medusa-tag-purple-text-dark border-medusa-tag-purple-border-dark",
|
||||
variant === "orange" &&
|
||||
"bg-medusa-tag-orange-bg dark:bg-medusa-tag-orange-bg-dark text-medusa-tag-orange-text dark:text-medusa-tag-orange-text-dark border-medusa-tag-orange-border dark:border-medusa-tag-orange-border-dark",
|
||||
variant === "orange-dark" &&
|
||||
"bg-medusa-tag-orange-bg-dark text-medusa-tag-orange-text-dark border-medusa-tag-orange-border-dark",
|
||||
variant === "green" &&
|
||||
"bg-medusa-tag-green-bg dark:bg-medusa-tag-green-bg-dark text-medusa-tag-green-text dark:text-medusa-tag-green-text-dark border-medusa-tag-green-border dark:border-medusa-tag-green-border-dark",
|
||||
variant === "green-dark" &&
|
||||
"bg-medusa-tag-green-bg-dark text-medusa-tag-green-text-dark border-medusa-tag-green-border-dark",
|
||||
variant === "blue" &&
|
||||
"bg-medusa-tag-blue-bg dark:bg-medusa-tag-blue-bg-dark text-medusa-tag-blue-text dark:text-medusa-tag-blue-text-dark border-medusa-tag-blue-border dark:border-medusa-tag-blue-border-dark",
|
||||
variant === "blue-dark" &&
|
||||
"bg-medusa-tag-blue-bg-dark text-medusa-tag-blue-text-dark border-medusa-tag-blue-border-dark",
|
||||
variant === "red" &&
|
||||
"bg-medusa-tag-red-bg dark:bg-medusa-tag-red-bg-dark text-medusa-tag-red-text dark:text-medusa-tag-red-text-dark border-medusa-tag-red-border dark:border-medusa-tag-red-border-dark",
|
||||
variant === "neutral" &&
|
||||
"bg-medusa-tag-neutral-bg dark:bg-medusa-tag-neutral-bg-dark text-medusa-tag-neutral-text dark:text-medusa-tag-neutral-text-dark border-medusa-tag-neutral-border dark:border-medusa-tag-neutral-border-dark",
|
||||
"badge",
|
||||
className
|
||||
)}
|
||||
>
|
||||
{children}
|
||||
</span>
|
||||
)
|
||||
}
|
||||
|
||||
export default Badge
|
||||
@@ -1,56 +0,0 @@
|
||||
import React from "react"
|
||||
import clsx from "clsx"
|
||||
import Bordered from "../Bordered/index"
|
||||
import IconProps from "../Icons/types"
|
||||
import { useColorMode } from "../../providers/color-mode"
|
||||
import Image from "next/image"
|
||||
|
||||
type BorderedIconProp = {
|
||||
icon?: {
|
||||
light: string
|
||||
dark?: string
|
||||
}
|
||||
IconComponent?: React.FC<IconProps>
|
||||
wrapperClassName?: string
|
||||
iconWrapperClassName?: string
|
||||
iconClassName?: string
|
||||
iconColorClassName?: string
|
||||
} & React.HTMLAttributes<HTMLSpanElement>
|
||||
|
||||
const BorderedIcon: React.FC<BorderedIconProp> = ({
|
||||
icon = null,
|
||||
IconComponent = null,
|
||||
wrapperClassName,
|
||||
iconWrapperClassName,
|
||||
iconClassName,
|
||||
iconColorClassName = "",
|
||||
}) => {
|
||||
const { colorMode } = useColorMode()
|
||||
|
||||
return (
|
||||
<Bordered wrapperClassName={wrapperClassName}>
|
||||
<span
|
||||
className={clsx(
|
||||
"rounded-xs p-0.125 bg-medusa-bg-component dark:bg-medusa-bg-component-dark inline-flex items-center justify-center",
|
||||
iconWrapperClassName
|
||||
)}
|
||||
>
|
||||
{!IconComponent && (
|
||||
<Image
|
||||
src={(colorMode === "light" ? icon?.light : icon?.dark) || ""}
|
||||
className={clsx(iconClassName, "bordered-icon")}
|
||||
alt=""
|
||||
/>
|
||||
)}
|
||||
{IconComponent && (
|
||||
<IconComponent
|
||||
className={clsx(iconClassName, "bordered-icon")}
|
||||
iconColorClassName={iconColorClassName}
|
||||
/>
|
||||
)}
|
||||
</span>
|
||||
</Bordered>
|
||||
)
|
||||
}
|
||||
|
||||
export default BorderedIcon
|
||||
@@ -1,35 +0,0 @@
|
||||
import clsx from "clsx"
|
||||
|
||||
export type ButtonProps = {
|
||||
isSelected?: boolean
|
||||
disabled?: boolean
|
||||
variant?: "primary" | "secondary" | "clear"
|
||||
darkVariant?: "primary" | "secondary" | "clear"
|
||||
} & React.HTMLAttributes<HTMLButtonElement>
|
||||
|
||||
const Button = ({
|
||||
className,
|
||||
children,
|
||||
variant = "primary",
|
||||
darkVariant,
|
||||
...props
|
||||
}: ButtonProps) => {
|
||||
return (
|
||||
<button
|
||||
className={clsx(
|
||||
variant === "primary" && "btn-primary",
|
||||
variant === "secondary" && "btn-secondary",
|
||||
variant === "clear" && "btn-clear",
|
||||
darkVariant && darkVariant === "primary" && "dark:btn-primary",
|
||||
darkVariant && darkVariant === "secondary" && "dark:btn-secondary",
|
||||
darkVariant && darkVariant === "clear" && "dark:btn-clear",
|
||||
className
|
||||
)}
|
||||
{...props}
|
||||
>
|
||||
{children}
|
||||
</button>
|
||||
)
|
||||
}
|
||||
|
||||
export default Button
|
||||
@@ -1,43 +0,0 @@
|
||||
import clsx from "clsx"
|
||||
import Link from "next/link"
|
||||
import IconArrowUpRightOnBox from "../Icons/ArrowUpRightOnBox"
|
||||
|
||||
type CardProps = {
|
||||
title: string
|
||||
text?: string
|
||||
href?: string
|
||||
className?: string
|
||||
}
|
||||
|
||||
const Card = ({ title, text, href, className }: CardProps) => {
|
||||
return (
|
||||
<div
|
||||
className={clsx(
|
||||
"bg-medusa-bg-subtle dark:bg-medusa-code-bg-base-dark w-full rounded",
|
||||
"shadow-card-rest dark:shadow-card-rest-dark py-0.75 relative px-1",
|
||||
"flex items-center justify-between gap-1 transition-shadow",
|
||||
href && "hover:shadow-card-hover dark:hover:shadow-card-hover-dark",
|
||||
className
|
||||
)}
|
||||
>
|
||||
<div className="flex flex-col">
|
||||
<span className="text-compact-medium-plus text-medusa-fg-base dark:text-medusa-fg-base-dark">
|
||||
{title}
|
||||
</span>
|
||||
{text && <span className="text-compact-medium">{text}</span>}
|
||||
</div>
|
||||
|
||||
{href && (
|
||||
<>
|
||||
<IconArrowUpRightOnBox />
|
||||
<Link
|
||||
href={href}
|
||||
className="absolute left-0 top-0 h-full w-full rounded"
|
||||
/>
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export default Card
|
||||
@@ -1,54 +0,0 @@
|
||||
"use client"
|
||||
|
||||
import { useState, useEffect, useRef, useCallback } from "react"
|
||||
import clsx from "clsx"
|
||||
import dynamic from "next/dynamic"
|
||||
import { TooltipProps } from "../Tooltip"
|
||||
import SpinnerLoading from "../Loading/Spinner"
|
||||
|
||||
const Tooltip = dynamic<TooltipProps>(async () => import("../Tooltip"), {
|
||||
loading: () => <SpinnerLoading />,
|
||||
}) as React.FC<TooltipProps>
|
||||
|
||||
export type CopyButtonProps = {
|
||||
text: string
|
||||
buttonClassName?: string
|
||||
tooltipClassName?: string
|
||||
} & React.HTMLAttributes<HTMLDivElement>
|
||||
|
||||
const CopyButton = ({
|
||||
text,
|
||||
buttonClassName = "",
|
||||
tooltipClassName = "",
|
||||
children,
|
||||
}: CopyButtonProps) => {
|
||||
const [isCopied, setIsCopied] = useState(false)
|
||||
const copyTimeout = useRef<number | undefined>(undefined)
|
||||
|
||||
const handleCopy = useCallback(async () => {
|
||||
const copy = (await import("copy-text-to-clipboard")).default
|
||||
copy(text)
|
||||
setIsCopied(true)
|
||||
copyTimeout.current = window.setTimeout(() => {
|
||||
setIsCopied(false)
|
||||
}, 1000)
|
||||
}, [text])
|
||||
|
||||
useEffect(() => () => window.clearTimeout(copyTimeout.current), [])
|
||||
|
||||
return (
|
||||
<Tooltip
|
||||
text={isCopied ? `Copied!` : `Copy to Clipboard`}
|
||||
tooltipClassName={tooltipClassName}
|
||||
>
|
||||
<span
|
||||
className={clsx("cursor-pointer", buttonClassName)}
|
||||
onClick={handleCopy}
|
||||
>
|
||||
{children}
|
||||
</span>
|
||||
</Tooltip>
|
||||
)
|
||||
}
|
||||
|
||||
export default CopyButton
|
||||
@@ -1,207 +0,0 @@
|
||||
"use client"
|
||||
|
||||
import React, { useRef, useState } from "react"
|
||||
import { CSSTransition, SwitchTransition } from "react-transition-group"
|
||||
import Solutions from "./Solutions/index"
|
||||
import Button from "../Button"
|
||||
import { ExtraData, useAnalytics } from "@/providers/analytics"
|
||||
import { usePathname } from "next/navigation"
|
||||
import Link from "next/link"
|
||||
import { useArea } from "../../providers/area"
|
||||
import clsx from "clsx"
|
||||
import TextArea from "../TextArea"
|
||||
import Label from "../Label"
|
||||
|
||||
type FeedbackProps = {
|
||||
event: string
|
||||
question?: string
|
||||
positiveBtn?: string
|
||||
negativeBtn?: string
|
||||
positiveQuestion?: string
|
||||
negativeQuestion?: string
|
||||
submitBtn?: string
|
||||
submitMessage?: string
|
||||
showPossibleSolutions?: boolean
|
||||
className?: string
|
||||
extraData?: ExtraData
|
||||
sectionTitle?: string
|
||||
vertical?: boolean
|
||||
} & React.HTMLAttributes<HTMLDivElement>
|
||||
|
||||
const Feedback: React.FC<FeedbackProps> = ({
|
||||
event,
|
||||
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 = {},
|
||||
sectionTitle = "",
|
||||
vertical = false,
|
||||
}) => {
|
||||
const [showForm, setShowForm] = useState(false)
|
||||
const [submittedFeedback, setSubmittedFeedback] = useState(false)
|
||||
const [loading, setLoading] = useState(false)
|
||||
const inlineFeedbackRef = useRef<HTMLDivElement>(null)
|
||||
const inlineQuestionRef = useRef<HTMLDivElement>(null)
|
||||
const inlineMessageRef = useRef<HTMLDivElement>(null)
|
||||
const [positiveFeedback, setPositiveFeedback] = useState(false)
|
||||
const [message, setMessage] = useState("")
|
||||
const nodeRef: React.RefObject<HTMLDivElement> = submittedFeedback
|
||||
? inlineMessageRef
|
||||
: showForm
|
||||
? inlineQuestionRef
|
||||
: inlineFeedbackRef
|
||||
|
||||
const pathname = usePathname()
|
||||
const { loaded, track } = useAnalytics()
|
||||
const { area } = useArea()
|
||||
|
||||
function handleFeedback(e: React.MouseEvent<HTMLButtonElement, 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<HTMLButtonElement, 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,
|
||||
...extraData,
|
||||
},
|
||||
function () {
|
||||
if (showForm) {
|
||||
setLoading(false)
|
||||
resetForm()
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
function resetForm() {
|
||||
setShowForm(false)
|
||||
setSubmittedFeedback(true)
|
||||
}
|
||||
|
||||
return (
|
||||
<div className={clsx("mt-3", className)}>
|
||||
<SwitchTransition mode="out-in">
|
||||
<CSSTransition
|
||||
key={
|
||||
showForm
|
||||
? "show_form"
|
||||
: !submittedFeedback
|
||||
? "feedback"
|
||||
: "submitted_feedback"
|
||||
}
|
||||
nodeRef={nodeRef}
|
||||
timeout={300}
|
||||
addEndListener={(done) => {
|
||||
nodeRef.current?.addEventListener("transitionend", done, false)
|
||||
}}
|
||||
classNames={{
|
||||
enter: "animate-fadeIn animate-fill-forwards animate-fast",
|
||||
exit: "animate-fadeOut animate-fill-forwards animate-fast",
|
||||
}}
|
||||
>
|
||||
<>
|
||||
{!showForm && !submittedFeedback && (
|
||||
<div
|
||||
className={clsx(
|
||||
"flex",
|
||||
!vertical && "flex-row items-center",
|
||||
vertical && "flex-col justify-center gap-1"
|
||||
)}
|
||||
ref={inlineFeedbackRef}
|
||||
>
|
||||
<Label className="mr-1.5">{question}</Label>
|
||||
<div className={clsx("flex flex-row items-center gap-0.5")}>
|
||||
<Button
|
||||
onClick={handleFeedback}
|
||||
className="positive w-fit"
|
||||
variant="secondary"
|
||||
>
|
||||
{positiveBtn}
|
||||
</Button>
|
||||
<Button
|
||||
onClick={handleFeedback}
|
||||
className="w-fit"
|
||||
variant="secondary"
|
||||
>
|
||||
{negativeBtn}
|
||||
</Button>
|
||||
<Link
|
||||
href={`https://github.com/medusajs/medusa/issues/new?assignees=&labels=type%3A+docs&template=docs.yml&title=API%20Ref%28${area}%29%3A%20Issue%20in%20${encodeURI(
|
||||
sectionTitle
|
||||
)}`}
|
||||
className="btn-secondary"
|
||||
>
|
||||
Report Issue
|
||||
</Link>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
{showForm && !submittedFeedback && (
|
||||
<div className="flex flex-col gap-1" ref={inlineQuestionRef}>
|
||||
<Label>
|
||||
{positiveFeedback ? positiveQuestion : negativeQuestion}
|
||||
</Label>
|
||||
<TextArea
|
||||
rows={4}
|
||||
value={message}
|
||||
onChange={(e) => setMessage(e.target.value)}
|
||||
/>
|
||||
<Button
|
||||
onClick={submitFeedback}
|
||||
disabled={loading}
|
||||
className="w-fit"
|
||||
variant="secondary"
|
||||
>
|
||||
{submitBtn}
|
||||
</Button>
|
||||
</div>
|
||||
)}
|
||||
{submittedFeedback && (
|
||||
<div>
|
||||
<div
|
||||
className="text-compact-large-plus flex flex-col"
|
||||
ref={inlineMessageRef}
|
||||
>
|
||||
<span>{submitMessage}</span>
|
||||
{showPossibleSolutions && (
|
||||
<Solutions message={message} feedback={positiveFeedback} />
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</>
|
||||
</CSSTransition>
|
||||
</SwitchTransition>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export default Feedback
|
||||
@@ -1,26 +0,0 @@
|
||||
import type IconProps from "../types"
|
||||
|
||||
const IconAlert = ({ iconColorClassName, ...props }: IconProps) => {
|
||||
return (
|
||||
<svg
|
||||
width={props.width || 20}
|
||||
height={props.height || 20}
|
||||
viewBox="0 0 20 20"
|
||||
fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
{...props}
|
||||
>
|
||||
<path
|
||||
fillRule="evenodd"
|
||||
clipRule="evenodd"
|
||||
d="M18 10C18 12.1217 17.1571 14.1566 15.6569 15.6569C14.1566 17.1571 12.1217 18 10 18C7.87827 18 5.84344 17.1571 4.34315 15.6569C2.84285 14.1566 2 12.1217 2 10C2 7.87827 2.84285 5.84344 4.34315 4.34315C5.84344 2.84285 7.87827 2 10 2C12.1217 2 14.1566 2.84285 15.6569 4.34315C17.1571 5.84344 18 7.87827 18 10ZM10 5C10.1989 5 10.3897 5.07902 10.5303 5.21967C10.671 5.36032 10.75 5.55109 10.75 5.75V10.25C10.75 10.4489 10.671 10.6397 10.5303 10.7803C10.3897 10.921 10.1989 11 10 11C9.80109 11 9.61032 10.921 9.46967 10.7803C9.32902 10.6397 9.25 10.4489 9.25 10.25V5.75C9.25 5.55109 9.32902 5.36032 9.46967 5.21967C9.61032 5.07902 9.80109 5 10 5ZM10 15C10.2652 15 10.5196 14.8946 10.7071 14.7071C10.8946 14.5196 11 14.2652 11 14C11 13.7348 10.8946 13.4804 10.7071 13.2929C10.5196 13.1054 10.2652 13 10 13C9.73478 13 9.48043 13.1054 9.29289 13.2929C9.10536 13.4804 9 13.7348 9 14C9 14.2652 9.10536 14.5196 9.29289 14.7071C9.48043 14.8946 9.73478 15 10 15Z"
|
||||
className={
|
||||
iconColorClassName ||
|
||||
"fill-medusa-fg-subtle dark:fill-medusa-fg-subtle-dark"
|
||||
}
|
||||
/>
|
||||
</svg>
|
||||
)
|
||||
}
|
||||
|
||||
export default IconAlert
|
||||
@@ -1,37 +0,0 @@
|
||||
import type IconProps from "../types"
|
||||
|
||||
const IconArrowDownLeftMini = ({ iconColorClassName, ...props }: IconProps) => {
|
||||
return (
|
||||
<svg
|
||||
width={props.width || 20}
|
||||
height={props.height || 20}
|
||||
viewBox="0 0 20 20"
|
||||
fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
{...props}
|
||||
>
|
||||
<path
|
||||
d="M8.00002 8.66675L4.66669 12.0001L8.00002 15.3334"
|
||||
className={
|
||||
iconColorClassName ||
|
||||
"stroke-medusa-fg-subtle dark:stroke-medusa-fg-subtle-dark"
|
||||
}
|
||||
strokeWidth="1.5"
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
/>
|
||||
<path
|
||||
d="M15.3334 4.66675V9.33341C15.3334 10.0407 15.0524 10.7189 14.5523 11.219C14.0522 11.7191 13.3739 12.0001 12.6667 12.0001H4.66669"
|
||||
className={
|
||||
iconColorClassName ||
|
||||
"stroke-medusa-fg-subtle dark:stroke-medusa-fg-subtle-dark"
|
||||
}
|
||||
strokeWidth="1.5"
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
/>
|
||||
</svg>
|
||||
)
|
||||
}
|
||||
|
||||
export default IconArrowDownLeftMini
|
||||
@@ -1,27 +0,0 @@
|
||||
import type IconProps from "../types"
|
||||
|
||||
const IconArrowUpRightOnBox = ({ iconColorClassName, ...props }: IconProps) => {
|
||||
return (
|
||||
<svg
|
||||
width={props.width || 20}
|
||||
height={props.height || 20}
|
||||
viewBox="0 0 20 20"
|
||||
fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
{...props}
|
||||
>
|
||||
<path
|
||||
d="M9.55356 5.32683H5.24268C4.7779 5.32683 4.33216 5.51146 4.00351 5.84011C3.67487 6.16875 3.49023 6.6145 3.49023 7.07927V15.2574C3.49023 15.7221 3.67487 16.1679 4.00351 16.4965C4.33216 16.8252 4.7779 17.0098 5.24268 17.0098H13.4208C13.8855 17.0098 14.3313 16.8252 14.6599 16.4965C14.9886 16.1679 15.1732 15.7221 15.1732 15.2574V11.0207M7.50323 13.0137L17.5098 2.99023M17.5098 2.99023H13.4208M17.5098 2.99023V7.07927"
|
||||
strokeWidth="1.5"
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
className={
|
||||
iconColorClassName ||
|
||||
"stroke-medusa-fg-subtle dark:stroke-medusa-fg-subtle-dark"
|
||||
}
|
||||
/>
|
||||
</svg>
|
||||
)
|
||||
}
|
||||
|
||||
export default IconArrowUpRightOnBox
|
||||
@@ -1,28 +0,0 @@
|
||||
import React from "react"
|
||||
import IconProps from "../types"
|
||||
|
||||
const IconBarsThree = ({ iconColorClassName, ...props }: IconProps) => {
|
||||
return (
|
||||
<svg
|
||||
width={props.width || 20}
|
||||
height={props.height || 20}
|
||||
viewBox="0 0 20 20"
|
||||
fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
{...props}
|
||||
>
|
||||
<path
|
||||
d="M3.125 5.00006H16.875M3.125 10H16.875M3.125 15.0001H16.875"
|
||||
className={
|
||||
iconColorClassName ||
|
||||
"stroke-medusa-fg-subtle dark:stroke-medusa-fg-subtle-dark"
|
||||
}
|
||||
strokeWidth="1.5"
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
/>
|
||||
</svg>
|
||||
)
|
||||
}
|
||||
|
||||
export default IconBarsThree
|
||||
@@ -1,32 +0,0 @@
|
||||
import type IconProps from "../types"
|
||||
|
||||
const IconCheckMini = ({
|
||||
iconColorClassName,
|
||||
containerClassName,
|
||||
...props
|
||||
}: IconProps) => {
|
||||
return (
|
||||
<svg
|
||||
width={props.width || 20}
|
||||
height={props.height || 20}
|
||||
viewBox="0 0 20 20"
|
||||
fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
className={containerClassName}
|
||||
{...props}
|
||||
>
|
||||
<path
|
||||
d="M5.83334 10.4167L9.16668 13.75L14.1667 6.25"
|
||||
className={
|
||||
iconColorClassName ||
|
||||
"stroke-medusa-fg-subtle dark:stroke-medusa-fg-subtle-dark"
|
||||
}
|
||||
strokeWidth="1.5"
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
/>
|
||||
</svg>
|
||||
)
|
||||
}
|
||||
|
||||
export default IconCheckMini
|
||||
@@ -1,27 +0,0 @@
|
||||
import type IconProps from "../types"
|
||||
|
||||
const IconChevronDownMini = ({ iconColorClassName, ...props }: IconProps) => {
|
||||
return (
|
||||
<svg
|
||||
width={props.width || 20}
|
||||
height={props.height || 20}
|
||||
viewBox="0 0 20 20"
|
||||
fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
{...props}
|
||||
>
|
||||
<path
|
||||
d="M15 8L10 13L5 8"
|
||||
strokeWidth="1.5"
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
className={
|
||||
iconColorClassName ||
|
||||
"stroke-medusa-fg-subtle dark:stroke-medusa-fg-subtle-dark"
|
||||
}
|
||||
/>
|
||||
</svg>
|
||||
)
|
||||
}
|
||||
|
||||
export default IconChevronDownMini
|
||||
@@ -1,32 +0,0 @@
|
||||
import type IconProps from "../types"
|
||||
|
||||
const IconChevronRightMini = ({
|
||||
iconColorClassName,
|
||||
containerClassName,
|
||||
...props
|
||||
}: IconProps) => {
|
||||
return (
|
||||
<svg
|
||||
width={props.width || 20}
|
||||
height={props.height || 20}
|
||||
viewBox="0 0 20 20"
|
||||
fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
className={containerClassName}
|
||||
{...props}
|
||||
>
|
||||
<path
|
||||
d="M8 6L12 10L8 14"
|
||||
strokeWidth="1.5"
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
className={
|
||||
iconColorClassName ||
|
||||
"stroke-medusa-fg-subtle dark:stroke-medusa-fg-subtle-dark"
|
||||
}
|
||||
/>
|
||||
</svg>
|
||||
)
|
||||
}
|
||||
|
||||
export default IconChevronRightMini
|
||||
@@ -1,32 +0,0 @@
|
||||
import type IconProps from "../types"
|
||||
|
||||
const IconChevronUpDown = ({
|
||||
iconColorClassName,
|
||||
containerClassName,
|
||||
...props
|
||||
}: IconProps) => {
|
||||
return (
|
||||
<svg
|
||||
width={props.width || 20}
|
||||
height={props.height || 20}
|
||||
viewBox="0 0 20 20"
|
||||
fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
className={containerClassName}
|
||||
{...props}
|
||||
>
|
||||
<path
|
||||
d="M6 12.75L9.75 16.5L13.5 12.75M6 6.75L9.75 3L13.5 6.75"
|
||||
className={
|
||||
iconColorClassName ||
|
||||
"stroke-medusa-fg-subtle dark:stroke-medusa-fg-subtle-dark"
|
||||
}
|
||||
strokeWidth="1.5"
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
/>
|
||||
</svg>
|
||||
)
|
||||
}
|
||||
|
||||
export default IconChevronUpDown
|
||||
@@ -1,31 +0,0 @@
|
||||
import IconProps from "../types"
|
||||
|
||||
const IconCopy = ({ iconColorClassName, ...props }: IconProps) => {
|
||||
return (
|
||||
<svg
|
||||
width={props.width || 20}
|
||||
height={props.height || 20}
|
||||
viewBox="0 0 20 20"
|
||||
fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
{...props}
|
||||
>
|
||||
<path
|
||||
d="M2 4.25C2 3.65326 2.23705 3.08097 2.65901 2.65901C3.08097 2.23705 3.65326 2 4.25 2H10.75C11.3467 2 11.919 2.23705 12.341 2.65901C12.7629 3.08097 13 3.65326 13 4.25V5.5H9.25C8.25544 5.5 7.30161 5.89509 6.59835 6.59835C5.89509 7.30161 5.5 8.25544 5.5 9.25V13H4.25C3.65326 13 3.08097 12.7629 2.65901 12.341C2.23705 11.919 2 11.3467 2 10.75V4.25Z"
|
||||
className={
|
||||
iconColorClassName ||
|
||||
"fill-medusa-fg-subtle dark:fill-medusa-fg-subtle-dark"
|
||||
}
|
||||
/>
|
||||
<path
|
||||
d="M9.25 7C8.65326 7 8.08097 7.23705 7.65901 7.65901C7.23705 8.08097 7 8.65326 7 9.25V15.75C7 16.3467 7.23705 16.919 7.65901 17.341C8.08097 17.7629 8.65326 18 9.25 18H15.75C16.3467 18 16.919 17.7629 17.341 17.341C17.7629 16.919 18 16.3467 18 15.75V9.25C18 8.65326 17.7629 8.08097 17.341 7.65901C16.919 7.23705 16.3467 7 15.75 7H9.25Z"
|
||||
className={
|
||||
iconColorClassName ||
|
||||
"fill-medusa-fg-subtle dark:fill-medusa-fg-subtle-dark"
|
||||
}
|
||||
/>
|
||||
</svg>
|
||||
)
|
||||
}
|
||||
|
||||
export default IconCopy
|
||||
@@ -1,28 +0,0 @@
|
||||
import React from "react"
|
||||
import IconProps from "../types"
|
||||
|
||||
const IconCopyOutline = ({ iconColorClassName, ...props }: IconProps) => {
|
||||
return (
|
||||
<svg
|
||||
width={props.width || 20}
|
||||
height={props.height || 20}
|
||||
viewBox="0 0 20 20"
|
||||
fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
{...props}
|
||||
>
|
||||
<path
|
||||
d="M13.75 6.875V5C13.75 4.50272 13.5525 4.02581 13.2008 3.67417C12.8492 3.32254 12.3723 3.125 11.875 3.125H5C4.50272 3.125 4.02581 3.32254 3.67417 3.67417C3.32254 4.02581 3.125 4.50272 3.125 5V11.875C3.125 12.3723 3.32254 12.8492 3.67417 13.2008C4.02581 13.5525 4.50272 13.75 5 13.75H6.875M13.75 6.875H15C15.4973 6.875 15.9742 7.07254 16.3258 7.42417C16.6775 7.77581 16.875 8.25272 16.875 8.75V15C16.875 15.4973 16.6775 15.9742 16.3258 16.3258C15.9742 16.6775 15.4973 16.875 15 16.875H8.75C8.25272 16.875 7.77581 16.6775 7.42417 16.3258C7.07254 15.9742 6.875 15.4973 6.875 15V13.75M13.75 6.875H8.75C8.25272 6.875 7.77581 7.07254 7.42417 7.42417C7.07254 7.77581 6.875 8.25272 6.875 8.75V13.75"
|
||||
className={
|
||||
iconColorClassName ||
|
||||
"stroke-medusa-fg-subtle dark:stroke-medusa-fg-subtle-dark"
|
||||
}
|
||||
strokeWidth="1.5"
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
/>
|
||||
</svg>
|
||||
)
|
||||
}
|
||||
|
||||
export default IconCopyOutline
|
||||
@@ -1,27 +0,0 @@
|
||||
import type IconProps from "../types"
|
||||
|
||||
const IconDarkMode = ({ iconColorClassName, ...props }: IconProps) => {
|
||||
return (
|
||||
<svg
|
||||
width={props.width || 20}
|
||||
height={props.height || 20}
|
||||
viewBox="0 0 20 20"
|
||||
fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
{...props}
|
||||
>
|
||||
<path
|
||||
d="M18.1267 12.5017C17.136 12.9147 16.0732 13.1265 15 13.1251C10.5125 13.1251 6.875 9.48758 6.875 5.00008C6.875 3.89175 7.09667 2.83591 7.49833 1.87341C6.01789 2.49101 4.75331 3.53287 3.86386 4.86779C2.9744 6.20271 2.49986 7.77098 2.5 9.37508C2.5 13.8626 6.1375 17.5001 10.625 17.5001C12.2291 17.5002 13.7974 17.0257 15.1323 16.1362C16.4672 15.2468 17.5091 13.9822 18.1267 12.5017Z"
|
||||
className={
|
||||
iconColorClassName ||
|
||||
"stroke-medusa-fg-subtle dark:stroke-medusa-fg-subtle-dark"
|
||||
}
|
||||
strokeWidth="1.5"
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
/>
|
||||
</svg>
|
||||
)
|
||||
}
|
||||
|
||||
export default IconDarkMode
|
||||
@@ -1,33 +0,0 @@
|
||||
import IconProps from "../types"
|
||||
|
||||
const IconDocumentTextSolid = ({ iconColorClassName, ...props }: IconProps) => {
|
||||
return (
|
||||
<svg
|
||||
width={props.width || 20}
|
||||
height={props.height || 20}
|
||||
viewBox="0 0 20 20"
|
||||
fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
{...props}
|
||||
>
|
||||
<path
|
||||
fillRule="evenodd"
|
||||
clipRule="evenodd"
|
||||
d="M4.91521 1.625C4.08888 1.625 3.41968 2.295 3.41968 3.12054V16.8795C3.41968 17.705 4.08968 18.375 4.91521 18.375H15.0849C15.9104 18.375 16.5804 17.705 16.5804 16.8795V10.5982C16.5804 9.80493 16.2653 9.04414 15.7043 8.48321C15.1434 7.92227 14.3826 7.60714 13.5893 7.60714H12.0938C11.6971 7.60714 11.3167 7.44958 11.0363 7.16911C10.7558 6.88864 10.5982 6.50825 10.5982 6.11161V4.61607C10.5982 3.82279 10.2831 3.062 9.72218 2.50106C9.16125 1.94013 8.40046 1.625 7.60718 1.625H4.91521ZM6.41075 12.3929C6.41075 12.2342 6.47378 12.082 6.58596 11.9699C6.69815 11.8577 6.85031 11.7946 7.00896 11.7946H12.9911C13.1498 11.7946 13.3019 11.8577 13.4141 11.9699C13.5263 12.082 13.5893 12.2342 13.5893 12.3929C13.5893 12.5515 13.5263 12.7037 13.4141 12.8159C13.3019 12.928 13.1498 12.9911 12.9911 12.9911H7.00896C6.85031 12.9911 6.69815 12.928 6.58596 12.8159C6.47378 12.7037 6.41075 12.5515 6.41075 12.3929ZM7.00896 14.1875C6.85031 14.1875 6.69815 14.2505 6.58596 14.3627C6.47378 14.4749 6.41075 14.6271 6.41075 14.7857C6.41075 14.9444 6.47378 15.0965 6.58596 15.2087C6.69815 15.3209 6.85031 15.3839 7.00896 15.3839H10C10.1587 15.3839 10.3108 15.3209 10.423 15.2087C10.5352 15.0965 10.5982 14.9444 10.5982 14.7857C10.5982 14.6271 10.5352 14.4749 10.423 14.3627C10.3108 14.2505 10.1587 14.1875 10 14.1875H7.00896Z"
|
||||
className={
|
||||
iconColorClassName ||
|
||||
"fill-medusa-fg-subtle dark:fill-medusa-fg-subtle-dark"
|
||||
}
|
||||
/>
|
||||
<path
|
||||
d="M10.7745 1.8772C11.4338 2.6373 11.7961 3.61006 11.7947 4.61622V6.11176C11.7947 6.27686 11.9287 6.41086 12.0938 6.41086H13.5893C14.5955 6.40947 15.5683 6.77177 16.3284 7.43102C15.9774 6.09637 15.2783 4.87888 14.3025 3.90306C13.3267 2.92724 12.1092 2.22812 10.7745 1.8772Z"
|
||||
className={
|
||||
iconColorClassName ||
|
||||
"fill-medusa-fg-subtle dark:fill-medusa-fg-subtle-dark"
|
||||
}
|
||||
/>
|
||||
</svg>
|
||||
)
|
||||
}
|
||||
|
||||
export default IconDocumentTextSolid
|
||||
@@ -1,31 +0,0 @@
|
||||
import type IconProps from "../types"
|
||||
|
||||
const IconEllipseMiniSolid = ({
|
||||
iconColorClassName,
|
||||
containerClassName,
|
||||
...props
|
||||
}: IconProps) => {
|
||||
return (
|
||||
<svg
|
||||
width={props.width || 20}
|
||||
height={props.height || 20}
|
||||
viewBox="0 0 20 20"
|
||||
fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
className={containerClassName}
|
||||
{...props}
|
||||
>
|
||||
<circle
|
||||
cx="10"
|
||||
cy="10"
|
||||
r="2"
|
||||
className={
|
||||
iconColorClassName ||
|
||||
"fill-medusa-fg-subtle dark:fill-medusa-fg-subtle-dark"
|
||||
}
|
||||
/>
|
||||
</svg>
|
||||
)
|
||||
}
|
||||
|
||||
export default IconEllipseMiniSolid
|
||||
@@ -1,29 +0,0 @@
|
||||
import IconProps from "../types"
|
||||
|
||||
const IconExclamationCircleSolid = ({
|
||||
iconColorClassName,
|
||||
...props
|
||||
}: IconProps) => {
|
||||
return (
|
||||
<svg
|
||||
width={props.width || 20}
|
||||
height={props.height || 20}
|
||||
viewBox="0 0 20 20"
|
||||
fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
{...props}
|
||||
>
|
||||
<path
|
||||
fillRule="evenodd"
|
||||
clipRule="evenodd"
|
||||
d="M18 10C18 12.1217 17.1571 14.1566 15.6569 15.6569C14.1566 17.1571 12.1217 18 10 18C7.87827 18 5.84344 17.1571 4.34315 15.6569C2.84285 14.1566 2 12.1217 2 10C2 7.87827 2.84285 5.84344 4.34315 4.34315C5.84344 2.84285 7.87827 2 10 2C12.1217 2 14.1566 2.84285 15.6569 4.34315C17.1571 5.84344 18 7.87827 18 10ZM10 5C10.1989 5 10.3897 5.07902 10.5303 5.21967C10.671 5.36032 10.75 5.55109 10.75 5.75V10.25C10.75 10.4489 10.671 10.6397 10.5303 10.7803C10.3897 10.921 10.1989 11 10 11C9.80109 11 9.61032 10.921 9.46967 10.7803C9.32902 10.6397 9.25 10.4489 9.25 10.25V5.75C9.25 5.55109 9.32902 5.36032 9.46967 5.21967C9.61032 5.07902 9.80109 5 10 5ZM10 15C10.2652 15 10.5196 14.8946 10.7071 14.7071C10.8946 14.5196 11 14.2652 11 14C11 13.7348 10.8946 13.4804 10.7071 13.2929C10.5196 13.1054 10.2652 13 10 13C9.73478 13 9.48043 13.1054 9.29289 13.2929C9.10536 13.4804 9 13.7348 9 14C9 14.2652 9.10536 14.5196 9.29289 14.7071C9.48043 14.8946 9.73478 15 10 15Z"
|
||||
className={
|
||||
iconColorClassName ||
|
||||
"fill-medusa-fg-subtle dark:fill-medusa-fg-subtle-dark"
|
||||
}
|
||||
/>
|
||||
</svg>
|
||||
)
|
||||
}
|
||||
|
||||
export default IconExclamationCircleSolid
|
||||
@@ -1,27 +0,0 @@
|
||||
import type IconProps from "../types"
|
||||
|
||||
const IconLightMode = ({ iconColorClassName, ...props }: IconProps) => {
|
||||
return (
|
||||
<svg
|
||||
width={props.width || 20}
|
||||
height={props.height || 20}
|
||||
viewBox="0 0 20 20"
|
||||
fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
{...props}
|
||||
>
|
||||
<path
|
||||
d="M10 2.5V4.375M15.3033 4.69667L13.9775 6.0225M17.5 10H15.625M15.3033 15.3033L13.9775 13.9775M10 15.625V17.5M6.0225 13.9775L4.69667 15.3033M4.375 10H2.5M6.0225 6.0225L4.69667 4.69667M13.125 10C13.125 10.8288 12.7958 11.6237 12.2097 12.2097C11.6237 12.7958 10.8288 13.125 10 13.125C9.1712 13.125 8.37634 12.7958 7.79029 12.2097C7.20424 11.6237 6.875 10.8288 6.875 10C6.875 9.1712 7.20424 8.37634 7.79029 7.79029C8.37634 7.20424 9.1712 6.875 10 6.875C10.8288 6.875 11.6237 7.20424 12.2097 7.79029C12.7958 8.37634 13.125 9.1712 13.125 10Z"
|
||||
className={
|
||||
iconColorClassName ||
|
||||
"stroke-medusa-fg-subtle dark:stroke-medusa-fg-subtle-dark"
|
||||
}
|
||||
strokeWidth="1.5"
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
/>
|
||||
</svg>
|
||||
)
|
||||
}
|
||||
|
||||
export default IconLightMode
|
||||
@@ -1,27 +0,0 @@
|
||||
import type IconProps from "../types"
|
||||
|
||||
const IconMagnifyingGlass = ({ iconColorClassName, ...props }: IconProps) => {
|
||||
return (
|
||||
<svg
|
||||
width={props.width || 20}
|
||||
height={props.height || 20}
|
||||
viewBox="0 0 20 20"
|
||||
fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
{...props}
|
||||
>
|
||||
<path
|
||||
d="M17.4999 17.8713L13.1691 13.5404M13.1691 13.5404C14.3412 12.3683 14.9997 10.7785 14.9997 9.12084C14.9997 7.46317 14.3412 5.8734 13.1691 4.70126C11.9969 3.52911 10.4072 2.87061 8.7495 2.87061C7.09184 2.87061 5.50207 3.52911 4.32992 4.70126C3.15777 5.8734 2.49927 7.46317 2.49927 9.12084C2.49927 10.7785 3.15777 12.3683 4.32992 13.5404C5.50207 14.7126 7.09184 15.3711 8.7495 15.3711C10.4072 15.3711 11.9969 14.7126 13.1691 13.5404V13.5404Z"
|
||||
className={
|
||||
iconColorClassName ||
|
||||
"stroke-medusa-fg-subtle dark:stroke-medusa-fg-subtle-dark"
|
||||
}
|
||||
strokeWidth="1.5"
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
/>
|
||||
</svg>
|
||||
)
|
||||
}
|
||||
|
||||
export default IconMagnifyingGlass
|
||||
@@ -1,25 +0,0 @@
|
||||
import type IconProps from "../types"
|
||||
|
||||
const IconMedusa = ({ iconColorClassName, ...props }: IconProps) => {
|
||||
return (
|
||||
<svg
|
||||
width={props.width || 20}
|
||||
height={props.height || 20}
|
||||
viewBox="0 0 20 20"
|
||||
fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
{...props}
|
||||
>
|
||||
<path
|
||||
d="M16.2447 3.92183L12.1688 1.57686C10.8352 0.807712 9.20112 0.807712 7.86753 1.57686L3.77285 3.92183C2.45804 4.69098 1.63159 6.11673 1.63159 7.63627V12.345C1.63159 13.8833 2.45804 15.2903 3.77285 16.0594L7.84875 18.4231C9.18234 19.1923 10.8165 19.1923 12.15 18.4231L16.2259 16.0594C17.5595 15.2903 18.3672 13.8833 18.3672 12.345V7.63627C18.4048 6.11673 17.5783 4.69098 16.2447 3.92183ZM10.0088 14.1834C7.69849 14.1834 5.82019 12.3075 5.82019 10C5.82019 7.69255 7.69849 5.81657 10.0088 5.81657C12.3191 5.81657 14.2162 7.69255 14.2162 10C14.2162 12.3075 12.3379 14.1834 10.0088 14.1834Z"
|
||||
fill="#030712"
|
||||
className={
|
||||
iconColorClassName ||
|
||||
"fill-medusa-fg-subtle dark:fill-medusa-fg-subtle-dark"
|
||||
}
|
||||
/>
|
||||
</svg>
|
||||
)
|
||||
}
|
||||
|
||||
export default IconMedusa
|
||||
@@ -1,27 +0,0 @@
|
||||
import type IconProps from "../types"
|
||||
|
||||
const IconMinusMini = ({ iconColorClassName, ...props }: IconProps) => {
|
||||
return (
|
||||
<svg
|
||||
width={props.width || 20}
|
||||
height={props.height || 20}
|
||||
viewBox="0 0 20 20"
|
||||
fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
{...props}
|
||||
>
|
||||
<path
|
||||
d="M14.375 10H5.62498"
|
||||
className={
|
||||
iconColorClassName ||
|
||||
"stroke-medusa-fg-subtle dark:stroke-medusa-fg-subtle-dark"
|
||||
}
|
||||
strokeWidth="1.5"
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
/>
|
||||
</svg>
|
||||
)
|
||||
}
|
||||
|
||||
export default IconMinusMini
|
||||
@@ -1,27 +0,0 @@
|
||||
import type IconProps from "../types"
|
||||
|
||||
const IconPlusMini = ({ iconColorClassName, ...props }: IconProps) => {
|
||||
return (
|
||||
<svg
|
||||
width={props.width || 20}
|
||||
height={props.height || 20}
|
||||
viewBox="0 0 20 20"
|
||||
fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
{...props}
|
||||
>
|
||||
<path
|
||||
d="M10.5 5V15M15.5 10H5.5"
|
||||
className={
|
||||
iconColorClassName ||
|
||||
"stroke-medusa-fg-subtle dark:stroke-medusa-fg-subtle-dark"
|
||||
}
|
||||
strokeWidth="1.5"
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
/>
|
||||
</svg>
|
||||
)
|
||||
}
|
||||
|
||||
export default IconPlusMini
|
||||
@@ -1,47 +0,0 @@
|
||||
import type IconProps from "../types"
|
||||
|
||||
const IconReport = ({ iconColorClassName, ...props }: IconProps) => {
|
||||
return (
|
||||
<svg
|
||||
width={props.width || 20}
|
||||
height={props.height || 20}
|
||||
viewBox="0 0 20 20"
|
||||
fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
{...props}
|
||||
>
|
||||
<path
|
||||
d="M10 17.5C14.1421 17.5 17.5 14.1421 17.5 10C17.5 5.85786 14.1421 2.5 10 2.5C5.85786 2.5 2.5 5.85786 2.5 10C2.5 14.1421 5.85786 17.5 10 17.5Z"
|
||||
className={
|
||||
iconColorClassName ||
|
||||
"stroke-medusa-fg-subtle dark:stroke-medusa-fg-subtle-dark"
|
||||
}
|
||||
strokeWidth="1.5"
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
/>
|
||||
<path
|
||||
d="M10 6.6665V9.99984"
|
||||
className={
|
||||
iconColorClassName ||
|
||||
"stroke-medusa-fg-subtle dark:stroke-medusa-fg-subtle-dark"
|
||||
}
|
||||
strokeWidth="1.5"
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
/>
|
||||
<path
|
||||
d="M10 13.3335H10.0088"
|
||||
className={
|
||||
iconColorClassName ||
|
||||
"stroke-medusa-fg-subtle dark:stroke-medusa-fg-subtle-dark"
|
||||
}
|
||||
strokeWidth="1.5"
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
/>
|
||||
</svg>
|
||||
)
|
||||
}
|
||||
|
||||
export default IconReport
|
||||
@@ -1,27 +0,0 @@
|
||||
import type IconProps from "../types"
|
||||
|
||||
const IconSidebar = ({ iconColorClassName, ...props }: IconProps) => {
|
||||
return (
|
||||
<svg
|
||||
width={props.width || 20}
|
||||
height={props.height || 20}
|
||||
viewBox="0 0 20 20"
|
||||
fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
{...props}
|
||||
>
|
||||
<path
|
||||
d="M9 3.125H4.375C3.87772 3.125 3.40081 3.32254 3.04917 3.67417C2.69754 4.02581 2.5 4.50272 2.5 5V6.875V15C2.5 15.4973 2.69754 15.9742 3.04917 16.3258C3.40081 16.6775 3.87772 16.875 4.375 16.875H9M9 3.125H15.625C16.1223 3.125 16.5992 3.32254 16.9508 3.67417C17.3025 4.02581 17.5 4.50272 17.5 5V6.875V15C17.5 15.4973 17.3025 15.9742 16.9508 16.3258C16.5992 16.6775 16.1223 16.875 15.625 16.875H9M9 3.125V16.875M5 6.5H6.5M5 9.5H6.5"
|
||||
className={
|
||||
iconColorClassName ||
|
||||
"stroke-medusa-fg-subtle dark:stroke-medusa-fg-subtle-dark"
|
||||
}
|
||||
strokeWidth="1.5"
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
/>
|
||||
</svg>
|
||||
)
|
||||
}
|
||||
|
||||
export default IconSidebar
|
||||
@@ -1,24 +0,0 @@
|
||||
import type IconProps from "../types"
|
||||
|
||||
const IconSpinner = ({ iconColorClassName, ...props }: IconProps) => {
|
||||
return (
|
||||
<svg
|
||||
width={props.width || 20}
|
||||
height={props.height || 20}
|
||||
viewBox="0 0 20 20"
|
||||
fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
{...props}
|
||||
>
|
||||
<path
|
||||
d="M14.8649 14.8649C15.3023 15.3023 15.3063 16.0188 14.8121 16.3909C14.0399 16.9723 13.1661 17.4109 12.2319 17.6823C10.9379 18.0583 9.56991 18.1013 8.25485 17.8073C6.93979 17.5134 5.72029 16.892 4.7095 16.0009C3.69872 15.1098 2.92941 13.9778 2.47295 12.7099C2.0165 11.4421 1.8877 10.0794 2.09849 8.74852C2.30929 7.4176 2.85286 6.16149 3.67876 5.09674C4.50466 4.032 5.58613 3.19312 6.82282 2.65796C7.71563 2.27161 8.66846 2.05258 9.6341 2.00837C10.252 1.98008 10.7057 2.53472 10.6475 3.15053C10.5893 3.76635 10.0393 4.20701 9.42382 4.26889C8.83606 4.32798 8.25864 4.47736 7.71243 4.71373C6.82201 5.09905 6.04336 5.70304 5.44871 6.46966C4.85406 7.23627 4.46269 8.14067 4.31091 9.09894C4.15914 10.0572 4.25188 11.0383 4.58053 11.9511C4.90917 12.864 5.46308 13.679 6.19084 14.3206C6.91861 14.9623 7.79665 15.4096 8.74349 15.6213C9.69034 15.8329 10.6753 15.802 11.607 15.5313C12.1785 15.3652 12.7186 15.1123 13.2092 14.7832C13.7229 14.4385 14.4275 14.4275 14.8649 14.8649Z"
|
||||
className={
|
||||
iconColorClassName ||
|
||||
"fill-medusa-fg-subtle dark:fill-medusa-fg-subtle-dark"
|
||||
}
|
||||
/>
|
||||
</svg>
|
||||
)
|
||||
}
|
||||
|
||||
export default IconSpinner
|
||||
@@ -1,42 +0,0 @@
|
||||
import IconProps from "../types"
|
||||
|
||||
const IconToolsSolid = ({ iconColorClassName, ...props }: IconProps) => {
|
||||
return (
|
||||
<svg
|
||||
width={props.width || 20}
|
||||
height={props.height || 20}
|
||||
viewBox="0 0 20 20"
|
||||
fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
{...props}
|
||||
>
|
||||
<path
|
||||
fillRule="evenodd"
|
||||
clipRule="evenodd"
|
||||
d="M9.99753 6.06351C9.99737 5.44855 10.1413 4.84211 10.4177 4.29277C10.6941 3.74343 11.0953 3.26648 11.5893 2.90013C12.0832 2.53379 12.6561 2.28824 13.262 2.18315C13.8679 2.07807 14.49 2.11638 15.0784 2.29501C15.1714 2.32318 15.2556 2.37498 15.3226 2.44534C15.3896 2.5157 15.4373 2.60222 15.4609 2.69649C15.4846 2.79075 15.4834 2.88952 15.4575 2.98319C15.4316 3.07686 15.3819 3.16222 15.3132 3.23095L12.8233 5.72003C12.8706 6.07626 13.0303 6.42049 13.3041 6.69422C13.5778 6.96795 13.922 7.12769 14.279 7.17419L16.7673 4.6851C16.8361 4.6164 16.9214 4.56668 17.0151 4.54078C17.1088 4.51489 17.2075 4.5137 17.3018 4.53734C17.3961 4.56099 17.4826 4.60864 17.5529 4.67568C17.6233 4.74271 17.6751 4.82683 17.7033 4.91984C17.8902 5.53544 17.9234 6.18746 17.8 6.81886C17.6766 7.45026 17.4003 8.0418 16.9954 8.54174C16.5905 9.04167 16.0692 9.43477 15.4772 9.68663C14.8852 9.93849 14.2405 10.0415 13.5995 9.9865C12.8361 9.92201 12.1971 10.0615 11.8679 10.462L6.50576 16.9753C6.2862 17.2406 6.01366 17.4571 5.70559 17.611C5.39752 17.7649 5.06071 17.8528 4.71672 17.869C4.37273 17.8852 4.02915 17.8294 3.70797 17.7052C3.38679 17.5809 3.0951 17.391 2.85157 17.1475C2.60803 16.904 2.41803 16.6124 2.29372 16.2912C2.16941 15.9701 2.11353 15.6265 2.12967 15.2825C2.14581 14.9385 2.2336 14.6017 2.38743 14.2936C2.54126 13.9855 2.75773 13.7129 3.02299 13.4933L9.53556 8.13037C9.93528 7.8004 10.0755 7.16219 10.011 6.39874C10.0018 6.28723 9.99734 6.17539 9.99753 6.06351ZM4.08567 15.3442C4.08567 15.195 4.14493 15.0519 4.25041 14.9464C4.35589 14.8409 4.49895 14.7817 4.64813 14.7817H4.65413C4.8033 14.7817 4.94637 14.8409 5.05185 14.9464C5.15733 15.0519 5.21659 15.195 5.21659 15.3442V15.3501C5.21659 15.4993 5.15733 15.6424 5.05185 15.7479C4.94637 15.8534 4.8033 15.9126 4.65413 15.9126H4.64813C4.49895 15.9126 4.35589 15.8534 4.25041 15.7479C4.14493 15.6424 4.08567 15.4993 4.08567 15.3501V15.3442Z"
|
||||
className={
|
||||
iconColorClassName ||
|
||||
"fill-medusa-fg-subtle dark:fill-medusa-fg-subtle-dark"
|
||||
}
|
||||
/>
|
||||
<path
|
||||
d="M8.55462 7.48082L6.90398 5.83093V4.65651C6.90397 4.5594 6.87883 4.46395 6.83099 4.37945C6.78315 4.29495 6.71425 4.22427 6.631 4.17429L3.81868 2.4869C3.71112 2.42242 3.58509 2.39574 3.46063 2.41109C3.33616 2.42645 3.2204 2.48296 3.13173 2.57164L2.56926 3.13411C2.48058 3.22278 2.42407 3.33854 2.40871 3.46301C2.39336 3.58747 2.42004 3.7135 2.48452 3.82106L4.17191 6.63338C4.22189 6.71663 4.29257 6.78553 4.37707 6.83337C4.46157 6.88121 4.55702 6.90635 4.65413 6.90636H5.82705L7.37345 8.45276L8.55462 7.48007V7.48082Z"
|
||||
className={
|
||||
iconColorClassName ||
|
||||
"fill-medusa-fg-subtle dark:fill-medusa-fg-subtle-dark"
|
||||
}
|
||||
/>
|
||||
<path
|
||||
fillRule="evenodd"
|
||||
clipRule="evenodd"
|
||||
d="M10.4146 13.9971L13.5516 17.1334C13.7866 17.3685 14.0657 17.5549 14.3727 17.6821C14.6798 17.8093 15.009 17.8748 15.3414 17.8748C15.6737 17.8748 16.0029 17.8093 16.31 17.6821C16.617 17.5549 16.8961 17.3685 17.1311 17.1334C17.3661 16.8984 17.5526 16.6194 17.6798 16.3123C17.807 16.0052 17.8724 15.6761 17.8724 15.3437C17.8724 15.0113 17.807 14.6821 17.6798 14.3751C17.5526 14.068 17.3661 13.7889 17.1311 13.5539L14.6518 11.0753C14.2717 11.1292 13.8868 11.14 13.5043 11.1076C13.2089 11.0821 12.9929 11.1031 12.8541 11.1391C12.8102 11.1484 12.768 11.1643 12.7289 11.1863L10.4146 13.9971ZM12.9749 12.9772C13.0803 12.8719 13.2233 12.8127 13.3724 12.8127C13.5214 12.8127 13.6644 12.8719 13.7698 12.9772L15.176 14.3841C15.2312 14.4356 15.2756 14.4977 15.3063 14.5667C15.3371 14.6357 15.3536 14.7102 15.3549 14.7857C15.3563 14.8612 15.3424 14.9362 15.3141 15.0063C15.2858 15.0763 15.2437 15.1399 15.1903 15.1933C15.1369 15.2467 15.0732 15.2888 15.0032 15.3171C14.9332 15.3454 14.8581 15.3593 14.7826 15.358C14.7071 15.3566 14.6326 15.3401 14.5636 15.3094C14.4946 15.2786 14.4325 15.2343 14.381 15.179L12.9749 13.7729C12.8696 13.6674 12.8104 13.5245 12.8104 13.3754C12.8104 13.2264 12.8696 13.0834 12.9749 12.9779V12.9772Z"
|
||||
className={
|
||||
iconColorClassName ||
|
||||
"fill-medusa-fg-subtle dark:fill-medusa-fg-subtle-dark"
|
||||
}
|
||||
/>
|
||||
</svg>
|
||||
)
|
||||
}
|
||||
|
||||
export default IconToolsSolid
|
||||
@@ -1,36 +0,0 @@
|
||||
import IconProps from "../types"
|
||||
|
||||
const IconTreeNode = ({ iconColorClassName, ...props }: IconProps) => {
|
||||
return (
|
||||
<svg
|
||||
width={props.width || 16}
|
||||
height={props.height || 32}
|
||||
viewBox="0 0 16 32"
|
||||
fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
{...props}
|
||||
>
|
||||
<rect
|
||||
width="1"
|
||||
height="32"
|
||||
rx="0.5"
|
||||
className={
|
||||
iconColorClassName ||
|
||||
"fill-medusa-fg-subtle dark:fill-medusa-fg-subtle-dark"
|
||||
}
|
||||
/>
|
||||
<rect
|
||||
y="15.5"
|
||||
width="16"
|
||||
height="1"
|
||||
rx="0.5"
|
||||
className={
|
||||
iconColorClassName ||
|
||||
"fill-medusa-fg-subtle dark:fill-medusa-fg-subtle-dark"
|
||||
}
|
||||
/>
|
||||
</svg>
|
||||
)
|
||||
}
|
||||
|
||||
export default IconTreeNode
|
||||
@@ -1,27 +0,0 @@
|
||||
import IconProps from "../types"
|
||||
|
||||
const IconXMark = ({ iconColorClassName, ...props }: IconProps) => {
|
||||
return (
|
||||
<svg
|
||||
width={props.width || 20}
|
||||
height={props.height || 20}
|
||||
viewBox="0 0 20 20"
|
||||
fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
{...props}
|
||||
>
|
||||
<path
|
||||
d="M5 15L15 5M5 5L15 15"
|
||||
className={
|
||||
iconColorClassName ||
|
||||
"stroke-medusa-fg-subtle dark:stroke-medusa-fg-subtle-dark"
|
||||
}
|
||||
strokeWidth="1.5"
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
/>
|
||||
</svg>
|
||||
)
|
||||
}
|
||||
|
||||
export default IconXMark
|
||||
@@ -1,27 +0,0 @@
|
||||
import IconProps from "../types"
|
||||
|
||||
const IconXMarkMini = ({ iconColorClassName, ...props }: IconProps) => {
|
||||
return (
|
||||
<svg
|
||||
width={props.width || 20}
|
||||
height={props.height || 20}
|
||||
viewBox="0 0 20 20"
|
||||
fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
{...props}
|
||||
>
|
||||
<path
|
||||
d="M6 14L14 6M6 6L14 14"
|
||||
className={
|
||||
iconColorClassName ||
|
||||
"stroke-medusa-fg-subtle dark:stroke-medusa-fg-subtle-dark"
|
||||
}
|
||||
strokeWidth="1.5"
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
/>
|
||||
</svg>
|
||||
)
|
||||
}
|
||||
|
||||
export default IconXMarkMini
|
||||
@@ -1,6 +0,0 @@
|
||||
type IconProps = {
|
||||
iconColorClassName?: string
|
||||
containerClassName?: string
|
||||
} & React.AllHTMLAttributes<SVGElement>
|
||||
|
||||
export default IconProps
|
||||
@@ -1,45 +0,0 @@
|
||||
import { CopyButtonProps } from "@/components/CopyButton"
|
||||
import clsx from "clsx"
|
||||
import dynamic from "next/dynamic"
|
||||
import SpinnerLoading from "../Loading/Spinner"
|
||||
|
||||
const CopyButton = dynamic<CopyButtonProps>(
|
||||
async () => import("../CopyButton"),
|
||||
{
|
||||
loading: () => <SpinnerLoading />,
|
||||
}
|
||||
) as React.FC<CopyButtonProps>
|
||||
|
||||
export type InlineCodeProps = React.ComponentProps<"code">
|
||||
|
||||
const InlineCode = (props: InlineCodeProps) => {
|
||||
const isInline = typeof props.children === "string"
|
||||
return (
|
||||
<>
|
||||
{!isInline && <code {...props} />}
|
||||
{isInline && (
|
||||
<CopyButton
|
||||
text={props.children as string}
|
||||
buttonClassName={clsx(
|
||||
"bg-transparent border-0 p-0 inline text-medusa-fg-subtle dark:text-medusa-fg-subtle-dark",
|
||||
"active:[&>code]:bg-medusa-bg-subtle-pressed dark:active:[&>code]:bg-medusa-bg-subtle-pressed-dark",
|
||||
"focus:[&>code]:bg-medusa-bg-subtle-pressed dark:focus:[&>code]:bg-medusa-bg-subtle-pressed-dark",
|
||||
"hover:[&>code]:bg-medusa-bg-subtle-hover dark:hover:[&>code]:bg-medusa-bg-base-hover-dark"
|
||||
)}
|
||||
>
|
||||
<code
|
||||
{...props}
|
||||
className={clsx(
|
||||
"border-medusa-tag-neutral-border dark:border-medusa-tag-neutral-border-dark border",
|
||||
"text-medusa-tag-neutral-text dark:text-medusa-tag-neutral-text-dark",
|
||||
"bg-medusa-tag-neutral-bg dark:bg-medusa-tag-neutral-bg-dark font-monospace text-code-label rounded-sm py-0 px-[6px]",
|
||||
props.className
|
||||
)}
|
||||
/>
|
||||
</CopyButton>
|
||||
)}
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
export default InlineCode
|
||||
@@ -1,11 +0,0 @@
|
||||
import Loading from ".."
|
||||
|
||||
const ContentLoading = () => {
|
||||
return (
|
||||
<div className="w-api-ref-content">
|
||||
<Loading />
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export default ContentLoading
|
||||
@@ -1,20 +0,0 @@
|
||||
import IconSpinner from "@/components/Icons/Spinner"
|
||||
import type IconProps from "@/components/Icons/types"
|
||||
import clsx from "clsx"
|
||||
|
||||
type SpinnerLoadingProps = {
|
||||
iconProps?: IconProps
|
||||
}
|
||||
|
||||
const SpinnerLoading = ({ iconProps }: SpinnerLoadingProps) => {
|
||||
return (
|
||||
<span role="status">
|
||||
<IconSpinner
|
||||
{...iconProps}
|
||||
className={clsx("animate-spin", iconProps?.className)}
|
||||
/>
|
||||
</span>
|
||||
)
|
||||
}
|
||||
|
||||
export default SpinnerLoading
|
||||
@@ -1,28 +0,0 @@
|
||||
import clsx from "clsx"
|
||||
import capitalize from "@/utils/capitalize"
|
||||
|
||||
export type MethodLabelProps = {
|
||||
method: string
|
||||
className?: string
|
||||
}
|
||||
|
||||
const MethodLabel = ({ method, className }: MethodLabelProps) => {
|
||||
return (
|
||||
<span
|
||||
className={clsx(
|
||||
"text-compact-x-small-plus rounded-sm border py-0 px-[6px]",
|
||||
method === "get" &&
|
||||
"bg-medusa-tag-green-bg dark:bg-medusa-tag-green-bg-dark text-medusa-tag-green-text dark:text-medusa-tag-green-text-dark border-medusa-tag-green-border dark:border-medusa-tag-green-border-dark",
|
||||
method === "post" &&
|
||||
"bg-medusa-tag-blue-bg dark:bg-medusa-tag-blue-bg-dark text-medusa-tag-blue-text dark:text-medusa-tag-blue-text-dark border-medusa-tag-blue-border dark:border-medusa-tag-blue-border-dark",
|
||||
method === "delete" &&
|
||||
"bg-medusa-tag-red-bg dark:bg-medusa-tag-red-bg-dark text-medusa-tag-red-text dark:text-medusa-tag-red-text-dark border-medusa-tag-red-border dark:border-medusa-tag-red-border-dark",
|
||||
className
|
||||
)}
|
||||
>
|
||||
{method === "delete" ? "Del" : capitalize(method)}
|
||||
</span>
|
||||
)
|
||||
}
|
||||
|
||||
export default MethodLabel
|
||||
@@ -1,28 +0,0 @@
|
||||
import clsx from "clsx"
|
||||
import Button, { ButtonProps } from "../../Button"
|
||||
|
||||
type ModalFooterProps = {
|
||||
actions?: ButtonProps[]
|
||||
children?: React.ReactNode
|
||||
className?: string
|
||||
}
|
||||
|
||||
const ModalFooter = ({ actions, children, className }: ModalFooterProps) => {
|
||||
return (
|
||||
<div
|
||||
className={clsx(
|
||||
"py-1.5 pl-0 pr-2",
|
||||
"border-medusa-border-base dark:border-medusa-border-base-dark border-0 border-t border-solid",
|
||||
"flex justify-end gap-0.5",
|
||||
className
|
||||
)}
|
||||
>
|
||||
{actions?.map((action, index) => (
|
||||
<Button {...action} key={index} />
|
||||
))}
|
||||
{children}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export default ModalFooter
|
||||
@@ -1,38 +0,0 @@
|
||||
import clsx from "clsx"
|
||||
import { useModal } from "../../../providers/modal"
|
||||
import IconXMark from "../../Icons/XMark"
|
||||
import Button from "../../Button"
|
||||
|
||||
type ModalHeaderProps = {
|
||||
title?: string
|
||||
}
|
||||
|
||||
const ModalHeader = ({ title }: ModalHeaderProps) => {
|
||||
const { closeModal } = useModal()
|
||||
|
||||
return (
|
||||
<div
|
||||
className={clsx(
|
||||
"border-medusa-border-base dark:border-medusa-border-base-dark border-0 border-b border-solid py-1.5 px-2",
|
||||
"flex items-center justify-between"
|
||||
)}
|
||||
>
|
||||
<span
|
||||
className={clsx(
|
||||
"text-medusa-fg-base dark:text-medusa-fg-base-dark text-h2"
|
||||
)}
|
||||
>
|
||||
{title}
|
||||
</span>
|
||||
<Button
|
||||
variant="clear"
|
||||
className="cursor-pointer"
|
||||
onClick={() => closeModal()}
|
||||
>
|
||||
<IconXMark />
|
||||
</Button>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export default ModalHeader
|
||||
@@ -1,117 +0,0 @@
|
||||
import clsx from "clsx"
|
||||
import React, { forwardRef, useCallback, useEffect, useRef } from "react"
|
||||
import { ButtonProps } from "../Button"
|
||||
import { useModal } from "../../providers/modal"
|
||||
import ModalHeader from "./Header"
|
||||
import ModalFooter from "./Footer"
|
||||
import useKeyboardShortcut from "../../hooks/use-keyboard-shortcut"
|
||||
|
||||
export type ModalProps = {
|
||||
className?: string
|
||||
title?: string
|
||||
actions?: ButtonProps[]
|
||||
modalContainerClassName?: string
|
||||
contentClassName?: string
|
||||
onClose?: React.ReactEventHandler<HTMLDialogElement>
|
||||
open?: boolean
|
||||
footerContent?: React.ReactNode
|
||||
} & Omit<React.ComponentProps<"dialog">, "ref">
|
||||
|
||||
const Modal = forwardRef<HTMLDialogElement, ModalProps>(function Modal(
|
||||
{
|
||||
className,
|
||||
title,
|
||||
actions,
|
||||
children,
|
||||
contentClassName,
|
||||
modalContainerClassName,
|
||||
onClose,
|
||||
open = true,
|
||||
footerContent,
|
||||
...props
|
||||
},
|
||||
passedRef
|
||||
) {
|
||||
const { closeModal } = useModal()
|
||||
const ref = useRef<HTMLDialogElement | null>(null)
|
||||
|
||||
const setRefs = useCallback(
|
||||
(node: HTMLDialogElement) => {
|
||||
// Ref's from useRef needs to have the node assigned to `current`
|
||||
ref.current = node
|
||||
if (typeof passedRef === "function") {
|
||||
passedRef(node)
|
||||
} else if (passedRef && "current" in passedRef) {
|
||||
passedRef.current = node
|
||||
}
|
||||
},
|
||||
[passedRef]
|
||||
)
|
||||
|
||||
useKeyboardShortcut({
|
||||
metakey: false,
|
||||
checkEditing: false,
|
||||
shortcutKeys: ["escape"],
|
||||
action: () => {
|
||||
if (open) {
|
||||
ref.current?.close()
|
||||
}
|
||||
},
|
||||
})
|
||||
|
||||
const handleClick = (e: React.MouseEvent<HTMLDialogElement, MouseEvent>) => {
|
||||
// close modal when the user clicks outside the content
|
||||
if (e.target === ref.current) {
|
||||
closeModal()
|
||||
onClose?.(e)
|
||||
}
|
||||
}
|
||||
|
||||
const handleClose = (e: React.SyntheticEvent<HTMLDialogElement, Event>) => {
|
||||
onClose?.(e)
|
||||
closeModal()
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
if (open) {
|
||||
document.body.setAttribute("data-modal", "opened")
|
||||
} else {
|
||||
document.body.removeAttribute("data-modal")
|
||||
}
|
||||
}, [open])
|
||||
|
||||
return (
|
||||
<dialog
|
||||
{...props}
|
||||
className={clsx(
|
||||
"fixed top-0 left-0 flex h-screen w-screen items-center justify-center",
|
||||
"bg-medusa-bg-overlay dark:bg-medusa-bg-overlay-dark z-[500]",
|
||||
"hidden open:flex",
|
||||
className
|
||||
)}
|
||||
onClick={handleClick}
|
||||
ref={setRefs}
|
||||
onClose={handleClose}
|
||||
open={open}
|
||||
>
|
||||
<div
|
||||
className={clsx(
|
||||
"bg-medusa-bg-base dark:bg-medusa-bg-base-dark rounded-sm",
|
||||
"border-medusa-border-base dark:border-medusa-border-base-dark border border-solid",
|
||||
"shadow-modal dark:shadow-modal-dark",
|
||||
"w-[90%] md:h-auto md:w-[75%] lg:w-[560px]",
|
||||
modalContainerClassName
|
||||
)}
|
||||
>
|
||||
{title && <ModalHeader title={title} />}
|
||||
<div className={clsx("overflow-auto py-1.5 px-2", contentClassName)}>
|
||||
{children}
|
||||
</div>
|
||||
{actions && actions?.length > 0 && <ModalFooter actions={actions} />}
|
||||
{footerContent && <ModalFooter>{footerContent}</ModalFooter>}
|
||||
</div>
|
||||
</dialog>
|
||||
)
|
||||
})
|
||||
|
||||
export default Modal
|
||||
@@ -1,35 +0,0 @@
|
||||
"use client"
|
||||
|
||||
import { useColorMode } from "@/providers/color-mode"
|
||||
import NavbarIconButton, { NavbarIconButtonProps } from "../IconButton"
|
||||
import type IconProps from "@/components/Icons/types"
|
||||
import dynamic from "next/dynamic"
|
||||
|
||||
const IconLightMode = dynamic<IconProps>(
|
||||
async () => import("../../Icons/LightMode")
|
||||
) as React.FC<IconProps>
|
||||
|
||||
const IconDarkMode = dynamic<IconProps>(
|
||||
async () => import("../../Icons/DarkMode")
|
||||
) as React.FC<IconProps>
|
||||
|
||||
type NavbarColorModeToggleProps = {
|
||||
buttonProps?: NavbarIconButtonProps
|
||||
}
|
||||
|
||||
const NavbarColorModeToggle = ({ buttonProps }: NavbarColorModeToggleProps) => {
|
||||
const { colorMode, toggleColorMode } = useColorMode()
|
||||
|
||||
return (
|
||||
<NavbarIconButton {...buttonProps} onClick={() => toggleColorMode()}>
|
||||
{colorMode === "light" && (
|
||||
<IconLightMode iconColorClassName="stroke-medusa-fg-muted dark:stroke-medusa-fg-muted-dark" />
|
||||
)}
|
||||
{colorMode === "dark" && (
|
||||
<IconDarkMode iconColorClassName="stroke-medusa-fg-muted dark:stroke-medusa-fg-muted-dark" />
|
||||
)}
|
||||
</NavbarIconButton>
|
||||
)
|
||||
}
|
||||
|
||||
export default NavbarColorModeToggle
|
||||
@@ -1,24 +0,0 @@
|
||||
import clsx from "clsx"
|
||||
|
||||
export type NavbarIconButtonProps = React.HTMLAttributes<HTMLButtonElement>
|
||||
|
||||
const NavbarIconButton = ({
|
||||
children,
|
||||
className,
|
||||
...props
|
||||
}: NavbarIconButtonProps) => {
|
||||
return (
|
||||
<button
|
||||
className={clsx(
|
||||
"btn-secondary btn-secondary-icon",
|
||||
"[&>svg]:h-[22px] [&>svg]:w-[22px]",
|
||||
className
|
||||
)}
|
||||
{...props}
|
||||
>
|
||||
{children}
|
||||
</button>
|
||||
)
|
||||
}
|
||||
|
||||
export default NavbarIconButton
|
||||
@@ -1,42 +0,0 @@
|
||||
"use client"
|
||||
|
||||
import clsx from "clsx"
|
||||
import Link from "next/link"
|
||||
import type { LinkProps } from "next/link"
|
||||
import { useNavbar } from "@/providers/navbar"
|
||||
import { Area } from "@/types/openapi"
|
||||
|
||||
type NavbarLinkProps = {
|
||||
href: string
|
||||
label: string
|
||||
className?: string
|
||||
activeValue?: Area
|
||||
} & LinkProps
|
||||
|
||||
const NavbarLink = ({
|
||||
href,
|
||||
label,
|
||||
className,
|
||||
activeValue,
|
||||
}: NavbarLinkProps) => {
|
||||
const { activeItem } = useNavbar()
|
||||
|
||||
return (
|
||||
<Link
|
||||
href={href}
|
||||
className={clsx(
|
||||
activeItem === activeValue &&
|
||||
"text-medusa-fg-base dark:text-medusa-fg-base-dark",
|
||||
activeItem !== activeValue &&
|
||||
"text-medusa-fg-subtle dark:text-medusa-fg-subtle-dark",
|
||||
"text-compact-small-plus inline-block",
|
||||
"hover:text-medusa-fg-base dark:hover:text-medusa-fg-base-dark",
|
||||
className
|
||||
)}
|
||||
>
|
||||
{label}
|
||||
</Link>
|
||||
)
|
||||
}
|
||||
|
||||
export default NavbarLink
|
||||
@@ -1,27 +0,0 @@
|
||||
"use client"
|
||||
|
||||
import { useColorMode } from "@/providers/color-mode"
|
||||
import Image from "next/image"
|
||||
import Link from "next/link"
|
||||
|
||||
const NavbarLogo = () => {
|
||||
const { colorMode } = useColorMode()
|
||||
|
||||
return (
|
||||
<Link href={`/`} className="flex-1">
|
||||
<Image
|
||||
src={
|
||||
colorMode === "light"
|
||||
? "/images/logo-icon.png"
|
||||
: "/images/logo-icon-dark.png"
|
||||
}
|
||||
alt="Medusa Logo"
|
||||
height={20}
|
||||
width={20}
|
||||
className="align-middle"
|
||||
/>
|
||||
</Link>
|
||||
)
|
||||
}
|
||||
|
||||
export default NavbarLogo
|
||||
@@ -1,38 +0,0 @@
|
||||
"use client"
|
||||
|
||||
import NavbarIconButton, { NavbarIconButtonProps } from "../IconButton"
|
||||
import { useSidebar } from "@/providers/sidebar"
|
||||
import IconSidebar from "../../Icons/Sidebar"
|
||||
import clsx from "clsx"
|
||||
import IconXMark from "../../Icons/XMark"
|
||||
import { usePageLoading } from "../../../providers/page-loading"
|
||||
|
||||
type NavbarMenuButtonProps = {
|
||||
buttonProps?: NavbarIconButtonProps
|
||||
}
|
||||
|
||||
const NavbarMenuButton = ({ buttonProps }: NavbarMenuButtonProps) => {
|
||||
const { setMobileSidebarOpen, mobileSidebarOpen } = useSidebar()
|
||||
const { isLoading } = usePageLoading()
|
||||
|
||||
return (
|
||||
<NavbarIconButton
|
||||
{...buttonProps}
|
||||
className={clsx("mr-1 lg:!hidden", buttonProps?.className)}
|
||||
onClick={() => {
|
||||
if (!isLoading) {
|
||||
setMobileSidebarOpen((prevValue) => !prevValue)
|
||||
}
|
||||
}}
|
||||
>
|
||||
{!mobileSidebarOpen && (
|
||||
<IconSidebar iconColorClassName="stroke-medusa-fg-muted dark:stroke-medusa-fg-muted-dark" />
|
||||
)}
|
||||
{mobileSidebarOpen && (
|
||||
<IconXMark iconColorClassName="stroke-medusa-fg-muted dark:stroke-medusa-fg-muted-dark" />
|
||||
)}
|
||||
</NavbarIconButton>
|
||||
)
|
||||
}
|
||||
|
||||
export default NavbarMenuButton
|
||||
@@ -1,27 +0,0 @@
|
||||
"use client"
|
||||
|
||||
import { useColorMode } from "@/providers/color-mode"
|
||||
import Image from "next/image"
|
||||
import Link from "next/link"
|
||||
|
||||
const NavbarMobileLogo = () => {
|
||||
const { colorMode } = useColorMode()
|
||||
|
||||
return (
|
||||
<Link href={`/`} className="flex-1 lg:hidden">
|
||||
<Image
|
||||
src={
|
||||
colorMode === "light"
|
||||
? "/images/logo-mobile.png"
|
||||
: "/images/logo-mobile-dark.png"
|
||||
}
|
||||
alt="Medusa Logo"
|
||||
height={20}
|
||||
width={82}
|
||||
className="mx-auto align-middle"
|
||||
/>
|
||||
</Link>
|
||||
)
|
||||
}
|
||||
|
||||
export default NavbarMobileLogo
|
||||
@@ -1,38 +0,0 @@
|
||||
"use client"
|
||||
|
||||
import NavbarMenuButton from "../MenuButton"
|
||||
import NavbarMobileLogo from "../MobileLogo"
|
||||
import NavbarColorModeToggle from "../ColorModeToggle"
|
||||
import SearchModalOpener from "../../Search/ModalOpener"
|
||||
import { useMobile } from "../../../providers/mobile"
|
||||
|
||||
const MobileMenu = () => {
|
||||
const { isMobile } = useMobile()
|
||||
|
||||
return (
|
||||
<div className="flex w-full items-center justify-between lg:hidden">
|
||||
{isMobile && (
|
||||
<>
|
||||
<NavbarMenuButton
|
||||
buttonProps={{
|
||||
className:
|
||||
"!border-none !bg-transparent !bg-no-image !shadow-none",
|
||||
}}
|
||||
/>
|
||||
<NavbarMobileLogo />
|
||||
<div className="flex">
|
||||
<SearchModalOpener />
|
||||
<NavbarColorModeToggle
|
||||
buttonProps={{
|
||||
className:
|
||||
"!border-none !bg-transparent !bg-no-image !shadow-none ml-1",
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export default MobileMenu
|
||||
@@ -1,88 +0,0 @@
|
||||
"use client"
|
||||
|
||||
import IconSidebar from "@/components/Icons/Sidebar"
|
||||
import Tooltip from "@/components/Tooltip"
|
||||
import NavbarIconButton from "../IconButton"
|
||||
import { useSidebar } from "../../../providers/sidebar"
|
||||
import clsx from "clsx"
|
||||
import { useEffect, useState } from "react"
|
||||
|
||||
const NavbarSidebarButton = () => {
|
||||
const { desktopSidebarOpen, setDesktopSidebarOpen } = useSidebar()
|
||||
const [isApple, setIsApple] = useState(false)
|
||||
|
||||
const toggleSidebar = () => {
|
||||
setDesktopSidebarOpen((prevValue) => !prevValue)
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
setIsApple(navigator.userAgent.toLowerCase().indexOf("mac") !== 0)
|
||||
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)
|
||||
}
|
||||
}, [])
|
||||
|
||||
const getPlatformKey = () =>
|
||||
`
|
||||
<kbd class="${clsx(
|
||||
"bg-medusa-tag-neutral-bg dark:bg-medusa-tag-neutral-bg-dark",
|
||||
"border border-solid rounded-sm border-medusa-tag-neutral-border dark:border-medusa-tag-neutral-border-dark",
|
||||
"text-medusa-tag-neutral-text dark:text-medusa-tag-neutral-text font-base text-compact-x-small-plus",
|
||||
"inline-flex !p-0 justify-center items-center shadow-none ml-0.5",
|
||||
isApple && "w-[22px] h-[22px]",
|
||||
!isApple && "w-1.5 h-1.5"
|
||||
)}">${isApple ? "⌘" : "Ctrl"}</kbd>
|
||||
`
|
||||
|
||||
return (
|
||||
<Tooltip
|
||||
html={
|
||||
desktopSidebarOpen
|
||||
? `<span class="text-compact-x-small-plus">Close sidebar ${getPlatformKey()}
|
||||
<kbd class="${clsx(
|
||||
"bg-medusa-tag-neutral-bg dark:bg-medusa-tag-neutral-bg-dark",
|
||||
"border border-solid rounded-sm border-medusa-tag-neutral-border dark:border-medusa-tag-neutral-border-dark",
|
||||
"text-medusa-tag-neutral-text dark:text-medusa-tag-neutral-text font-base text-compact-x-small-plus",
|
||||
"inline-flex w-[22px] h-[22px] !p-0 justify-center items-center shadow-none"
|
||||
)}">I</kbd></span>`
|
||||
: `<span class="text-compact-x-small-plus">Lock sidebar open ${getPlatformKey()}
|
||||
<kbd class="${clsx(
|
||||
"bg-medusa-tag-neutral-bg dark:bg-medusa-tag-neutral-bg-dark",
|
||||
"border border-solid rounded-sm border-medusa-tag-neutral-border dark:border-medusa-tag-neutral-border-dark",
|
||||
"text-medusa-tag-neutral-text dark:text-medusa-tag-neutral-text font-base text-compact-x-small-plus",
|
||||
"inline-flex w-[22px] h-[22px] !p-0 justify-center items-center shadow-none"
|
||||
)}">I</kbd></span>`
|
||||
}
|
||||
>
|
||||
<NavbarIconButton onClick={toggleSidebar}>
|
||||
<IconSidebar iconColorClassName="stroke-medusa-fg-muted dark:stroke-medusa-fg-muted-dark" />
|
||||
</NavbarIconButton>
|
||||
</Tooltip>
|
||||
)
|
||||
}
|
||||
|
||||
export default NavbarSidebarButton
|
||||
@@ -1,57 +0,0 @@
|
||||
import clsx from "clsx"
|
||||
import NavbarLink from "./Link"
|
||||
import NavbarColorModeToggle from "./ColorModeToggle"
|
||||
import NavbarLogo from "./Logo"
|
||||
import getLinkWithBasePath from "../../utils/get-link-with-base-path"
|
||||
import FeedbackModal from "./FeedbackModal"
|
||||
import MobileMenu from "./MobileMenu"
|
||||
import SearchModalOpener from "../Search/ModalOpener"
|
||||
|
||||
const Navbar = () => {
|
||||
return (
|
||||
<nav
|
||||
className={clsx(
|
||||
"h-navbar sticky top-0 w-full justify-between",
|
||||
"bg-docs-bg dark:bg-docs-bg-dark border-medusa-border-base dark:border-medusa-border-base-dark z-[400] border-b"
|
||||
)}
|
||||
>
|
||||
<div
|
||||
className={clsx(
|
||||
"h-navbar max-w-xxl py-0.75 sticky top-0 mx-auto flex w-full justify-between px-1 lg:px-3"
|
||||
)}
|
||||
>
|
||||
<div className="hidden w-full items-center gap-0.5 lg:flex lg:w-auto lg:gap-1.5">
|
||||
<NavbarLogo />
|
||||
<div className="hidden items-center gap-1.5 lg:flex">
|
||||
<NavbarLink href="https://docs.medusajs.com/" label="Docs" />
|
||||
<NavbarLink
|
||||
href="https://docs.medusajs.com/user-guide"
|
||||
label="User Guide"
|
||||
/>
|
||||
<NavbarLink
|
||||
href={getLinkWithBasePath("/store")}
|
||||
label="Store API"
|
||||
activeValue="store"
|
||||
/>
|
||||
<NavbarLink
|
||||
href={getLinkWithBasePath("/admin")}
|
||||
label="Admin API"
|
||||
activeValue="admin"
|
||||
/>
|
||||
<NavbarLink href="https://docs.medusajs.com/ui" label="UI" />
|
||||
</div>
|
||||
</div>
|
||||
<div className="hidden min-w-0 flex-1 items-center justify-end gap-0.5 lg:flex">
|
||||
<div>
|
||||
<SearchModalOpener />
|
||||
</div>
|
||||
<NavbarColorModeToggle />
|
||||
<FeedbackModal />
|
||||
</div>
|
||||
<MobileMenu />
|
||||
</div>
|
||||
</nav>
|
||||
)
|
||||
}
|
||||
|
||||
export default Navbar
|
||||
@@ -1,21 +0,0 @@
|
||||
import clsx from "clsx"
|
||||
|
||||
type SearchHitGroupNameProps = {
|
||||
name: string
|
||||
}
|
||||
|
||||
const SearchHitGroupName = ({ name }: SearchHitGroupNameProps) => {
|
||||
return (
|
||||
<span
|
||||
className={clsx(
|
||||
"pb-0.25 flex px-0.5 pt-1",
|
||||
"text-medusa-fg-muted dark:text-medusa-fg-muted-dark",
|
||||
"text-compact-x-small-plus"
|
||||
)}
|
||||
>
|
||||
{name}
|
||||
</span>
|
||||
)
|
||||
}
|
||||
|
||||
export default SearchHitGroupName
|
||||
@@ -1,381 +0,0 @@
|
||||
"use client"
|
||||
|
||||
import React, { useCallback, useEffect, useMemo, useRef, useState } from "react"
|
||||
import algoliasearch, { SearchClient } from "algoliasearch/lite"
|
||||
import { InstantSearch, SearchBox } from "react-instantsearch"
|
||||
import Modal from "../../Modal"
|
||||
import clsx from "clsx"
|
||||
import IconMagnifyingGlass from "../../Icons/MagnifyingGlass"
|
||||
import IconXMark from "../../Icons/XMark"
|
||||
import SearchEmptyQueryBoundary from "../EmptyQueryBoundary"
|
||||
import SearchSuggestions from "../Suggestions"
|
||||
import { useSearch } from "../../../providers/search"
|
||||
import checkArraySameElms from "../../../utils/array-same-elms"
|
||||
import SearchHitsWrapper from "../Hits"
|
||||
import Button from "../../Button"
|
||||
import Kbd from "../../MDXComponents/Kbd"
|
||||
import { OptionType } from "../../../hooks/use-select"
|
||||
import SelectBadge from "../../Select/Badge"
|
||||
import useKeyboardShortcut from "../../../hooks/use-keyboard-shortcut"
|
||||
import { findNextSibling, findPrevSibling } from "../../../utils/dom-utils"
|
||||
|
||||
const algoliaClient = algoliasearch(
|
||||
process.env.NEXT_PUBLIC_ALGOLIA_APP_ID || "temp",
|
||||
process.env.NEXT_PUBLIC_ALGOLIA_API_KEY || "temp"
|
||||
)
|
||||
|
||||
const searchClient: SearchClient = {
|
||||
...algoliaClient,
|
||||
async search(requests) {
|
||||
if (requests.every(({ params }) => !params?.query)) {
|
||||
return Promise.resolve({
|
||||
results: requests.map(() => ({
|
||||
hits: [],
|
||||
nbHits: 0,
|
||||
nbPages: 0,
|
||||
page: 0,
|
||||
processingTimeMS: 0,
|
||||
hitsPerPage: 0,
|
||||
exhaustiveNbHits: false,
|
||||
query: "",
|
||||
params: "",
|
||||
})),
|
||||
})
|
||||
}
|
||||
|
||||
return algoliaClient.search(requests)
|
||||
},
|
||||
}
|
||||
|
||||
const SearchModal = () => {
|
||||
const modalRef = useRef<HTMLDialogElement | null>(null)
|
||||
const options: OptionType[] = useMemo(() => {
|
||||
return [
|
||||
{
|
||||
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",
|
||||
},
|
||||
]
|
||||
}, [])
|
||||
const { isOpen, setIsOpen, defaultFilters } = useSearch()
|
||||
const [filters, setFilters] = useState<string[]>(defaultFilters)
|
||||
const formattedFilters: string = useMemo(() => {
|
||||
let formatted = ""
|
||||
filters.forEach((filter) => {
|
||||
const split = filter.split("_")
|
||||
split.forEach((f) => {
|
||||
if (formatted.length) {
|
||||
formatted += " OR "
|
||||
}
|
||||
formatted += `_tags:${f}`
|
||||
})
|
||||
})
|
||||
return formatted
|
||||
}, [filters])
|
||||
const searchBoxRef = useRef<HTMLFormElement>(null)
|
||||
|
||||
const focusSearchInput = () =>
|
||||
searchBoxRef.current?.querySelector("input")?.focus()
|
||||
|
||||
useEffect(() => {
|
||||
if (!checkArraySameElms(defaultFilters, filters)) {
|
||||
setFilters(defaultFilters)
|
||||
}
|
||||
}, [defaultFilters])
|
||||
|
||||
useEffect(() => {
|
||||
if (isOpen && searchBoxRef.current) {
|
||||
focusSearchInput()
|
||||
} else if (!isOpen) {
|
||||
const focusedItem = modalRef.current?.querySelector(
|
||||
":focus"
|
||||
) as HTMLElement
|
||||
if (
|
||||
focusedItem &&
|
||||
focusedItem === searchBoxRef.current?.querySelector("input")
|
||||
) {
|
||||
// remove focus
|
||||
focusedItem.blur()
|
||||
}
|
||||
}
|
||||
}, [isOpen])
|
||||
|
||||
const handleKeyAction = (e: KeyboardEvent) => {
|
||||
if (!isOpen) {
|
||||
return
|
||||
}
|
||||
e.preventDefault()
|
||||
const focusedItem = modalRef.current?.querySelector(":focus") as HTMLElement
|
||||
if (!focusedItem) {
|
||||
// focus the first data-hit
|
||||
const nextItem = modalRef.current?.querySelector(
|
||||
"[data-hit]"
|
||||
) as HTMLElement
|
||||
nextItem?.focus()
|
||||
return
|
||||
}
|
||||
|
||||
const isHit = focusedItem.hasAttribute("data-hit")
|
||||
const isInput = focusedItem.tagName.toLowerCase() === "input"
|
||||
|
||||
if (!isHit && !isInput) {
|
||||
// ignore if focused items aren't input/data-hit
|
||||
return
|
||||
}
|
||||
|
||||
const lowerPressedKey = e.key.toLowerCase()
|
||||
|
||||
if (lowerPressedKey === "enter") {
|
||||
if (isHit) {
|
||||
// trigger click event of the focused element
|
||||
focusedItem.click()
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
if (lowerPressedKey === "arrowup") {
|
||||
// only hit items has action on arrow up
|
||||
if (isHit) {
|
||||
// find if there's a data-hit item before this one
|
||||
const beforeItem = findPrevSibling(focusedItem, "[data-hit]")
|
||||
if (!beforeItem) {
|
||||
// focus the input
|
||||
focusSearchInput()
|
||||
} else {
|
||||
// focus the previous item
|
||||
beforeItem.focus()
|
||||
}
|
||||
}
|
||||
} else if (lowerPressedKey === "arrowdown") {
|
||||
// check if item is input or hit
|
||||
if (isInput) {
|
||||
// go to the first data-hit item
|
||||
const nextItem = modalRef.current?.querySelector(
|
||||
"[data-hit]"
|
||||
) as HTMLElement
|
||||
nextItem?.focus()
|
||||
} else {
|
||||
// handle go down for hit items
|
||||
// find if there's a data-hit item after this one
|
||||
const afterItem = findNextSibling(focusedItem, "[data-hit]")
|
||||
if (afterItem) {
|
||||
// focus the next item
|
||||
afterItem.focus()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const shortcutKeys = useMemo(() => ["ArrowUp", "ArrowDown", "Enter"], [])
|
||||
|
||||
useKeyboardShortcut({
|
||||
metakey: false,
|
||||
shortcutKeys,
|
||||
action: handleKeyAction,
|
||||
checkEditing: false,
|
||||
preventDefault: false,
|
||||
})
|
||||
|
||||
const handleKeyDown = useCallback(
|
||||
(e: KeyboardEvent) => {
|
||||
if (!isOpen) {
|
||||
return
|
||||
}
|
||||
// check if shortcut keys were pressed
|
||||
const lowerPressedKey = e.key.toLowerCase()
|
||||
const pressedShortcut = [...shortcutKeys, "Escape"].some(
|
||||
(s) => s.toLowerCase() === lowerPressedKey
|
||||
)
|
||||
if (pressedShortcut) {
|
||||
return
|
||||
}
|
||||
|
||||
const focusedItem = modalRef.current?.querySelector(
|
||||
":focus"
|
||||
) as HTMLElement
|
||||
const searchInput = searchBoxRef.current?.querySelector(
|
||||
"input"
|
||||
) as HTMLInputElement
|
||||
if (searchInput && focusedItem !== searchInput) {
|
||||
searchInput.focus()
|
||||
}
|
||||
},
|
||||
[shortcutKeys, isOpen]
|
||||
)
|
||||
|
||||
useEffect(() => {
|
||||
window.addEventListener("keydown", handleKeyDown)
|
||||
|
||||
return () => {
|
||||
window.removeEventListener("keydown", handleKeyDown)
|
||||
}
|
||||
}, [handleKeyDown])
|
||||
|
||||
return (
|
||||
<Modal
|
||||
contentClassName={clsx(
|
||||
"!p-0 overflow-hidden relative h-full",
|
||||
"rounded-none md:rounded-lg flex flex-col justify-between"
|
||||
)}
|
||||
modalContainerClassName="w-screen h-screen !rounded-none md:!rounded-lg"
|
||||
open={isOpen}
|
||||
onClose={() => setIsOpen(false)}
|
||||
ref={modalRef}
|
||||
>
|
||||
<InstantSearch
|
||||
indexName={process.env.NEXT_PUBLIC_API_ALGOLIA_INDEX_NAME}
|
||||
searchClient={searchClient}
|
||||
>
|
||||
<div
|
||||
className={clsx("bg-medusa-bg-base dark:bg-medusa-bg-base-dark flex")}
|
||||
>
|
||||
<SearchBox
|
||||
classNames={{
|
||||
root: clsx(
|
||||
"h-[56px] w-full md:rounded-t-xl relative border-b border-medusa-border-base dark:border-medusa-border-base-dark",
|
||||
"bg-transparent"
|
||||
),
|
||||
form: clsx("h-full md:rounded-t-xl bg-transparent"),
|
||||
input: clsx(
|
||||
"w-full h-full pl-3 text-medusa-fg-base dark:text-medusa-fg-base-dark",
|
||||
"placeholder:text-medusa-fg-muted dark:placeholder:text-medusa-fg-muted-dark",
|
||||
"md:rounded-t-xl text-compact-medium bg-transparent",
|
||||
"appearance-none search-cancel:hidden active:outline-none focus:outline-none"
|
||||
),
|
||||
submit: clsx("absolute top-[18px] left-1"),
|
||||
reset: clsx(
|
||||
"absolute top-0.75 right-1 hover:bg-medusa-bg-base-hover dark:hover:bg-medusa-bg-base-hover-dark",
|
||||
"p-[5px] md:rounded"
|
||||
),
|
||||
loadingIndicator: clsx("absolute top-[18px] right-1"),
|
||||
}}
|
||||
submitIconComponent={() => (
|
||||
<IconMagnifyingGlass iconColorClassName="stroke-medusa-fg-muted dark:stroke-medusa-fg-muted-dark" />
|
||||
)}
|
||||
resetIconComponent={() => (
|
||||
<IconXMark
|
||||
iconColorClassName="stroke-medusa-fg-subtle dark:stroke-medusa-fg-subtle-dark"
|
||||
className="hidden md:block"
|
||||
/>
|
||||
)}
|
||||
placeholder="Find something..."
|
||||
autoFocus
|
||||
formRef={searchBoxRef}
|
||||
/>
|
||||
<Button
|
||||
variant="clear"
|
||||
className={clsx(
|
||||
"bg-medusa-bg-base dark:bg-medusa-bg-base-dark block md:hidden",
|
||||
"border-medusa-border-base dark:border-medusa-border-base-dark border-b",
|
||||
"pr-1"
|
||||
)}
|
||||
onClick={() => setIsOpen(false)}
|
||||
>
|
||||
<IconXMark iconColorClassName="stroke-medusa-fg-muted dark:stroke-medusa-fg-muted-dark" />
|
||||
</Button>
|
||||
</div>
|
||||
<div className="mx-0.5 h-[calc(100%-120px)] md:h-[332px] md:flex-initial lg:max-h-[332px] lg:min-h-[332px]">
|
||||
<SearchEmptyQueryBoundary fallback={<SearchSuggestions />}>
|
||||
<SearchHitsWrapper
|
||||
configureProps={{
|
||||
filters: formattedFilters,
|
||||
attributesToSnippet: [
|
||||
"content",
|
||||
"hierarchy.lvl1",
|
||||
"hierarchy.lvl2",
|
||||
],
|
||||
attributesToHighlight: [
|
||||
"content",
|
||||
"hierarchy.lvl1",
|
||||
"hierarchy.lvl2",
|
||||
],
|
||||
}}
|
||||
/>
|
||||
</SearchEmptyQueryBoundary>
|
||||
</div>
|
||||
</InstantSearch>
|
||||
<div
|
||||
className={clsx(
|
||||
"py-0.75 flex items-center justify-between px-1",
|
||||
"border-medusa-border-base dark:border-medusa-border-base-dark border-t",
|
||||
"bg-medusa-bg-base dark:bg-medusa-bg-base-dark"
|
||||
)}
|
||||
>
|
||||
<SelectBadge
|
||||
multiple
|
||||
options={options}
|
||||
value={filters}
|
||||
setSelected={(value) =>
|
||||
setFilters(Array.isArray(value) ? [...value] : [value])
|
||||
}
|
||||
addSelected={(value) => setFilters((prev) => [...prev, value])}
|
||||
removeSelected={(value) =>
|
||||
setFilters((prev) => prev.filter((v) => v !== value))
|
||||
}
|
||||
showClearButton={false}
|
||||
placeholder="Filters"
|
||||
handleAddAll={(isAllSelected: boolean) => {
|
||||
if (isAllSelected) {
|
||||
setFilters(defaultFilters)
|
||||
} else {
|
||||
setFilters(options.map((option) => option.value))
|
||||
}
|
||||
}}
|
||||
/>
|
||||
<div className="hidden items-center gap-1 md:flex">
|
||||
<div className="flex items-center gap-0.5">
|
||||
<span
|
||||
className={clsx(
|
||||
"text-medusa-fg-subtle dark:text-medusa-fg-subtle-dark",
|
||||
"text-compact-x-small"
|
||||
)}
|
||||
>
|
||||
Navigation
|
||||
</span>
|
||||
<span className="gap-0.25 flex">
|
||||
<Kbd>↑</Kbd>
|
||||
<Kbd>↓</Kbd>
|
||||
</span>
|
||||
</div>
|
||||
<div className="flex items-center gap-0.5">
|
||||
<span
|
||||
className={clsx(
|
||||
"text-medusa-fg-subtle dark:text-medusa-fg-subtle-dark",
|
||||
"text-compact-x-small"
|
||||
)}
|
||||
>
|
||||
Open Result
|
||||
</span>
|
||||
<Kbd>↵</Kbd>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</Modal>
|
||||
)
|
||||
}
|
||||
|
||||
export default SearchModal
|
||||
@@ -1,14 +0,0 @@
|
||||
import IconExclamationCircleSolid from "../../Icons/ExclamationCircleSolid"
|
||||
|
||||
const SearchNoResult = () => {
|
||||
return (
|
||||
<div className="flex h-full w-full flex-col items-center justify-center gap-1">
|
||||
<IconExclamationCircleSolid iconColorClassName="fill-medusa-fg-muted dark:fill-medusa-fg-muted-dark" />
|
||||
<span className="text-compact-small text-medusa-fg-muted dark:text-medusa-fg-muted-dark">
|
||||
No results found. Try changing selected filters.
|
||||
</span>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export default SearchNoResult
|
||||
@@ -1,49 +0,0 @@
|
||||
import clsx from "clsx"
|
||||
import { useInstantSearch } from "react-instantsearch"
|
||||
import SearchHitGroupName from "../Hits/GroupName"
|
||||
|
||||
const SearchSuggestions = () => {
|
||||
const { setIndexUiState } = useInstantSearch()
|
||||
const suggestions = [
|
||||
"Authentication",
|
||||
"Expanding fields",
|
||||
"Selecting fields",
|
||||
"Pagination",
|
||||
"Query parameter types",
|
||||
]
|
||||
return (
|
||||
<div className="h-full overflow-auto">
|
||||
<SearchHitGroupName name={"Search suggestions"} />
|
||||
{suggestions.map((suggestion, index) => (
|
||||
<div
|
||||
className={clsx(
|
||||
"flex items-center justify-between",
|
||||
"cursor-pointer rounded-sm p-0.5",
|
||||
"hover:bg-medusa-bg-base-hover dark:hover:bg-medusa-bg-base-hover-dark",
|
||||
"focus:bg-medusa-bg-base-hover dark:focus:bg-medusa-bg-base-hover-dark",
|
||||
"last:mb-1 focus:outline-none"
|
||||
)}
|
||||
onClick={() =>
|
||||
setIndexUiState({
|
||||
query: suggestion,
|
||||
})
|
||||
}
|
||||
key={index}
|
||||
tabIndex={index}
|
||||
data-hit
|
||||
>
|
||||
<span
|
||||
className={clsx(
|
||||
"text-medusa-fg-base dark:text-medusa-fg-base-dark",
|
||||
"text-compact-small"
|
||||
)}
|
||||
>
|
||||
{suggestion}
|
||||
</span>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export default SearchSuggestions
|
||||
@@ -1,135 +0,0 @@
|
||||
import { useCallback, useRef, useState } from "react"
|
||||
import useSelect from "../../../hooks/use-select"
|
||||
import clsx from "clsx"
|
||||
import SelectDropdown from "../Dropdown"
|
||||
import { SelectProps } from "../types"
|
||||
|
||||
const SelectBadge = ({
|
||||
value,
|
||||
options,
|
||||
setSelected,
|
||||
addSelected,
|
||||
removeSelected,
|
||||
multiple,
|
||||
className,
|
||||
addAll = multiple,
|
||||
handleAddAll,
|
||||
...props
|
||||
}: SelectProps) => {
|
||||
const [open, setOpen] = useState(false)
|
||||
const ref = useRef<HTMLDivElement>(null)
|
||||
const dropdownRef = useRef<HTMLDivElement>(null)
|
||||
const { isValueSelected, isAllSelected, handleChange, handleSelectAll } =
|
||||
useSelect({
|
||||
value,
|
||||
options,
|
||||
multiple,
|
||||
setSelected,
|
||||
removeSelected,
|
||||
addSelected,
|
||||
handleAddAll,
|
||||
})
|
||||
|
||||
const getSelectedText = useCallback(() => {
|
||||
let str = ""
|
||||
const selectedOptions = options.filter((option) =>
|
||||
value.includes(option.value)
|
||||
)
|
||||
|
||||
if (isAllSelected) {
|
||||
str = "All Areas"
|
||||
} else {
|
||||
if (
|
||||
(!Array.isArray(value) && !value) ||
|
||||
(Array.isArray(value) && !value.length)
|
||||
) {
|
||||
str = "None selected"
|
||||
} else {
|
||||
str = selectedOptions[0].label
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
<span
|
||||
className={clsx(
|
||||
"text-medusa-fg-base dark:text-medusa-fg-base-dark",
|
||||
"text-compact-x-small-plus",
|
||||
"inline-block w-[60px] max-w-[60px] overflow-hidden text-ellipsis"
|
||||
)}
|
||||
>
|
||||
{str}
|
||||
</span>
|
||||
{!isAllSelected && selectedOptions.length > 1 && (
|
||||
<span
|
||||
className={clsx(
|
||||
"text-medusa-fg-subtle dark:text-medusa-fg-subtle-dark",
|
||||
"text-compact-x-small"
|
||||
)}
|
||||
>
|
||||
{" "}
|
||||
+ {selectedOptions.length}
|
||||
</span>
|
||||
)}
|
||||
</>
|
||||
)
|
||||
}, [isAllSelected, options, value])
|
||||
|
||||
return (
|
||||
<div className={clsx("relative", className)}>
|
||||
<div
|
||||
className={clsx(
|
||||
"border-medusa-border-base dark:border-medusa-border-base-dark rounded-sm border",
|
||||
"hover:bg-medusa-bg-subtle-hover dark:hover:bg-medusa-bg-subtle-hover-dark",
|
||||
"py-0.25 h-fit cursor-pointer px-0.5",
|
||||
"flex items-center gap-[6px] whitespace-nowrap",
|
||||
"text-medusa-fg-subtle dark:text-medusa-fg-subtle-dark",
|
||||
!open && "bg-medusa-bg-subtle dark:bg-medusa-bg-subtle-dark",
|
||||
open &&
|
||||
"bg-medusa-bg-subtle-hover dark:bg-medusa-bg-subtle-hover-dark",
|
||||
className
|
||||
)}
|
||||
ref={ref}
|
||||
onClick={(e) => {
|
||||
if (!dropdownRef.current?.contains(e.target as Element)) {
|
||||
setOpen((prev) => !prev)
|
||||
}
|
||||
}}
|
||||
>
|
||||
<span
|
||||
className={clsx(
|
||||
"text-medusa-fg-subtle dark:text-medusa-fg-subtle-dark",
|
||||
"text-compact-x-small"
|
||||
)}
|
||||
>
|
||||
Show results from:{" "}
|
||||
</span>
|
||||
{getSelectedText()}
|
||||
</div>
|
||||
<input
|
||||
type="hidden"
|
||||
name={props.name}
|
||||
value={Array.isArray(value) ? value.join(",") : value}
|
||||
/>
|
||||
<SelectDropdown
|
||||
options={options}
|
||||
open={open}
|
||||
setOpen={setOpen}
|
||||
addAll={addAll}
|
||||
multiple={multiple}
|
||||
isAllSelected={isAllSelected}
|
||||
isValueSelected={isValueSelected}
|
||||
handleSelectAll={handleSelectAll}
|
||||
handleChange={handleChange}
|
||||
parentRef={ref}
|
||||
ref={dropdownRef}
|
||||
className={clsx(
|
||||
"!top-[unset] !bottom-full",
|
||||
open && "!-translate-y-0.5"
|
||||
)}
|
||||
/>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export default SelectBadge
|
||||
@@ -1,151 +0,0 @@
|
||||
import clsx from "clsx"
|
||||
import IconCheckMini from "../../Icons/CheckMini"
|
||||
import IconEllipseMiniSolid from "../../Icons/EllipseMiniSolid"
|
||||
import { OptionType } from "../../../hooks/use-select"
|
||||
import { forwardRef, useCallback, useEffect, useRef } from "react"
|
||||
|
||||
type SelectDropdownProps = {
|
||||
options: OptionType[]
|
||||
open: boolean
|
||||
setOpen: React.Dispatch<React.SetStateAction<boolean>>
|
||||
addAll?: boolean
|
||||
multiple?: boolean
|
||||
isAllSelected: boolean
|
||||
isValueSelected: (val: string) => boolean
|
||||
handleSelectAll: () => void
|
||||
handleChange?: (selectedValue: string, wasSelected: boolean) => void
|
||||
parentRef?: React.RefObject<HTMLDivElement>
|
||||
className?: string
|
||||
}
|
||||
|
||||
const SelectDropdown = forwardRef<HTMLDivElement, SelectDropdownProps>(
|
||||
function SelectDropdown(
|
||||
{
|
||||
open,
|
||||
setOpen,
|
||||
options,
|
||||
addAll,
|
||||
multiple = false,
|
||||
isAllSelected,
|
||||
isValueSelected,
|
||||
handleSelectAll,
|
||||
handleChange: handleSelectChange,
|
||||
parentRef,
|
||||
className,
|
||||
},
|
||||
passedRef
|
||||
) {
|
||||
const ref = useRef<HTMLDivElement | null>(null)
|
||||
const setRefs = useCallback(
|
||||
(node: HTMLDivElement) => {
|
||||
// Ref's from useRef needs to have the node assigned to `current`
|
||||
ref.current = node
|
||||
if (typeof passedRef === "function") {
|
||||
passedRef(node)
|
||||
} else if (passedRef && "current" in passedRef) {
|
||||
passedRef.current = node
|
||||
}
|
||||
},
|
||||
[passedRef]
|
||||
)
|
||||
|
||||
const handleChange = (clickedValue: string, wasSelected: boolean) => {
|
||||
handleSelectChange?.(clickedValue, wasSelected)
|
||||
if (!multiple) {
|
||||
setOpen(false)
|
||||
}
|
||||
}
|
||||
|
||||
const handleOutsideClick = useCallback(
|
||||
(e: MouseEvent) => {
|
||||
if (
|
||||
open &&
|
||||
!ref.current?.contains(e.target as Element) &&
|
||||
!parentRef?.current?.contains(e.target as Element)
|
||||
) {
|
||||
setOpen(false)
|
||||
}
|
||||
},
|
||||
[open, parentRef, setOpen]
|
||||
)
|
||||
|
||||
useEffect(() => {
|
||||
document.body.addEventListener("click", handleOutsideClick)
|
||||
|
||||
return () => {
|
||||
document.body.removeEventListener("click", handleOutsideClick)
|
||||
}
|
||||
}, [handleOutsideClick])
|
||||
|
||||
const getSelectOption = (option: OptionType, index: number) => {
|
||||
const isSelected = option.isAllOption
|
||||
? isAllSelected
|
||||
: isValueSelected(option.value)
|
||||
|
||||
return (
|
||||
<li
|
||||
key={index}
|
||||
className={clsx(
|
||||
"pr-0.75 relative rounded-sm py-0.5 pl-2.5",
|
||||
"hover:bg-medusa-bg-base-hover dark:hover:bg-medusa-bg-base-hover-dark",
|
||||
"[&>svg]:left-0.75 cursor-pointer [&>svg]:absolute [&>svg]:top-0.5",
|
||||
!isSelected && "text-compact-small",
|
||||
isSelected && "text-compact-small-plus"
|
||||
)}
|
||||
onClick={() => {
|
||||
if (option.isAllOption) {
|
||||
handleSelectAll()
|
||||
} else {
|
||||
handleChange(option.value, isSelected)
|
||||
}
|
||||
}}
|
||||
>
|
||||
{isSelected && (
|
||||
<>
|
||||
{multiple && (
|
||||
<IconCheckMini className="stroke-medusa-fg-base dark:stroke-medusa-fg-base-dark" />
|
||||
)}
|
||||
{!multiple && (
|
||||
<IconEllipseMiniSolid className="fill-medusa-fg-base dark:fill-medusa-fg-base-dark" />
|
||||
)}
|
||||
</>
|
||||
)}
|
||||
{option.label}
|
||||
</li>
|
||||
)
|
||||
}
|
||||
|
||||
return (
|
||||
<div
|
||||
className={clsx(
|
||||
"absolute top-full left-0 w-full",
|
||||
"z-10 h-0 translate-y-0 overflow-hidden transition-transform",
|
||||
open && "h-auto translate-y-0.5 !overflow-visible",
|
||||
className
|
||||
)}
|
||||
ref={setRefs}
|
||||
>
|
||||
<ul
|
||||
className={clsx(
|
||||
"p-0.25 mb-0 w-full overflow-auto rounded",
|
||||
"bg-medusa-bg-base dark:bg-medusa-bg-base-dark text-medusa-fg-base dark:text-medusa-fg-base-dark",
|
||||
"shadow-flyout dark:shadow-flyout-dark list-none"
|
||||
)}
|
||||
>
|
||||
{addAll &&
|
||||
getSelectOption(
|
||||
{
|
||||
value: "all",
|
||||
label: "All Areas",
|
||||
isAllOption: true,
|
||||
},
|
||||
-1
|
||||
)}
|
||||
{options.map(getSelectOption)}
|
||||
</ul>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
)
|
||||
|
||||
export default SelectDropdown
|
||||
@@ -1,106 +0,0 @@
|
||||
import type { SidebarItemType } from "@/providers/sidebar"
|
||||
import { useSidebar } from "@/providers/sidebar"
|
||||
import clsx from "clsx"
|
||||
import dynamic from "next/dynamic"
|
||||
import Link from "next/link"
|
||||
import { useEffect, useMemo, useRef, useState } from "react"
|
||||
import type { MethodLabelProps } from "../../MethodLabel"
|
||||
import checkSidebarItemVisibility from "@/utils/check-sidebar-item-visibility"
|
||||
import Loading from "../../Loading"
|
||||
|
||||
const MethodLabel = dynamic<MethodLabelProps>(
|
||||
async () => import("../../MethodLabel")
|
||||
) as React.FC<MethodLabelProps>
|
||||
|
||||
export type SidebarItemProps = {
|
||||
item: SidebarItemType
|
||||
nested?: boolean
|
||||
} & React.AllHTMLAttributes<HTMLLIElement>
|
||||
|
||||
const SidebarItem = ({ item, nested = false, className }: SidebarItemProps) => {
|
||||
const [showLoading, setShowLoading] = useState(false)
|
||||
const { isItemActive, setMobileSidebarOpen: setSidebarOpen } = useSidebar()
|
||||
const active = useMemo(() => {
|
||||
return isItemActive(item, nested)
|
||||
}, [isItemActive, item, nested])
|
||||
const collapsed = !isItemActive(item, true)
|
||||
const ref = useRef<HTMLLIElement>(null)
|
||||
|
||||
useEffect(() => {
|
||||
if (active && ref.current && window.innerWidth >= 1025) {
|
||||
if (
|
||||
!checkSidebarItemVisibility(ref.current, {
|
||||
topMargin: 57,
|
||||
})
|
||||
) {
|
||||
// scroll to element
|
||||
ref.current.scrollIntoView({
|
||||
block: "center",
|
||||
})
|
||||
}
|
||||
}
|
||||
if (active) {
|
||||
setShowLoading(true)
|
||||
}
|
||||
}, [active])
|
||||
|
||||
return (
|
||||
<li
|
||||
className={clsx(
|
||||
item.hasChildren && !collapsed && "my-1.5",
|
||||
!item.hasChildren && !nested && active && "mt-1.5",
|
||||
((item.hasChildren && !collapsed) ||
|
||||
(!item.hasChildren && !nested && active)) &&
|
||||
"-translate-y-1 transition-transform",
|
||||
className
|
||||
)}
|
||||
ref={ref}
|
||||
>
|
||||
<Link
|
||||
href={item.isPathHref ? item.path : `#${item.path}`}
|
||||
className={clsx(
|
||||
"flex items-center justify-between gap-0.5 rounded-sm border px-0.5 py-[6px] hover:no-underline",
|
||||
!item.hasChildren &&
|
||||
"text-compact-small-plus text-medusa-fg-subtle dark:text-medusa-fg-subtle-dark",
|
||||
item.hasChildren &&
|
||||
"text-compact-x-small-plus text-medusa-fg-muted dark:text-medusa-fg-muted-dark uppercase",
|
||||
active &&
|
||||
"!text-medusa-fg-base dark:!text-medusa-fg-base-dark bg-medusa-bg-base-pressed dark:bg-medusa-bg-base-pressed-dark",
|
||||
active &&
|
||||
"border-medusa-border-base dark:border-medusa-border-base-dark",
|
||||
!active &&
|
||||
"hover:bg-medusa-bg-base-hover dark:hover:bg-medusa-bg-base-hover-dark border-transparent"
|
||||
)}
|
||||
scroll={true}
|
||||
onClick={() => {
|
||||
if (window.innerWidth < 1025) {
|
||||
setSidebarOpen(false)
|
||||
}
|
||||
}}
|
||||
replace
|
||||
shallow
|
||||
>
|
||||
<span>{item.title}</span>
|
||||
{item.method && <MethodLabel method={item.method} className="h-fit" />}
|
||||
</Link>
|
||||
{item.hasChildren && (
|
||||
<ul
|
||||
className={clsx("ease-ease overflow-hidden", collapsed && "m-0 h-0")}
|
||||
>
|
||||
{showLoading && !item.loaded && (
|
||||
<Loading
|
||||
count={3}
|
||||
className="!mb-0 !px-0.5"
|
||||
barClassName="h-[20px]"
|
||||
/>
|
||||
)}
|
||||
{item.children?.map((childItem, index) => (
|
||||
<SidebarItem item={childItem} key={index} nested={true} />
|
||||
))}
|
||||
</ul>
|
||||
)}
|
||||
</li>
|
||||
)
|
||||
}
|
||||
|
||||
export default SidebarItem
|
||||
@@ -1,289 +0,0 @@
|
||||
@tailwind base;
|
||||
@tailwind components;
|
||||
@tailwind utilities;
|
||||
|
||||
@layer base {
|
||||
h1 {
|
||||
@apply text-h1 mb-1;
|
||||
}
|
||||
|
||||
h2 {
|
||||
@apply text-h2 mb-1;
|
||||
}
|
||||
|
||||
h3 {
|
||||
@apply text-h3 mb-0.5;
|
||||
}
|
||||
|
||||
h4 {
|
||||
@apply text-h4 mb-0.5;
|
||||
}
|
||||
|
||||
h1, h2, h3, h4 {
|
||||
@apply text-medusa-fg-base dark:text-medusa-fg-base-dark;
|
||||
}
|
||||
|
||||
hr {
|
||||
@apply h-[1px] w-full border-0 bg-medusa-border-base dark:bg-medusa-border-base-dark my-2;
|
||||
}
|
||||
|
||||
p, ul, ol {
|
||||
@apply mb-1.5;
|
||||
}
|
||||
|
||||
html {
|
||||
-webkit-font-smoothing: antialiased;
|
||||
}
|
||||
|
||||
body {
|
||||
@apply overflow-x-hidden;
|
||||
}
|
||||
|
||||
*::selection {
|
||||
@apply bg-medusa-bg-highlight dark:bg-medusa-bg-highlight-dark;
|
||||
}
|
||||
|
||||
pre *::selection {
|
||||
@apply !bg-medusa-code-text-highlight;
|
||||
}
|
||||
|
||||
body[data-modal="opened"] {
|
||||
@apply !overflow-hidden;
|
||||
}
|
||||
|
||||
mark {
|
||||
@apply bg-medusa-bg-highlight dark:bg-medusa-bg-highlight-dark;
|
||||
@apply text-medusa-fg-interactive dark:text-medusa-fg-interactive-dark;
|
||||
}
|
||||
}
|
||||
|
||||
@layer utilities {
|
||||
@-webkit-keyframes fadeIn {
|
||||
from {
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
to {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
@keyframes fadeIn {
|
||||
from {
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
to {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
|
||||
@-webkit-keyframes fadeOut {
|
||||
from {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
to {
|
||||
opacity: 0;
|
||||
}
|
||||
}
|
||||
@keyframes fadeOut {
|
||||
from {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
to {
|
||||
opacity: 0;
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes bounceIn {
|
||||
from,
|
||||
20%,
|
||||
40%,
|
||||
60%,
|
||||
80%,
|
||||
to {
|
||||
animation-timing-function: cubic-bezier(0.215, 0.61, 0.355, 1);
|
||||
}
|
||||
|
||||
0% {
|
||||
opacity: 0;
|
||||
transform: scale3d(0.3, 0.3, 0.3);
|
||||
}
|
||||
|
||||
20% {
|
||||
transform: scale3d(1.1, 1.1, 1.1);
|
||||
}
|
||||
|
||||
40% {
|
||||
transform: scale3d(0.9, 0.9, 0.9);
|
||||
}
|
||||
|
||||
60% {
|
||||
opacity: 1;
|
||||
transform: scale3d(1.03, 1.03, 1.03);
|
||||
}
|
||||
|
||||
80% {
|
||||
transform: scale3d(0.97, 0.97, 0.97);
|
||||
}
|
||||
|
||||
to {
|
||||
opacity: 1;
|
||||
transform: scale3d(1, 1, 1);
|
||||
}
|
||||
}
|
||||
|
||||
@-webkit-keyframes bounceIn {
|
||||
from,
|
||||
20%,
|
||||
40%,
|
||||
60%,
|
||||
80%,
|
||||
to {
|
||||
animation-timing-function: cubic-bezier(0.215, 0.61, 0.355, 1);
|
||||
}
|
||||
|
||||
0% {
|
||||
opacity: 0;
|
||||
transform: scale3d(0.3, 0.3, 0.3);
|
||||
}
|
||||
|
||||
20% {
|
||||
transform: scale3d(1.1, 1.1, 1.1);
|
||||
}
|
||||
|
||||
40% {
|
||||
transform: scale3d(0.9, 0.9, 0.9);
|
||||
}
|
||||
|
||||
60% {
|
||||
opacity: 1;
|
||||
transform: scale3d(1.03, 1.03, 1.03);
|
||||
}
|
||||
|
||||
80% {
|
||||
transform: scale3d(0.97, 0.97, 0.97);
|
||||
}
|
||||
|
||||
to {
|
||||
opacity: 1;
|
||||
transform: scale3d(1, 1, 1);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes bounceOut {
|
||||
20% {
|
||||
transform: scale3d(0.9, 0.9, 0.9);
|
||||
}
|
||||
|
||||
50%,
|
||||
55% {
|
||||
opacity: 1;
|
||||
transform: scale3d(1.1, 1.1, 1.1);
|
||||
}
|
||||
|
||||
to {
|
||||
opacity: 0;
|
||||
transform: scale3d(0.3, 0.3, 0.3);
|
||||
}
|
||||
}
|
||||
|
||||
@-webkit-keyframes bounceOut {
|
||||
20% {
|
||||
transform: scale3d(0.9, 0.9, 0.9);
|
||||
}
|
||||
|
||||
50%,
|
||||
55% {
|
||||
opacity: 1;
|
||||
transform: scale3d(1.1, 1.1, 1.1);
|
||||
}
|
||||
|
||||
to {
|
||||
opacity: 0;
|
||||
transform: scale3d(0.3, 0.3, 0.3);
|
||||
}
|
||||
}
|
||||
|
||||
.animate-fadeIn {
|
||||
animation: fadeIn 500ms;
|
||||
}
|
||||
|
||||
.animate-fadeOut {
|
||||
animation: fadeOut 300ms;
|
||||
}
|
||||
|
||||
.animate-bounceIn {
|
||||
animation: bounceIn 300ms;
|
||||
}
|
||||
|
||||
.animate-bounceOut {
|
||||
animation: bounceOut 300ms;
|
||||
}
|
||||
|
||||
.animate-fill-forwards {
|
||||
animation-fill-mode: forwards;
|
||||
}
|
||||
|
||||
.animate-fast {
|
||||
animation-duration: 300ms;
|
||||
}
|
||||
|
||||
.clip {
|
||||
clip-path: inset(0);
|
||||
}
|
||||
|
||||
.no-marker {
|
||||
@apply marker:content-none;
|
||||
}
|
||||
|
||||
.no-marker::-webkit-details-marker {
|
||||
@apply hidden;
|
||||
}
|
||||
}
|
||||
|
||||
@layer components {
|
||||
.btn-secondary {
|
||||
@apply inline-flex flex-row justify-center items-center;
|
||||
@apply py-[5px] px-0.75 rounded-sm cursor-pointer;
|
||||
@apply bg-button-neutral bg-medusa-button-neutral dark:bg-button-neutral-dark dark:bg-medusa-button-neutral-dark;
|
||||
@apply hover:bg-medusa-button-neutral-hover hover:bg-no-image dark:hover:bg-medusa-button-neutral-hover-dark hover:no-underline;
|
||||
@apply active:bg-medusa-button-neutral-pressed active:bg-no-image dark:active:bg-medusa-button-neutral-pressed-dark;
|
||||
@apply focus:bg-medusa-button-neutral-pressed focus:bg-no-image dark:focus:bg-medusa-button-neutral-pressed-dark;
|
||||
@apply disabled:!bg-no-image disabled:bg-medusa-bg-disabled dark:disabled:bg-medusa-bg-disabled-dark;
|
||||
@apply disabled:cursor-not-allowed;
|
||||
@apply border border-solid border-medusa-border-base dark:border-medusa-border-base-dark;
|
||||
@apply text-compact-small-plus text-medusa-fg-base dark:text-medusa-fg-base-dark;
|
||||
@apply shadow-button-neutral focus:shadow-button-neutral-focused active:shadow-button-neutral-focused transition-shadow;
|
||||
@apply dark:shadow-button-neutral dark:focus:shadow-button-neutral-focused dark:active:shadow-button-neutral-focused;
|
||||
@apply select-none;
|
||||
}
|
||||
|
||||
.btn-secondary-icon {
|
||||
@apply !p-0.25;
|
||||
}
|
||||
|
||||
.btn-primary {
|
||||
@apply inline-flex flex-row justify-center items-center;
|
||||
@apply py-[5px] px-0.75 rounded-sm cursor-pointer;
|
||||
@apply bg-button-inverted bg-medusa-button-inverted dark:bg-button-inverted-dark dark:bg-medusa-button-inverted-dark;
|
||||
@apply hover:bg-medusa-button-inverted-hover hover:bg-no-image dark:hover:bg-medusa-button-inverted-hover-dark hover:no-underline;
|
||||
@apply active:bg-medusa-button-inverted-pressed active:bg-no-image dark:active:bg-medusa-button-inverted-pressed-dark;
|
||||
@apply focus:bg-medusa-button-inverted-pressed focus:bg-no-image dark:focus:bg-medusa-button-inverted-pressed-dark;
|
||||
@apply shadow-button-colored active:shadow-button-colored-focused focus:shadow-button-colored-focused transition-shadow;
|
||||
@apply dark:shadow-button-colored-dark dark:active:shadow-button-colored-focused-dark dark:focus:shadow-button-colored-focused-dark;
|
||||
@apply disabled:!bg-no-image disabled:bg-medusa-bg-disabled dark:disabled:bg-medusa-bg-disabled-dark;
|
||||
@apply disabled:cursor-not-allowed disabled:border-medusa-border-base dark:disabled:border-medusa-border-base-dark;
|
||||
@apply text-compact-small-plus text-medusa-fg-on-inverted dark:text-medusa-fg-on-inverted-dark;
|
||||
@apply disabled:text-medusa-fg-disabled dark:disabled:text-medusa-fg-disabled-dark;
|
||||
@apply border border-medusa-border-loud dark:border-medusa-border-loud-dark;
|
||||
@apply select-none;
|
||||
}
|
||||
|
||||
.btn-clear {
|
||||
@apply bg-transparent shadow-none border-0 outline-none cursor-pointer;
|
||||
}
|
||||
}
|
||||
|
||||
@import url('./tooltip.css');
|
||||
@@ -1,10 +0,0 @@
|
||||
:root {
|
||||
--rt-opacity: theme(opacity.100) !important;
|
||||
--rt-color-dark: theme(colors.medusa.bg.base.DEFAULT) !important;
|
||||
--rt-color-white: theme(colors.medusa.fg.subtle.DEFAULT) !important;
|
||||
}
|
||||
|
||||
[data-theme="dark"] {
|
||||
--rt-color-dark: theme(colors.medusa.bg.base.dark) !important;
|
||||
--rt-color-white: theme(colors.medusa.fg.subtle.dark) !important;
|
||||
}
|
||||
@@ -1,70 +0,0 @@
|
||||
"use client"
|
||||
|
||||
import { createContext, useContext, useEffect, useState } from "react"
|
||||
|
||||
type ControlledHeightContextType = {
|
||||
height: number
|
||||
}
|
||||
|
||||
const ControlledHeightContext =
|
||||
createContext<ControlledHeightContextType | null>(null)
|
||||
|
||||
type ControlledHeightProvider = {
|
||||
children?: React.ReactNode
|
||||
}
|
||||
|
||||
const ControlledHeightProvider = ({ children }: ControlledHeightProvider) => {
|
||||
const [height, setHeight] = useState(0)
|
||||
|
||||
const initHeight = () => {
|
||||
const storedHeight = window.localStorage.getItem("height")
|
||||
if (storedHeight) {
|
||||
setHeight(parseFloat(storedHeight))
|
||||
}
|
||||
|
||||
const resizeObserver = new ResizeObserver((entries) => {
|
||||
window.localStorage.setItem(
|
||||
"height",
|
||||
`${entries[0].contentBoxSize[0].inlineSize}`
|
||||
)
|
||||
|
||||
setHeight(entries[0].target.clientHeight)
|
||||
})
|
||||
|
||||
resizeObserver.observe(document.body)
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
if (height !== document.body.clientHeight) {
|
||||
document.body.style.height = `${height}px`
|
||||
}
|
||||
}, [height])
|
||||
|
||||
useEffect(() => {
|
||||
initHeight()
|
||||
}, [])
|
||||
|
||||
return (
|
||||
<ControlledHeightContext.Provider
|
||||
value={{
|
||||
height,
|
||||
}}
|
||||
>
|
||||
{children}
|
||||
</ControlledHeightContext.Provider>
|
||||
)
|
||||
}
|
||||
|
||||
export default ControlledHeightProvider
|
||||
|
||||
export const useControlledHeight = (): ControlledHeightContextType => {
|
||||
const context = useContext(ControlledHeightContext)
|
||||
|
||||
if (!context) {
|
||||
throw new Error(
|
||||
"useControlledHeight must be used inside an ControlledHeightProvider"
|
||||
)
|
||||
}
|
||||
|
||||
return context
|
||||
}
|
||||
@@ -1,42 +0,0 @@
|
||||
"use client"
|
||||
|
||||
import type { Area } from "@/types/openapi"
|
||||
import { createContext, useContext, useState } from "react"
|
||||
|
||||
type NavbarContextType = {
|
||||
activeItem: Area | null
|
||||
setActiveItem: (value: Area) => void
|
||||
}
|
||||
|
||||
const NavbarContext = createContext<NavbarContextType | null>(null)
|
||||
|
||||
type NavbarProviderProps = {
|
||||
children: React.ReactNode
|
||||
}
|
||||
|
||||
const NavbarProvider = ({ children }: NavbarProviderProps) => {
|
||||
const [activeItem, setActiveItem] = useState<Area | null>(null)
|
||||
|
||||
return (
|
||||
<NavbarContext.Provider
|
||||
value={{
|
||||
activeItem,
|
||||
setActiveItem,
|
||||
}}
|
||||
>
|
||||
{children}
|
||||
</NavbarContext.Provider>
|
||||
)
|
||||
}
|
||||
|
||||
export default NavbarProvider
|
||||
|
||||
export const useNavbar = (): NavbarContextType => {
|
||||
const context = useContext(NavbarContext)
|
||||
|
||||
if (!context) {
|
||||
throw new Error("useNavbar must be used inside a NavbarProvider")
|
||||
}
|
||||
|
||||
return context
|
||||
}
|
||||
@@ -1,48 +0,0 @@
|
||||
"use client"
|
||||
|
||||
import { createContext, useContext, useState } from "react"
|
||||
import SearchModal from "../components/Search/Modal"
|
||||
|
||||
type SearchContextType = {
|
||||
isOpen: boolean
|
||||
setIsOpen: React.Dispatch<React.SetStateAction<boolean>>
|
||||
defaultFilters: string[]
|
||||
setDefaultFilters: (value: string[]) => void
|
||||
}
|
||||
|
||||
const SearchContext = createContext<SearchContextType | null>(null)
|
||||
|
||||
type SearchProviderProps = {
|
||||
children: React.ReactNode
|
||||
}
|
||||
|
||||
const SearchProvider = ({ children }: SearchProviderProps) => {
|
||||
const [isOpen, setIsOpen] = useState(false)
|
||||
const [defaultFilters, setDefaultFilters] = useState<string[]>([])
|
||||
|
||||
return (
|
||||
<SearchContext.Provider
|
||||
value={{
|
||||
isOpen,
|
||||
setIsOpen,
|
||||
defaultFilters,
|
||||
setDefaultFilters,
|
||||
}}
|
||||
>
|
||||
{children}
|
||||
<SearchModal />
|
||||
</SearchContext.Provider>
|
||||
)
|
||||
}
|
||||
|
||||
export default SearchProvider
|
||||
|
||||
export const useSearch = (): SearchContextType => {
|
||||
const context = useContext(SearchContext)
|
||||
|
||||
if (!context) {
|
||||
throw new Error("useSearch must be used inside a SearchProvider")
|
||||
}
|
||||
|
||||
return context
|
||||
}
|
||||
@@ -1,10 +0,0 @@
|
||||
export default function checkArraySameElms(
|
||||
arr1: Array<any>,
|
||||
arr2: Array<any>
|
||||
): boolean {
|
||||
if (arr1.length !== arr2.length) {
|
||||
return false
|
||||
}
|
||||
|
||||
return arr1.every((value, index) => value === arr2[index])
|
||||
}
|
||||
@@ -1,6 +0,0 @@
|
||||
{
|
||||
"crons": [{
|
||||
"path": "/api/algolia",
|
||||
"schedule": "0 0 * * 4"
|
||||
}]
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
11
www/apps/api-reference/.eslintrc.js
Normal file
11
www/apps/api-reference/.eslintrc.js
Normal file
@@ -0,0 +1,11 @@
|
||||
module.exports = {
|
||||
root: true,
|
||||
extends: [
|
||||
"docs/next"
|
||||
],
|
||||
settings: {
|
||||
next: {
|
||||
rootDir: ".",
|
||||
},
|
||||
},
|
||||
}
|
||||
@@ -37,4 +37,7 @@ next-env.d.ts
|
||||
|
||||
# unnecessary specs
|
||||
specs/admin.oas.json
|
||||
specs/store.oas.json
|
||||
specs/store.oas.json
|
||||
|
||||
# analyzer
|
||||
analyze
|
||||
1
www/apps/api-reference/.yarnrc.yml
Normal file
1
www/apps/api-reference/.yarnrc.yml
Normal file
@@ -0,0 +1 @@
|
||||
nmMode: hardlinks-local
|
||||
@@ -1,6 +1,6 @@
|
||||
import CodeTabs from "@/components/CodeTabs"
|
||||
import Feedback from "@/components/Feedback"
|
||||
import { Feedback, CodeTabs } from "docs-ui"
|
||||
import SectionContainer from "@/components/Section/Container"
|
||||
import formatReportLink from "@/utils/format-report-link"
|
||||
|
||||
<SectionContainer noTopPadding={true}>
|
||||
|
||||
@@ -22,7 +22,8 @@ Aside from this API reference, check out the [Commerce Modules](https://docs.med
|
||||
area: "admin",
|
||||
section: "introduction"
|
||||
}}
|
||||
sectionTitle="Introduction"
|
||||
reportLink={formatReportLink("admin", "Introduction")}
|
||||
pathName="/api/admin"
|
||||
/>
|
||||
|
||||
</SectionContainer>
|
||||
@@ -148,8 +149,9 @@ You can also pass it to client libraries:
|
||||
area: "admin",
|
||||
section: "authentication-api-key"
|
||||
}}
|
||||
sectionTitle="Authentication - API Token"
|
||||
className="mb-3"
|
||||
reportLink={formatReportLink("admin", "Authentication - API Token")}
|
||||
pathName="/api/admin"
|
||||
/>
|
||||
|
||||
### Cookie Session ID
|
||||
@@ -219,7 +221,8 @@ fetch(`<BACKEND_URL>/admin/products`, {
|
||||
area: "admin",
|
||||
section: "authentication-cookie"
|
||||
}}
|
||||
sectionTitle="Authentication - Cookie Session ID"
|
||||
reportLink={formatReportLink("admin", "Authentication - Cookie Session ID")}
|
||||
pathName="/api/admin"
|
||||
/>
|
||||
|
||||
</SectionContainer>
|
||||
@@ -290,7 +293,8 @@ const App = () => {
|
||||
area: "admin",
|
||||
section: "http-compression"
|
||||
}}
|
||||
sectionTitle="HTTP Compression"
|
||||
reportLink={formatReportLink("admin", "Authentication - Cookie Session ID")}
|
||||
pathName="/api/admin"
|
||||
/>
|
||||
|
||||
</SectionContainer>
|
||||
@@ -501,7 +505,8 @@ relations like `collection`.
|
||||
area: "admin",
|
||||
section: "expand"
|
||||
}}
|
||||
sectionTitle="Expanding Fields"
|
||||
reportLink={formatReportLink("admin", "Expanding Fields")}
|
||||
pathName="/api/admin"
|
||||
/>
|
||||
|
||||
</SectionContainer>
|
||||
@@ -831,7 +836,8 @@ export default Products`,
|
||||
area: "admin",
|
||||
section: "select-fields"
|
||||
}}
|
||||
sectionTitle="Selecting Fields"
|
||||
reportLink={formatReportLink("admin", "Selecting Fields")}
|
||||
pathName="/api/admin"
|
||||
/>
|
||||
|
||||
</SectionContainer>
|
||||
@@ -981,7 +987,8 @@ curl -g "http://localhost:9000/admin/products?created_at[lt]=2023-02-17&created_
|
||||
area: "admin",
|
||||
section: "query-parameters"
|
||||
}}
|
||||
sectionTitle="Query Parameter Types"
|
||||
reportLink={formatReportLink("admin", "Query Parameter Types")}
|
||||
pathName="/api/admin"
|
||||
/>
|
||||
|
||||
</SectionContainer>
|
||||
@@ -1204,7 +1211,8 @@ order.
|
||||
area: "admin",
|
||||
section: "pagination"
|
||||
}}
|
||||
sectionTitle="Pagination"
|
||||
reportLink={formatReportLink("admin", "Pagination")}
|
||||
pathName="/api/admin"
|
||||
/>
|
||||
|
||||
</SectionContainer>
|
||||
@@ -1,4 +1,4 @@
|
||||
import CodeTabs from "@/components/CodeTabs"
|
||||
import { CodeTabs } from "docs-ui"
|
||||
import Space from "@/components/Space"
|
||||
|
||||
### Just Getting Started?
|
||||
@@ -1,6 +1,7 @@
|
||||
import Feedback from "@/components/Feedback"
|
||||
import CodeTabs from "@/components/CodeTabs"
|
||||
|
||||
import { Feedback, CodeTabs } from "docs-ui"
|
||||
import SectionContainer from "@/components/Section/Container"
|
||||
import formatReportLink from "@/utils/format-report-link"
|
||||
|
||||
<SectionContainer noTopPadding={true}>
|
||||
|
||||
@@ -22,7 +23,8 @@ Aside from this API reference, check out the [Commerce Modules](https://docs.med
|
||||
area: "store",
|
||||
section: "introduction"
|
||||
}}
|
||||
sectionTitle="Introduction"
|
||||
reportLink={formatReportLink("store", "Introduction")}
|
||||
pathName="/api/store"
|
||||
/>
|
||||
|
||||
</SectionContainer>
|
||||
@@ -99,7 +101,8 @@ fetch(`<BACKEND_URL>/admin/products`, {
|
||||
area: "store",
|
||||
section: "authentication-cookie"
|
||||
}}
|
||||
sectionTitle="Authentication - Cookie Session ID"
|
||||
reportLink={formatReportLink("store", "Authentication - Cookie Session ID")}
|
||||
pathName="/api/store"
|
||||
/>
|
||||
|
||||
</SectionContainer>
|
||||
@@ -182,7 +185,8 @@ const App = () => {
|
||||
area: "store",
|
||||
section: "publishable-api-key"
|
||||
}}
|
||||
sectionTitle="Publishable API Key"
|
||||
reportLink={formatReportLink("store", "Publishable API Key")}
|
||||
pathName="/api/store"
|
||||
/>
|
||||
|
||||
</SectionContainer>
|
||||
@@ -253,7 +257,8 @@ const App = () => {
|
||||
area: "store",
|
||||
section: "http-compression"
|
||||
}}
|
||||
sectionTitle="HTTP Compression"
|
||||
reportLink={formatReportLink("store", "HTTP Compression")}
|
||||
pathName="/api/store"
|
||||
/>
|
||||
|
||||
</SectionContainer>
|
||||
@@ -456,7 +461,8 @@ relations like `collection`.
|
||||
area: "store",
|
||||
section: "expand"
|
||||
}}
|
||||
sectionTitle="Expanding Fields"
|
||||
reportLink={formatReportLink("store", "Expanding Fields")}
|
||||
pathName="/api/store"
|
||||
/>
|
||||
|
||||
</SectionContainer>
|
||||
@@ -776,7 +782,8 @@ export default Products`,
|
||||
area: "store",
|
||||
section: "select-fields"
|
||||
}}
|
||||
sectionTitle="Selecting Fields"
|
||||
reportLink={formatReportLink("store", "Selecting Fields")}
|
||||
pathName="/api/store"
|
||||
/>
|
||||
|
||||
</SectionContainer>
|
||||
@@ -916,7 +923,8 @@ curl -g "http://localhost:9000/store/products?created_at[lt]=2023-02-17&created_
|
||||
area: "store",
|
||||
section: "query-parameters"
|
||||
}}
|
||||
sectionTitle="Query Parameter Types"
|
||||
reportLink={formatReportLink("store", "Query Parameter Types")}
|
||||
pathName="/api/store"
|
||||
/>
|
||||
|
||||
</SectionContainer>
|
||||
@@ -939,8 +947,8 @@ returning the resulting entities.
|
||||
|
||||
|
||||
You can use the `offset` query parameter to change between pages. For
|
||||
example, if the limit is 50, at page 1 the offset should be 0; at page 2 the
|
||||
offset should be 50, and so on.
|
||||
example, if the limit is `50`, at page `1` the offset should be `0`; at page `2` the
|
||||
offset should be `50`, and so on.
|
||||
|
||||
|
||||
For example, to limit the number of products returned in the List Products
|
||||
@@ -1140,7 +1148,8 @@ order.
|
||||
area: "store",
|
||||
section: "pagination"
|
||||
}}
|
||||
sectionTitle="Pagination"
|
||||
reportLink={formatReportLink("store", "Pagination")}
|
||||
pathName="/api/store"
|
||||
/>
|
||||
|
||||
</SectionContainer>
|
||||
54
www/apps/api-reference/app/api/[area]/layout.tsx
Normal file
54
www/apps/api-reference/app/api/[area]/layout.tsx
Normal file
@@ -0,0 +1,54 @@
|
||||
import clsx from "clsx"
|
||||
import "../../../css/globals.css"
|
||||
import Navbar from "@/components/Navbar"
|
||||
import { Inter } from "next/font/google"
|
||||
import { Roboto_Mono } from "next/font/google"
|
||||
import Providers from "../../../providers"
|
||||
import { Sidebar } from "docs-ui"
|
||||
|
||||
export const metadata = {
|
||||
title: "Medusa API Reference",
|
||||
description: "Check out Medusa's API reference",
|
||||
}
|
||||
|
||||
const inter = Inter({
|
||||
subsets: ["latin"],
|
||||
variable: "--font-inter",
|
||||
weight: ["400", "500"],
|
||||
})
|
||||
|
||||
const robotoMono = Roboto_Mono({
|
||||
subsets: ["latin"],
|
||||
variable: "--font-roboto-mono",
|
||||
})
|
||||
|
||||
export default function RootLayout({
|
||||
children,
|
||||
}: {
|
||||
children: React.ReactNode
|
||||
}) {
|
||||
return (
|
||||
<html lang="en" className={clsx("h-full w-full")}>
|
||||
<body
|
||||
className={clsx(
|
||||
inter.variable,
|
||||
robotoMono.variable,
|
||||
"bg-docs-bg dark:bg-docs-bg-dark font-base text-medium h-full w-full",
|
||||
"text-medusa-fg-subtle dark:text-medusa-fg-subtle-dark"
|
||||
)}
|
||||
>
|
||||
<Providers>
|
||||
<div className="w-full">
|
||||
<Navbar />
|
||||
<div className="max-w-xxl mx-auto flex w-full px-1.5">
|
||||
<Sidebar />
|
||||
<main className="lg:w-ref-main relative mt-4 w-full flex-1 lg:mt-7">
|
||||
{children}
|
||||
</main>
|
||||
</div>
|
||||
</div>
|
||||
</Providers>
|
||||
</body>
|
||||
</html>
|
||||
)
|
||||
}
|
||||
|
Before Width: | Height: | Size: 253 KiB After Width: | Height: | Size: 253 KiB |
@@ -6,7 +6,7 @@ import Section from "@/components/Section"
|
||||
import Tags from "@/components/Tags"
|
||||
import type { Area } from "@/types/openapi"
|
||||
import DividedLayout from "@/layouts/Divided"
|
||||
import capitalize from "@/utils/capitalize"
|
||||
import { capitalize } from "docs-ui"
|
||||
import PageTitleProvider from "../../../providers/page-title"
|
||||
|
||||
type ReferencePageProps = {
|
||||
|
Before Width: | Height: | Size: 253 KiB After Width: | Height: | Size: 253 KiB |
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user