+ {/* @ts-expect-error React v19 doesn't recognize these as elements. */}
Page Not Found
+ {/* @ts-expect-error React v19 doesn't recognize these as elements. */}
The page you were looking for isn't available.
+ {/* @ts-expect-error React v19 doesn't recognize these as elements. */}
If you think this is a mistake, please
diff --git a/www/apps/ui/src/components/component-example.tsx b/www/apps/ui/src/components/component-example.tsx
index 6b1aa1082d..1dd96a20ad 100644
--- a/www/apps/ui/src/components/component-example.tsx
+++ b/www/apps/ui/src/components/component-example.tsx
@@ -28,7 +28,7 @@ export function ComponentExample({
}, [name])
const CodeElement = children as React.ReactElement
- const Code = CodeElement.props.code
+ const Code = (CodeElement.props as Record).code
return (
diff --git a/www/apps/ui/src/components/icon-search.tsx b/www/apps/ui/src/components/icon-search.tsx
index 570881e4bc..2546a19ffa 100644
--- a/www/apps/ui/src/components/icon-search.tsx
+++ b/www/apps/ui/src/components/icon-search.tsx
@@ -8,7 +8,7 @@ import * as React from "react"
const iconNames = Object.keys(Icons).filter((name) => name !== "default")
-const IconSearch = React.memo(function IconSearch() {
+const IconSearch = () => {
const [query, setQuery] = React.useState("")
return (
@@ -23,7 +23,7 @@ const IconSearch = React.memo(function IconSearch() {
)
-})
+}
const SearchResults = ({ query = "" }: { query?: string }) => {
const cleanQuery = escapeStringRegexp(query.trim().replace(/\s/g, " "))
diff --git a/www/apps/user-guide/.content.eslintrc.js b/www/apps/user-guide/.content.eslintrc.js
deleted file mode 100644
index fc843a3a5a..0000000000
--- a/www/apps/user-guide/.content.eslintrc.js
+++ /dev/null
@@ -1,6 +0,0 @@
-module.exports = {
- root: true,
- extends: [
- "docs/content"
- ],
-}
diff --git a/www/apps/user-guide/.content.eslintrc.mjs b/www/apps/user-guide/.content.eslintrc.mjs
new file mode 100644
index 0000000000..65f47a8b41
--- /dev/null
+++ b/www/apps/user-guide/.content.eslintrc.mjs
@@ -0,0 +1,159 @@
+import prettier from "eslint-plugin-prettier"
+import markdown from "eslint-plugin-markdown"
+import globals from "globals"
+import babelParser from "@babel/eslint-parser"
+import typescriptEslintEslintPlugin from "@typescript-eslint/eslint-plugin"
+import tsParser from "@typescript-eslint/parser"
+import path from "node:path"
+import { fileURLToPath } from "node:url"
+import js from "@eslint/js"
+import { FlatCompat } from "@eslint/eslintrc"
+
+const __filename = fileURLToPath(import.meta.url)
+const __dirname = path.dirname(__filename)
+const compat = new FlatCompat({
+ baseDirectory: __dirname,
+ recommendedConfig: js.configs.recommended,
+ allConfig: js.configs.all,
+})
+
+export default [
+ {
+ ignores: [
+ "**/references/**/*",
+ "**/events-reference/**/*",
+ "**/_events-table/**/*",
+ ],
+ },
+ {
+ plugins: {
+ prettier,
+ markdown,
+ },
+
+ languageOptions: {
+ globals: {
+ ...globals.node,
+ },
+
+ parser: babelParser,
+ ecmaVersion: 13,
+ sourceType: "module",
+
+ parserOptions: {
+ requireConfigFile: false,
+
+ ecmaFeatures: {
+ experimentalDecorators: true,
+ modules: true,
+ },
+ },
+ },
+
+ settings: {
+ react: {
+ version: "detect",
+ },
+ },
+
+ rules: {
+ "no-undef": "off",
+ "no-unused-expressions": "off",
+ "no-unused-vars": "off",
+ "no-unused-labels": "off",
+ "no-console": "off",
+ curly: ["error", "all"],
+ "new-cap": "off",
+ "require-jsdoc": "off",
+ camelcase: "off",
+ "no-invalid-this": "off",
+
+ "max-len": [
+ "warn",
+ {
+ code: 64,
+ },
+ ],
+
+ 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": "off",
+ "eol-last": ["error", "always"],
+ "react/prop-types": "off",
+ "react/jsx-no-undef": "off",
+ },
+ },
+ {
+ files: ["**/*.md", "**/*.mdx"],
+ processor: "markdown/markdown",
+ },
+ {
+ files: ["**/*.md/*.js", "**/*.mdx/*.js", "**/*.md/*.jsx", "**/*.mdx/*.jsx"],
+ },
+ ...compat.extends("plugin:@typescript-eslint/recommended").map((config) => ({
+ ...config,
+ files: ["**/*.md/*.ts", "**/*.mdx/*.ts", "**/*.md/*.tsx", "**/*.mdx/*.tsx"],
+ })),
+ {
+ files: ["**/*.md/*.ts", "**/*.mdx/*.ts", "**/*.md/*.tsx", "**/*.mdx/*.tsx"],
+
+ plugins: {
+ "@typescript-eslint": typescriptEslintEslintPlugin,
+ },
+
+ languageOptions: {
+ parser: tsParser,
+ },
+
+ rules: {
+ "@typescript-eslint/no-unused-vars": "off",
+ "@typescript-eslint/no-empty-function": "off",
+ "@typescript-eslint/no-explicit-any": "off",
+ "@typescript-eslint/no-non-null-assertion": "off",
+ "@typescript-eslint/no-var-requires": "off",
+ "prefer-rest-params": "off",
+ "@typescript-eslint/ban-ts-comment": "off",
+ "@typescript-eslint/no-non-null-asserted-optional-chain": "off",
+ "@typescript-eslint/ban-types": "off",
+ },
+ },
+]
diff --git a/www/apps/user-guide/.eslintrc.js b/www/apps/user-guide/.eslintrc.js
deleted file mode 100644
index ef48b51dd2..0000000000
--- a/www/apps/user-guide/.eslintrc.js
+++ /dev/null
@@ -1,14 +0,0 @@
-module.exports = {
- root: true,
- extends: [
- "docs/next"
- ],
- settings: {
- next: {
- rootDir: ".",
- },
- },
- ignorePatterns: [
- "generated"
- ]
-}
diff --git a/www/apps/user-guide/eslint.config.mjs b/www/apps/user-guide/eslint.config.mjs
new file mode 100644
index 0000000000..0113bd8b20
--- /dev/null
+++ b/www/apps/user-guide/eslint.config.mjs
@@ -0,0 +1,207 @@
+import prettier from "eslint-plugin-prettier/recommended"
+import globals from "globals"
+import babelParser from "@babel/eslint-parser"
+import typescriptEslintEslintPlugin from "@typescript-eslint/eslint-plugin"
+import tsParser from "@typescript-eslint/parser"
+import path from "node:path"
+import { fileURLToPath } from "node:url"
+import js from "@eslint/js"
+import { FlatCompat } from "@eslint/eslintrc"
+
+const __filename = fileURLToPath(import.meta.url)
+const __dirname = path.dirname(__filename)
+const compat = new FlatCompat({
+ baseDirectory: __dirname,
+ recommendedConfig: js.configs.recommended,
+ allConfig: js.configs.all,
+})
+
+export default [
+ prettier,
+ {
+ ignores: ["**/eslint-config-docs", "**/.eslintrc.js", "**/dist"],
+ },
+ ...compat.extends(
+ "eslint:recommended",
+ "plugin:react/recommended",
+ "plugin:react/jsx-runtime",
+ "plugin:react-hooks/recommended",
+ "plugin:@next/next/recommended"
+ ),
+ {
+ languageOptions: {
+ globals: {
+ ...globals.node,
+ ...globals.jest,
+ ...globals.browser,
+ },
+
+ parser: babelParser,
+ ecmaVersion: 13,
+ sourceType: "module",
+
+ parserOptions: {
+ requireConfigFile: false,
+
+ ecmaFeatures: {
+ experimentalDecorators: true,
+ jsx: true,
+ modules: true,
+ },
+
+ project: true,
+ },
+ },
+
+ 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"],
+ },
+ ],
+
+ "react/prop-types": [
+ 2,
+ {
+ ignore: ["className"],
+ },
+ ],
+ },
+ },
+ ...compat
+ .extends(
+ "plugin:@typescript-eslint/recommended",
+ "plugin:react/recommended"
+ )
+ .map((config) => ({
+ ...config,
+ files: ["**/*.ts", "**/*.tsx", "**/*.js", "**/*.jsx"],
+ })),
+ {
+ files: ["**/*.ts", "**/*.tsx", "**/*.js", "**/*.jsx"],
+
+ plugins: {
+ "@typescript-eslint": typescriptEslintEslintPlugin,
+ },
+
+ languageOptions: {
+ parser: tsParser,
+ ecmaVersion: 13,
+ sourceType: "module",
+
+ parserOptions: {
+ project: "./tsconfig.json",
+ },
+ },
+
+ settings: {
+ next: {
+ rootDir: ".",
+ },
+ },
+ ignores: [
+ "**/next.config.js",
+ "**/spec",
+ "**/node_modules",
+ "**/public",
+ "**/.eslintrc.js",
+ ],
+
+ rules: {
+ "react/react-in-jsx-scope": "off",
+ "@typescript-eslint/prefer-ts-expect-error": "off",
+ "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",
+ "@/keyword-spacing": "error",
+
+ "@/space-before-function-paren": [
+ "error",
+ {
+ anonymous: "always",
+ named: "never",
+ asyncArrow: "always",
+ },
+ ],
+
+ "@/space-infix-ops": "error",
+ "@typescript-eslint/no-explicit-any": "warn",
+ "@typescript-eslint/no-unused-vars": "warn",
+ },
+ },
+]
diff --git a/www/apps/user-guide/package.json b/www/apps/user-guide/package.json
index 7e9eb86b88..1d187686bf 100644
--- a/www/apps/user-guide/package.json
+++ b/www/apps/user-guide/package.json
@@ -10,19 +10,19 @@
"start": "next start",
"start:monorepo": "yarn start -p 3004",
"lint": "next lint --fix",
- "lint:content": "eslint --no-eslintrc -c .content.eslintrc.js app/**/*.mdx --fix",
+ "lint:content": "eslint --no-config-lookup -c .content.eslintrc.mjs app/**/*.mdx --fix",
"prep": "node ./scripts/prepare.mjs"
},
"dependencies": {
- "@mdx-js/loader": "^3.0.0",
- "@mdx-js/react": "^3.0.0",
+ "@mdx-js/loader": "^3.1.0",
+ "@mdx-js/react": "^3.1.0",
"@medusajs/icons": "^2.0.0",
- "@next/mdx": "^14.2.14",
+ "@next/mdx": "15.0.1",
"clsx": "^2.1.0",
"docs-ui": "*",
- "next": "14.2.14",
- "react": "^18.2.0",
- "react-dom": "^18.2.0",
+ "next": "15.0.1",
+ "react": "rc",
+ "react-dom": "rc",
"rehype-mdx-code-props": "^2.0.0",
"rehype-slug": "^6.0.0",
"remark-directive": "^3.0.0",
@@ -30,15 +30,15 @@
"remark-rehype-plugins": "*"
},
"devDependencies": {
- "@types/mdx": "^2.0.10",
+ "@types/mdx": "^2.0.13",
"@types/node": "^20",
- "@types/react": "^18.2.0",
- "@types/react-dom": "^18.2.0",
+ "@types/react": "npm:types-react@rc",
+ "@types/react-dom": "npm:types-react@rc",
"autoprefixer": "^10.0.1",
"build-scripts": "*",
- "eslint": "^8",
- "eslint-config-docs": "*",
- "eslint-config-next": "14.2.3",
+ "eslint": "^9.13.0",
+ "eslint-plugin-prettier": "^5.2.1",
+ "eslint-plugin-react-hooks": "^5.0.0",
"postcss": "^8",
"tailwind": "*",
"tailwindcss": "^3.3.0",
@@ -48,5 +48,9 @@
},
"engines": {
"node": ">=20"
+ },
+ "overrides": {
+ "@types/react": "npm:types-react@rc",
+ "@types/react-dom": "npm:types-react-dom@rc"
}
}
diff --git a/www/eslint.config.mjs b/www/eslint.config.mjs
new file mode 100644
index 0000000000..d2120e9eee
--- /dev/null
+++ b/www/eslint.config.mjs
@@ -0,0 +1,160 @@
+import prettier from "eslint-plugin-prettier/recommended";
+import globals from "globals";
+import babelParser from "@babel/eslint-parser";
+import typescriptEslintEslintPlugin from "@typescript-eslint/eslint-plugin";
+import tsParser from "@typescript-eslint/parser";
+import path from "node:path";
+import { fileURLToPath } from "node:url";
+import js from "@eslint/js";
+import { FlatCompat } from "@eslint/eslintrc";
+
+const __filename = fileURLToPath(import.meta.url);
+const __dirname = path.dirname(__filename);
+const compat = new FlatCompat({
+ baseDirectory: __dirname,
+ recommendedConfig: js.configs.recommended,
+ allConfig: js.configs.all
+});
+
+export default [
+ prettier,
+ {
+ ignores: ["**/dist", "**/build"],
+}, ...compat.extends(
+ "eslint:recommended",
+ "plugin:react/recommended",
+ "plugin:react/jsx-runtime",
+), {
+
+ languageOptions: {
+ globals: {
+ ...globals.node,
+ ...globals.jest,
+ ...globals.browser,
+ },
+
+ parser: babelParser,
+ ecmaVersion: 13,
+ sourceType: "module",
+
+ parserOptions: {
+ requireConfigFile: false,
+
+ ecmaFeatures: {
+ experimentalDecorators: true,
+ jsx: true,
+ modules: true
+ },
+
+ project: true,
+ },
+ },
+
+ 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"],
+ }],
+
+ "react/prop-types": [2, {
+ ignore: ["className"],
+ }],
+ },
+}, ...compat.extends("plugin:@typescript-eslint/recommended", "plugin:react/recommended").map(config => ({
+ ...config,
+ files: ["**/*.ts", "**/*.tsx", "**/*.js", "**/*.jsx"],
+})), {
+ files: ["**/*.ts", "**/*.tsx", "**/*.js", "**/*.jsx"],
+
+ plugins: {
+ "@typescript-eslint": typescriptEslintEslintPlugin,
+ },
+
+ languageOptions: {
+ parser: tsParser,
+ ecmaVersion: 13,
+ sourceType: "module",
+
+ 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",
+ "@/keyword-spacing": "error",
+
+ "@/space-before-function-paren": ["error", {
+ anonymous: "always",
+ named: "never",
+ asyncArrow: "always",
+ }],
+
+ "@/space-infix-ops": "error",
+ "@typescript-eslint/no-explicit-any": "warn",
+ "@typescript-eslint/no-unused-vars": "warn",
+ },
+ settings: {
+ next: {
+ rootDir: ["apps/*/"],
+ },
+ },
+}];
\ No newline at end of file
diff --git a/www/package.json b/www/package.json
index d009ead948..865b07f972 100644
--- a/www/package.json
+++ b/www/package.json
@@ -20,13 +20,25 @@
},
"dependencies": {
"autoprefixer": "10.4.14",
- "eslint": "^8.36.0",
+ "eslint": "^9.13.0",
"postcss": "8.4.27",
- "prettier": "^2.8.4",
+ "prettier": "^3.3.3",
"tailwindcss": "3.3.3",
"tsconfig": "*",
"turbo": "latest"
},
+ "devDependencies": {
+ "@babel/eslint-parser": "^7.25.9",
+ "@eslint/js": "9.13.0",
+ "@types/eslint__js": "8.42.3",
+ "eslint-config-next": "15.0.1",
+ "eslint-config-prettier": "9.1.0",
+ "eslint-config-turbo": "2.2.3",
+ "eslint-plugin-markdown": "5.1.0",
+ "eslint-plugin-prettier": "5.2.1",
+ "eslint-plugin-react": "7.37.2",
+ "typescript-eslint": "8.11.0"
+ },
"engines": {
"node": ">=18.17.0"
}
diff --git a/www/packages/build-scripts/.eslintrc.cjs b/www/packages/build-scripts/.eslintrc.cjs
deleted file mode 100644
index 81f8b29932..0000000000
--- a/www/packages/build-scripts/.eslintrc.cjs
+++ /dev/null
@@ -1,9 +0,0 @@
-const path = require("path")
-
-module.exports = {
- extends: ["docs"],
- parserOptions: {
- project: true,
- tsconfigRootDir: path.join(__dirname, "..", ".."),
- },
-}
diff --git a/www/packages/build-scripts/package.json b/www/packages/build-scripts/package.json
index 7f6f60a367..487155176b 100644
--- a/www/packages/build-scripts/package.json
+++ b/www/packages/build-scripts/package.json
@@ -31,7 +31,6 @@
},
"devDependencies": {
"@types/node": "^20.11.20",
- "eslint-config-docs": "*",
"rimraf": "^5.0.5",
"tsconfig": "*",
"types": "*",
diff --git a/www/packages/docs-ui/.eslintrc.js b/www/packages/docs-ui/.eslintrc.js
deleted file mode 100644
index c95714ea4d..0000000000
--- a/www/packages/docs-ui/.eslintrc.js
+++ /dev/null
@@ -1,10 +0,0 @@
-module.exports = {
- root: true,
- extends: [
- "docs"
- ],
- parserOptions: {
- project: true,
- tsconfigRootDir: __dirname,
- },
-}
diff --git a/www/packages/docs-ui/package.json b/www/packages/docs-ui/package.json
index c02d3c8732..3b0e400ab7 100644
--- a/www/packages/docs-ui/package.json
+++ b/www/packages/docs-ui/package.json
@@ -34,16 +34,12 @@
"lint": "eslint src --fix"
},
"devDependencies": {
- "@types/react": "^18.2.0",
- "@types/react-dom": "^18.2.0",
- "@types/react-google-recaptcha": "^2.1.6",
+ "@types/react": "npm:types-react@rc",
+ "@types/react-dom": "npm:types-react@rc",
"clsx": "^2.0.0",
"cpy-cli": "^5.0.0",
- "eslint": "^8",
- "eslint-config-docs": "*",
- "next": "^14.2.14",
- "react": "^18.2.0",
- "react-dom": "^18.2.0",
+ "eslint": "^9.13.0",
+ "next": "15.0.1",
"rimraf": "^5.0.1",
"tailwind": "*",
"tailwindcss": "^3.3.3",
@@ -53,31 +49,38 @@
"typescript": "^5.1.6"
},
"peerDependencies": {
- "@types/react": "^18.2.0",
- "@types/react-dom": "^18.2.0",
+ "@types/react": "*",
+ "@types/react-dom": "*",
"next": "*",
- "react": "^18.2.0",
- "react-dom": "^18.2.0"
+ "react": "*",
+ "react-dom": "*"
},
"dependencies": {
+ "@emotion/is-prop-valid": "^1.3.1",
"@medusajs/icons": "^2.0.0",
"@medusajs/ui": "^4.0.0",
"@octokit/request": "^8.1.1",
"@react-hook/resize-observer": "^1.2.6",
- "@segment/analytics-next": "^1.55.0",
+ "@segment/analytics-next": "^1.75.0",
"@uidotdev/usehooks": "^2.4.1",
"algoliasearch": "^5.2.1",
- "framer-motion": "^11.3.21",
+ "framer-motion": "^11.11.9",
"mermaid": "^10.9.0",
"npm-to-yarn": "^2.1.0",
- "prism-react-renderer": "2.3.1",
+ "prism-react-renderer": "2.4.0",
+ "react": "rc",
+ "react-dom": "rc",
"react-google-recaptcha": "^3.1.0",
- "react-instantsearch": "^7.13.0",
- "react-markdown": "^8.0.7",
+ "react-instantsearch": "^7.13.6",
+ "react-markdown": "^9.0.1",
"react-medium-image-zoom": "^5.2.10",
- "react-tooltip": "^5.21.3",
+ "react-tooltip": "^5.28.0",
"react-transition-group": "^4.4.5",
"react-uuid": "^2.0.0",
"slugify": "^1.6.6"
+ },
+ "overrides": {
+ "@types/react": "npm:types-react@rc",
+ "@types/react-dom": "npm:types-react-dom@rc"
}
}
diff --git a/www/packages/docs-ui/src/components/AiAssistant/index.tsx b/www/packages/docs-ui/src/components/AiAssistant/index.tsx
index 2d966bc792..c732515413 100644
--- a/www/packages/docs-ui/src/components/AiAssistant/index.tsx
+++ b/www/packages/docs-ui/src/components/AiAssistant/index.tsx
@@ -297,7 +297,7 @@ export const AiAssistant = () => {
}
}, [loading, answer, thread, lastAnswerIndex, inputRef.current])
- useResizeObserver(contentRef, () => {
+ useResizeObserver(contentRef as React.RefObject, () => {
if (!loading) {
return
}
diff --git a/www/packages/docs-ui/src/components/ApiRunner/ParamInputs/Array/index.tsx b/www/packages/docs-ui/src/components/ApiRunner/ParamInputs/Array/index.tsx
index bb7ad110df..4cb47e957d 100644
--- a/www/packages/docs-ui/src/components/ApiRunner/ParamInputs/Array/index.tsx
+++ b/www/packages/docs-ui/src/components/ApiRunner/ParamInputs/Array/index.tsx
@@ -85,8 +85,8 @@ export const ApiRunnerParamArrayInput = ({
Array.isArray(prev[0])
? [...prev[0]]
: typeof prev[0] === "object"
- ? Object.assign({}, prev[0])
- : prev[0],
+ ? Object.assign({}, prev[0])
+ : prev[0],
])
}}
className="mt-0.5"
diff --git a/www/packages/docs-ui/src/components/ApiRunner/ParamInputs/Default/index.tsx b/www/packages/docs-ui/src/components/ApiRunner/ParamInputs/Default/index.tsx
index 8dfbffb451..24f869a1af 100644
--- a/www/packages/docs-ui/src/components/ApiRunner/ParamInputs/Default/index.tsx
+++ b/www/packages/docs-ui/src/components/ApiRunner/ParamInputs/Default/index.tsx
@@ -94,8 +94,8 @@ export const ApiRunnerParamInput = ({
typeof paramValue === "string"
? (paramValue as string)
: typeof paramValue === "number"
- ? (paramValue as number)
- : `${paramValue}`
+ ? (paramValue as number)
+ : `${paramValue}`
}
className="w-full"
/>
diff --git a/www/packages/docs-ui/src/components/ApiRunner/index.tsx b/www/packages/docs-ui/src/components/ApiRunner/index.tsx
index f2a680613b..545dc60811 100644
--- a/www/packages/docs-ui/src/components/ApiRunner/index.tsx
+++ b/www/packages/docs-ui/src/components/ApiRunner/index.tsx
@@ -163,8 +163,8 @@ export const ApiRunner = React.forwardRef(
!responseCode
? "red"
: responseCode.startsWith("2")
- ? "green"
- : "red"
+ ? "green"
+ : "red"
}
/>
)}
diff --git a/www/packages/docs-ui/src/components/Breadcrumbs/index.tsx b/www/packages/docs-ui/src/components/Breadcrumbs/index.tsx
index ede20126fe..a643b7b5c6 100644
--- a/www/packages/docs-ui/src/components/Breadcrumbs/index.tsx
+++ b/www/packages/docs-ui/src/components/Breadcrumbs/index.tsx
@@ -33,18 +33,18 @@ export const Breadcrumbs = () => {
item.parentItem?.type === "link"
? getLinkPath(item.parentItem)
: (item.parentItem?.type === "category" &&
- breadcrumbOptions?.showCategories) ||
- item.parentItem?.type === "sub-category"
- ? "#"
- : undefined
+ breadcrumbOptions?.showCategories) ||
+ item.parentItem?.type === "sub-category"
+ ? "#"
+ : undefined
const firstItemPath =
item.default[0].type === "link"
? getLinkPath(item.default[0])
: (item.default[0].type === "category" &&
- breadcrumbOptions?.showCategories) ||
- item.default[0].type === "sub-category"
- ? "#"
- : undefined
+ breadcrumbOptions?.showCategories) ||
+ item.default[0].type === "sub-category"
+ ? "#"
+ : undefined
const breadcrumbPath = parentPath || firstItemPath || "/"
diff --git a/www/packages/docs-ui/src/components/ChildDocs/index.tsx b/www/packages/docs-ui/src/components/ChildDocs/index.tsx
index 5be8ca4fdb..a723e81e38 100644
--- a/www/packages/docs-ui/src/components/ChildDocs/index.tsx
+++ b/www/packages/docs-ui/src/components/ChildDocs/index.tsx
@@ -1,7 +1,7 @@
"use client"
import React, { useMemo } from "react"
-import { Card, CardList, MDXComponents, useSidebar } from "../.."
+import { Card, CardList, H2, useSidebar } from "../.."
import { InteractiveSidebarItem, SidebarItem, SidebarItemLink } from "types"
import slugify from "slugify"
@@ -27,8 +27,8 @@ export const ChildDocs = ({
return showItems !== undefined
? "show"
: hideItems.length > 0
- ? "hide"
- : "all"
+ ? "hide"
+ : "all"
}, [showItems, hideItems])
const filterCondition = (item: SidebarItem): boolean => {
@@ -132,12 +132,12 @@ export const ChildDocs = ({
childItem.type === "link"
? childItem.path
: childItem.children?.length
- ? (
- childItem.children.find(
- (item) => item.type === "link"
- ) as SidebarItemLink
- )?.path
- : "#"
+ ? (
+ childItem.children.find(
+ (item) => item.type === "link"
+ ) as SidebarItemLink
+ )?.path
+ : "#"
return {
title: childItem.title,
href,
@@ -151,9 +151,7 @@ export const ChildDocs = ({
const getAllLevelsElms = (items?: SidebarItem[]) =>
filterNonInteractiveItems(items).map((item, key) => {
const itemChildren = getChildrenForLevel(item)
- const HeadingComponent = itemChildren?.length
- ? MDXComponents["h2"]
- : undefined
+ const HeadingComponent = itemChildren?.length ? H2 : undefined
return (
diff --git a/www/packages/docs-ui/src/components/CodeBlock/Collapsible/Lines/index.tsx b/www/packages/docs-ui/src/components/CodeBlock/Collapsible/Lines/index.tsx
index 809e37f44c..29db163782 100644
--- a/www/packages/docs-ui/src/components/CodeBlock/Collapsible/Lines/index.tsx
+++ b/www/packages/docs-ui/src/components/CodeBlock/Collapsible/Lines/index.tsx
@@ -1,6 +1,4 @@
-"use client"
-
-import React, { useMemo } from "react"
+import React from "react"
import { CollapsibleReturn } from "../../../../hooks"
export type CodeBlockCollapsibleLinesProps = {
@@ -12,18 +10,13 @@ export const CodeBlockCollapsibleLines = ({
children,
type,
collapsed,
- getCollapsibleElms,
}: CodeBlockCollapsibleLinesProps) => {
- const shownChildren: React.ReactNode = useMemo(() => {
- const isStart = type === "start"
- return (
- <>
- {collapsed && Array.isArray(children)
- ? children.slice(isStart ? -2 : 0, isStart ? undefined : 2)
- : children}
- >
- )
- }, [children, collapsed])
-
- return getCollapsibleElms(shownChildren)
+ const isStart = type === "start"
+ return (
+ <>
+ {collapsed && Array.isArray(children)
+ ? children.slice(isStart ? -2 : 0, isStart ? undefined : 2)
+ : children}
+ >
+ )
}
diff --git a/www/packages/docs-ui/src/components/CodeBlock/index.tsx b/www/packages/docs-ui/src/components/CodeBlock/index.tsx
index eefce95c1d..c284e021d0 100644
--- a/www/packages/docs-ui/src/components/CodeBlock/index.tsx
+++ b/www/packages/docs-ui/src/components/CodeBlock/index.tsx
@@ -8,6 +8,7 @@ import { useColorMode } from "@/providers"
import { CodeBlockHeader, CodeBlockHeaderMeta } from "./Header"
import { CodeBlockLine } from "./Line"
import { ApiAuthType, ApiDataOptions, ApiMethod } from "types"
+// @ts-expect-error can't install the types package because it doesn't support React v19
import { CSSTransition } from "react-transition-group"
import { useCollapsibleCodeLines } from "../.."
import { HighlightProps as CollapsibleHighlightProps } from "@/hooks"
diff --git a/www/packages/docs-ui/src/components/CodeTabs/index.tsx b/www/packages/docs-ui/src/components/CodeTabs/index.tsx
index ef39aa662b..35df69d011 100644
--- a/www/packages/docs-ui/src/components/CodeTabs/index.tsx
+++ b/www/packages/docs-ui/src/components/CodeTabs/index.tsx
@@ -16,6 +16,7 @@ import { CodeBlockHeaderWrapper } from "../CodeBlock/Header/Wrapper"
type CodeTab = BaseTabType & {
codeProps: CodeBlockProps
codeBlock: React.ReactNode
+ children?: React.ReactNode
}
type CodeTabProps = {
@@ -33,36 +34,72 @@ export const CodeTabs = ({
blockStyle = "loud",
}: CodeTabProps) => {
const { colorMode } = useColorMode()
+
+ const isCodeBlock = (
+ node: React.ReactNode
+ ): node is
+ | React.ReactElement>
+ | React.ReactPortal => {
+ if (!React.isValidElement(node)) {
+ return false
+ }
+
+ if (node.type === "pre") {
+ return true
+ }
+
+ const typedProps = node.props as Record
+
+ return "source" in typedProps
+ }
+
const tabs: CodeTab[] = useMemo(() => {
const tempTabs: CodeTab[] = []
Children.forEach(children, (child) => {
+ if (!React.isValidElement(child)) {
+ return
+ }
+ const typedChildProps = child.props as CodeTab
if (
!React.isValidElement(child) ||
- !child.props.label ||
- !child.props.value ||
- !React.isValidElement(child.props.children)
+ !typedChildProps.label ||
+ !typedChildProps.value ||
+ !React.isValidElement(typedChildProps.children)
) {
return
}
- // extract child code block
- const codeBlock =
- child.props.children.type === "pre" &&
- React.isValidElement(child.props.children.props.children)
- ? child.props.children.props.children
- : child.props.children
+ const codeBlock: React.ReactNode = isCodeBlock(typedChildProps.children)
+ ? typedChildProps.children
+ : undefined
+
+ if (!codeBlock) {
+ return
+ }
+
+ const codeBlockProps = codeBlock.props as CodeBlockProps
tempTabs.push({
- label: child.props.label,
- value: child.props.value,
- codeProps: codeBlock.props,
+ label: typedChildProps.label,
+ value: typedChildProps.value,
+ codeProps: codeBlockProps,
codeBlock: {
...codeBlock,
props: {
- ...codeBlock.props,
- badgeLabel: undefined,
- hasTabs: true,
- className: clsx("!my-0", codeBlock.props.className),
+ ...codeBlockProps,
+ children: {
+ ...(typeof codeBlockProps.children === "object"
+ ? codeBlockProps.children
+ : {}),
+ props: {
+ ...(React.isValidElement(codeBlockProps.children)
+ ? (codeBlockProps.children.props as Record)
+ : {}),
+ badgeLabel: undefined,
+ hasTabs: true,
+ className: clsx("!my-0", codeBlockProps.className),
+ },
+ },
},
},
})
@@ -188,7 +225,7 @@ export const CodeTabs = ({
return (
tabRefs.push(tabButton)
@@ -197,7 +234,7 @@ export const CodeTabs = ({
isSelected={
!selectedTab
? index === 0
- : selectedTab.value === child.props.value
+ : selectedTab.value === (child.props as CodeTab).value
}
/>
)
diff --git a/www/packages/docs-ui/src/components/Details/Summary/index.tsx b/www/packages/docs-ui/src/components/Details/Summary/index.tsx
index 226c09641e..3a45282c4c 100644
--- a/www/packages/docs-ui/src/components/Details/Summary/index.tsx
+++ b/www/packages/docs-ui/src/components/Details/Summary/index.tsx
@@ -34,7 +34,7 @@ export const DetailsSummary = ({
expandable && "cursor-pointer",
!expandable &&
"border-medusa-border-base border-y border-solid border-x-0",
- (expandable || badge) && "gap-0.5",
+ (expandable || badge !== undefined) && "gap-0.5",
"no-marker",
className
)}
diff --git a/www/packages/docs-ui/src/components/Details/index.tsx b/www/packages/docs-ui/src/components/Details/index.tsx
index e528ac5f34..97b6499c39 100644
--- a/www/packages/docs-ui/src/components/Details/index.tsx
+++ b/www/packages/docs-ui/src/components/Details/index.tsx
@@ -3,7 +3,7 @@
import React, { Suspense, cloneElement, useRef, useState } from "react"
import { Loading } from "@/components"
import clsx from "clsx"
-import { DetailsSummary } from "./Summary"
+import { DetailsSummary, DetailsSummaryProps } from "./Summary"
import { useCollapsible } from "../../hooks"
export type DetailsProps = {
@@ -22,12 +22,14 @@ export const Details = ({
...props
}: DetailsProps) => {
const [open, setOpen] = useState(openInitial)
+ const ref = useRef(null)
+ const childrenWrapperRef = useRef(null)
const { getCollapsibleElms, setCollapsed } = useCollapsible({
initialValue: !openInitial,
heightAnimation,
onClose: () => setOpen(false),
+ childrenRef: childrenWrapperRef,
})
- const ref = useRef(null)
const handleToggle = (e: React.MouseEvent) => {
const targetElm = e.target as HTMLElement
@@ -77,13 +79,19 @@ export const Details = ({
/>
)}
{summaryElm &&
- cloneElement(summaryElm as React.ReactElement, {
- open,
- onClick: handleToggle,
- })}
+ cloneElement(
+ summaryElm as React.ReactElement<
+ DetailsSummaryProps,
+ React.FunctionComponent
+ >,
+ {
+ open,
+ onClick: handleToggle,
+ }
+ )}
{getCollapsibleElms(
}>
- {children}
+ {children}
)}
diff --git a/www/packages/docs-ui/src/components/Feedback/index.tsx b/www/packages/docs-ui/src/components/Feedback/index.tsx
index 0d84f26dca..9672c2c0a4 100644
--- a/www/packages/docs-ui/src/components/Feedback/index.tsx
+++ b/www/packages/docs-ui/src/components/Feedback/index.tsx
@@ -1,6 +1,7 @@
"use client"
import React, { useRef, useState } from "react"
+// @ts-expect-error can't install the types package because it doesn't support React v19
import { CSSTransition, SwitchTransition } from "react-transition-group"
import { Solutions } from "./Solutions"
import { ExtraData, useAnalytics } from "@/providers/Analytics"
@@ -65,11 +66,11 @@ export const Feedback = ({
const [medusaVersion, setMedusaVersion] = useState("")
const [errorFix, setErrorFix] = useState("")
const [contactInfo, setContactInfo] = useState("")
- const nodeRef: React.RefObject = submittedFeedback
+ const nodeRef = submittedFeedback
? inlineMessageRef
: showForm
- ? inlineQuestionRef
- : inlineFeedbackRef
+ ? inlineQuestionRef
+ : inlineFeedbackRef
const { loaded, track } = useAnalytics()
function handleFeedback(e: React.MouseEvent) {
@@ -132,12 +133,12 @@ export const Feedback = ({
showForm
? "show_form"
: !submittedFeedback
- ? "feedback"
- : "submitted_feedback"
+ ? "feedback"
+ : "submitted_feedback"
}
nodeRef={nodeRef}
timeout={300}
- addEndListener={(done) => {
+ addEndListener={(done: () => void) => {
nodeRef.current?.addEventListener("transitionend", done, false)
}}
classNames={{
diff --git a/www/packages/docs-ui/src/components/Heading/H2/index.tsx b/www/packages/docs-ui/src/components/Heading/H2/index.tsx
index e285c0afea..9d3273562e 100644
--- a/www/packages/docs-ui/src/components/Heading/H2/index.tsx
+++ b/www/packages/docs-ui/src/components/Heading/H2/index.tsx
@@ -7,7 +7,7 @@ import { useIsBrowser } from "../../../providers"
type H2Props = React.HTMLAttributes & {
id?: string
- passRef?: React.RefObject
+ passRef?: React.RefObject
}
export const H2 = ({ className, children, passRef, ...props }: H2Props) => {
diff --git a/www/packages/docs-ui/src/components/LearningPath/Finish/index.tsx b/www/packages/docs-ui/src/components/LearningPath/Finish/index.tsx
index 8ee3defae6..78ab63019a 100644
--- a/www/packages/docs-ui/src/components/LearningPath/Finish/index.tsx
+++ b/www/packages/docs-ui/src/components/LearningPath/Finish/index.tsx
@@ -32,7 +32,7 @@ export const LearningPathFinish = ({
)}
{type === "custom" && (
- {step.descriptionJSX}
+ {step.descriptionJSX as React.ReactNode}
)}
>
diff --git a/www/packages/docs-ui/src/components/LearningPath/Steps/index.tsx b/www/packages/docs-ui/src/components/LearningPath/Steps/index.tsx
index fa64f39aa7..929752a242 100644
--- a/www/packages/docs-ui/src/components/LearningPath/Steps/index.tsx
+++ b/www/packages/docs-ui/src/components/LearningPath/Steps/index.tsx
@@ -5,6 +5,7 @@ import clsx from "clsx"
import { IconCircleDottedLine } from "@/components/Icons"
import { CheckCircleSolid, CircleMiniSolid, ListBullet } from "@medusajs/icons"
import { Badge, Button, Link } from "@/components"
+// @ts-expect-error can't install the types package because it doesn't support React v19
import { CSSTransition, SwitchTransition } from "react-transition-group"
type LearningPathStepsProps = {
@@ -17,7 +18,7 @@ export const LearningPathSteps = ({ ...rest }: LearningPathStepsProps) => {
const [collapsed, setCollapsed] = useState(false)
const stepsRef = useRef(null)
const buttonRef = useRef(null)
- const nodeRef: React.RefObject = collapsed ? buttonRef : stepsRef
+ const nodeRef = collapsed ? buttonRef : stepsRef
const handleScroll = useCallback(() => {
if (window.scrollY > 100 && !collapsed) {
@@ -51,7 +52,7 @@ export const LearningPathSteps = ({ ...rest }: LearningPathStepsProps) => {
key={collapsed ? "show_path" : "show_button"}
nodeRef={nodeRef}
timeout={300}
- addEndListener={(done) => {
+ addEndListener={(done: () => void) => {
nodeRef.current?.addEventListener("transitionend", done, false)
}}
classNames={{
@@ -120,7 +121,8 @@ export const LearningPathSteps = ({ ...rest }: LearningPathStepsProps) => {
"text-medium text-ui-fg-subtle mt-docs_1"
)}
>
- {step.descriptionJSX ?? step.description}
+ {(step.descriptionJSX as React.ReactNode) ??
+ step.description}