docs: improvements and fixes to components in API reference (#9410)

- Change layout of parameters for clearer display
- Fix schema code blocks being longer than container
- switch between showing required to showing optional indicator
- Fixed code tabs not having copy / report buttons

Closes DOCS-936

Preview: https://api-reference-v2-git-docs-api-ref-comp-improv-medusajs.vercel.app/v2/api/store
This commit is contained in:
Shahed Nasser
2024-10-09 20:51:27 +03:00
committed by GitHub
parent 8d3e7b3336
commit 7f1f075222
14 changed files with 239 additions and 187 deletions

View File

@@ -67,6 +67,14 @@ const TagsOperationDescriptionSection = ({
workflow={operation["x-workflow"]} workflow={operation["x-workflow"]}
/> />
)} )}
{operation.externalDocs && (
<>
Related guide:{" "}
<Link href={operation.externalDocs.url} target="_blank">
{operation.externalDocs.description || "Read More"}
</Link>
</>
)}
<Feedback <Feedback
event="survey_api-ref" event="survey_api-ref"
extraData={{ extraData={{
@@ -79,14 +87,6 @@ const TagsOperationDescriptionSection = ({
vertical={true} vertical={true}
question="Did this API Route run successfully?" question="Did this API Route run successfully?"
/> />
{operation.externalDocs && (
<>
Related guide:{" "}
<Link href={operation.externalDocs.url} target="_blank">
{operation.externalDocs.description || "Read More"}
</Link>
</>
)}
{operation.security && ( {operation.security && (
<TagsOperationDescriptionSectionSecurity <TagsOperationDescriptionSectionSecurity
security={operation.security} security={operation.security}

View File

@@ -16,100 +16,37 @@ type TagOperationParametersDescriptionProps = {
const TagOperationParametersDescription = ({ const TagOperationParametersDescription = ({
schema, schema,
}: TagOperationParametersDescriptionProps) => { }: TagOperationParametersDescriptionProps) => {
let typeDescription: React.ReactNode = <></>
switch (true) {
case schema.type === "object":
typeDescription = (
<>
{schema.type} {schema.title ? `(${schema.title})` : ""}
{schema.nullable ? ` or null` : ""}
</>
)
break
case schema.type === "array":
typeDescription = (
<>
{schema.type === "array" && formatArrayDescription(schema.items)}
{schema.nullable ? ` or null` : ""}
</>
)
break
case schema.anyOf !== undefined:
case schema.allOf !== undefined:
typeDescription = (
<>
{formatUnionDescription(schema.allOf)}
{schema.nullable ? ` or null` : ""}
</>
)
break
case schema.oneOf !== undefined:
typeDescription = (
<>
{schema.oneOf?.map((item, index) => (
<Fragment key={index}>
{index !== 0 && <> or </>}
{item.type !== "array" && <>{item.title || item.type}</>}
{item.type === "array" && (
<>array{item.items.type ? ` of ${item.items.type}s` : ""}</>
)}
</Fragment>
))}
{schema.nullable ? ` or null` : ""}
</>
)
break
default:
typeDescription = (
<>
{!schema.type ? "any" : schema.type}
{schema.nullable ? ` or null` : ""}
{schema.format ? ` <${schema.format}>` : ""}
</>
)
}
return ( return (
<div className={clsx("w-2/3 break-words pb-0.5")}> <div className={clsx("pb-0.5 flex flex-col gap-0.25")}>
{typeDescription}
{schema.default !== undefined && ( {schema.default !== undefined && (
<> <span>
<br /> Default:{" "}
<span> <InlineCode className="break-words">
Default:{" "} {JSON.stringify(schema.default)}
<InlineCode className="break-words"> </InlineCode>
{JSON.stringify(schema.default)} </span>
</InlineCode>
</span>
</>
)} )}
{schema.enum && ( {schema.enum && (
<> <span>
<br /> Enum:{" "}
<span> {schema.enum.map((value, index) => (
Enum:{" "} <Fragment key={index}>
{schema.enum.map((value, index) => ( {index !== 0 && <>, </>}
<Fragment key={index}> <InlineCode key={index}>{JSON.stringify(value)}</InlineCode>
{index !== 0 && <>, </>} </Fragment>
<InlineCode key={index}>{JSON.stringify(value)}</InlineCode> ))}
</Fragment> </span>
))}
</span>
</>
)} )}
{schema.example !== undefined && ( {schema.example !== undefined && (
<> <span>
<br /> Example:{" "}
<span> <InlineCode className="break-words">
Example:{" "} {JSON.stringify(schema.example)}
<InlineCode className="break-words"> </InlineCode>
{JSON.stringify(schema.example)} </span>
</InlineCode>
</span>
</>
)} )}
{schema.description && ( {schema.description && (
<> <>
<br />
<MDXContentClient <MDXContentClient
content={capitalize(schema.description)} content={capitalize(schema.description)}
className={clsx("!mb-0 [&>*]:!mb-0")} className={clsx("!mb-0 [&>*]:!mb-0")}
@@ -120,33 +57,15 @@ const TagOperationParametersDescription = ({
</> </>
)} )}
{schema.externalDocs && ( {schema.externalDocs && (
<> <span>
Related guide:{" "} Related guide:{" "}
<Link href={schema.externalDocs.url} target="_blank"> <Link href={schema.externalDocs.url} target="_blank">
{schema.externalDocs.description || "Read More"} {schema.externalDocs.description || "Read More"}
</Link> </Link>
</> </span>
)} )}
</div> </div>
) )
} }
export default TagOperationParametersDescription export default TagOperationParametersDescription
function formatArrayDescription(schema?: SchemaObject) {
if (!schema) {
return "Array"
}
const type =
schema.type === "object"
? `objects ${schema.title ? `(${schema.title})` : ""}`
: `${schema.type || "object"}s`
return `Array of ${type}`
}
function formatUnionDescription(arr?: SchemaObject[]) {
const types = [...new Set(arr?.map((type) => type.type || "object"))]
return <>{types.join(" or ")}</>
}

View File

@@ -1,5 +1,6 @@
import type { SchemaObject } from "@/types/openapi" import type { SchemaObject } from "@/types/openapi"
import { Badge, ExpandableNotice, FeatureFlagNotice } from "docs-ui" import { Badge, ExpandableNotice, FeatureFlagNotice } from "docs-ui"
import { Fragment } from "react"
export type TagOperationParametersNameProps = { export type TagOperationParametersNameProps = {
name: string name: string
@@ -12,39 +13,101 @@ const TagOperationParametersName = ({
isRequired, isRequired,
schema, schema,
}: TagOperationParametersNameProps) => { }: TagOperationParametersNameProps) => {
let typeDescription: React.ReactNode = <></>
switch (true) {
case schema.type === "object":
typeDescription = (
<>
{schema.type} {schema.title ? `(${schema.title})` : ""}
{schema.nullable ? ` or null` : ""}
</>
)
break
case schema.type === "array":
typeDescription = (
<>
{schema.type === "array" && formatArrayDescription(schema.items)}
{schema.nullable ? ` or null` : ""}
</>
)
break
case schema.anyOf !== undefined:
case schema.allOf !== undefined:
typeDescription = (
<>
{formatUnionDescription(schema.allOf)}
{schema.nullable ? ` or null` : ""}
</>
)
break
case schema.oneOf !== undefined:
typeDescription = (
<>
{schema.oneOf?.map((item, index) => (
<Fragment key={index}>
{index !== 0 && <> or </>}
{item.type !== "array" && <>{item.title || item.type}</>}
{item.type === "array" && (
<>array{item.items.type ? ` of ${item.items.type}s` : ""}</>
)}
</Fragment>
))}
{schema.nullable ? ` or null` : ""}
</>
)
break
default:
typeDescription = (
<>
{!schema.type ? "any" : schema.type}
{schema.nullable ? ` or null` : ""}
{schema.format ? ` <${schema.format}>` : ""}
</>
)
}
return ( return (
<span className="w-1/3 break-words pr-0.5"> <span className="inline-flex gap-0.5 items-center">
<span className="font-monospace">{name}</span> <span className="font-monospace">{name}</span>
<span className="text-medusa-fg-muted text-compact-small">
{typeDescription}
</span>
{schema.deprecated && ( {schema.deprecated && (
<Badge variant="orange" className="ml-1"> <Badge variant="orange" className="ml-1">
deprecated deprecated
</Badge> </Badge>
)} )}
{schema["x-expandable"] && ( {schema["x-expandable"] && (
<> <ExpandableNotice type="request" link="#expanding-relations" />
<br />
<ExpandableNotice type="request" link="#expanding-relations" />
</>
)} )}
{schema["x-featureFlag"] && ( {schema["x-featureFlag"] && (
<> <FeatureFlagNotice featureFlag={schema["x-featureFlag"]} type="type" />
<br />
<FeatureFlagNotice
featureFlag={schema["x-featureFlag"]}
type="type"
/>
</>
)} )}
{isRequired && ( {!isRequired && (
<> <span className="text-medusa-tag-blue-text text-compact-x-small">
<br /> optional
<span className="text-medusa-tag-red-text text-compact-x-small"> </span>
required
</span>
</>
)} )}
</span> </span>
) )
} }
export default TagOperationParametersName export default TagOperationParametersName
function formatArrayDescription(schema?: SchemaObject) {
if (!schema) {
return "Array"
}
const type =
schema.type === "object"
? `objects ${schema.title ? `(${schema.title})` : ""}`
: `${schema.type || "object"}s`
return `Array of ${type}`
}
function formatUnionDescription(arr?: SchemaObject[]) {
const types = [...new Set(arr?.map((type) => type.type || "object"))]
return <>{types.join(" or ")}</>
}

View File

@@ -21,7 +21,7 @@ const TagOperationParametersDefault = ({
return ( return (
<div <div
className={clsx( className={clsx(
"my-0.5 inline-flex justify-between", "my-0.5 inline-flex flex-col justify-between gap-0.25",
expandable && "w-[calc(100%-16px)]", expandable && "w-[calc(100%-16px)]",
!expandable && "w-full pl-1", !expandable && "w-full pl-1",
className className

View File

@@ -101,16 +101,20 @@ const TagOperationParametersObject = ({
const content = ( const content = (
<> <>
{sortedProperties.map((property, index) => ( {sortedProperties.map((property, index) => (
<TagOperationParameters <>
schemaObject={{ {index !== 0 && <hr className="bg-medusa-border-base my-0" />}
...properties[property], <TagOperationParameters
parameterName: property, schemaObject={{
}} ...properties[property],
key={index} parameterName: property,
isRequired={ }}
properties[property].isRequired || checkRequired(schema, property) key={index}
} isRequired={
/> properties[property].isRequired ||
checkRequired(schema, property)
}
/>
</>
))} ))}
</> </>
) )

View File

@@ -1,4 +1,4 @@
import { useEffect, useMemo } from "react" import { useEffect, useMemo, useRef, useState } from "react"
import { SchemaObject } from "../../../../types/openapi" import { SchemaObject } from "../../../../types/openapi"
import TagOperationParameters from "../../Operation/Parameters" import TagOperationParameters from "../../Operation/Parameters"
import { import {
@@ -16,6 +16,8 @@ import useSchemaExample from "../../../../hooks/use-schema-example"
import { InView } from "react-intersection-observer" import { InView } from "react-intersection-observer"
import checkElementInViewport from "../../../../utils/check-element-in-viewport" import checkElementInViewport from "../../../../utils/check-element-in-viewport"
import { singular } from "pluralize" import { singular } from "pluralize"
import useResizeObserver from "@react-hook/resize-observer"
import clsx from "clsx"
export type TagSectionSchemaProps = { export type TagSectionSchemaProps = {
schema: SchemaObject schema: SchemaObject
@@ -23,6 +25,8 @@ export type TagSectionSchemaProps = {
} }
const TagSectionSchema = ({ schema, tagName }: TagSectionSchemaProps) => { const TagSectionSchema = ({ schema, tagName }: TagSectionSchemaProps) => {
const paramsRef = useRef<HTMLDivElement>(null)
const [maxCodeHeight, setMaxCodeHeight] = useState(0)
const { addItems, setActivePath, activePath } = useSidebar() const { addItems, setActivePath, activePath } = useSidebar()
const tagSlugName = useMemo(() => getSectionId([tagName]), [tagName]) const tagSlugName = useMemo(() => getSectionId([tagName]), [tagName])
const formattedName = useMemo( const formattedName = useMemo(
@@ -39,6 +43,9 @@ const TagSectionSchema = ({ schema, tagName }: TagSectionSchemaProps) => {
skipNonRequired: false, skipNonRequired: false,
}, },
}) })
useResizeObserver(paramsRef, () => {
setMaxCodeHeight(paramsRef.current?.clientHeight || 0)
})
const { scrollableElement, scrollToElement } = useScrollController() const { scrollableElement, scrollToElement } = useScrollController()
const root = useMemo(() => { const root = useMemo(() => {
@@ -106,7 +113,7 @@ const TagSectionSchema = ({ schema, tagName }: TagSectionSchemaProps) => {
> >
<DividedLayout <DividedLayout
mainContent={ mainContent={
<SectionContainer> <SectionContainer ref={paramsRef}>
<h2>{formattedName} Object</h2> <h2>{formattedName} Object</h2>
<h4 className="border-medusa-border-base border-b py-1.5 mt-2"> <h4 className="border-medusa-border-base border-b py-1.5 mt-2">
Fields Fields
@@ -121,6 +128,11 @@ const TagSectionSchema = ({ schema, tagName }: TagSectionSchemaProps) => {
source={examples[0].content} source={examples[0].content}
lang="json" lang="json"
title={`The ${formattedName} Object`} title={`The ${formattedName} Object`}
className={clsx(maxCodeHeight && "overflow-auto")}
style={{
// remove padding + extra space
maxHeight: maxCodeHeight ? maxCodeHeight - 212 : "unset",
}}
/> />
)} )}
</SectionContainer> </SectionContainer>

View File

@@ -74,7 +74,7 @@ const TagSection = ({ tag }: TagSectionProps) => {
return isElmWindow(scrollableElement) ? document.body : scrollableElement return isElmWindow(scrollableElement) ? document.body : scrollableElement
}, [scrollableElement]) }, [scrollableElement])
const { ref } = useInView({ const { ref } = useInView({
threshold: 0.5, threshold: 0.8,
rootMargin: `112px 0px 112px 0px`, rootMargin: `112px 0px 112px 0px`,
root, root,
onChange: (inView) => { onChange: (inView) => {

View File

@@ -18,6 +18,7 @@
"@medusajs/icons": "preview", "@medusajs/icons": "preview",
"@medusajs/ui": "^3.0.0", "@medusajs/ui": "^3.0.0",
"@next/mdx": "14.2.14", "@next/mdx": "14.2.14",
"@react-hook/resize-observer": "^2.0.2",
"@readme/openapi-parser": "^2.5.0", "@readme/openapi-parser": "^2.5.0",
"@types/mapbox__rehype-prism": "^0.8.0", "@types/mapbox__rehype-prism": "^0.8.0",
"@types/mdx": "^2.0.5", "@types/mdx": "^2.0.5",

View File

@@ -15,7 +15,7 @@ export type CodeBlockActionsProps = {
inInnerCode?: boolean inInnerCode?: boolean
isCollapsed: boolean isCollapsed: boolean
canShowApiTesting?: boolean canShowApiTesting?: boolean
onApiTesting: React.Dispatch<React.SetStateAction<boolean>> onApiTesting?: React.Dispatch<React.SetStateAction<boolean>>
noReport?: boolean noReport?: boolean
noCopy?: boolean noCopy?: boolean
} }
@@ -91,7 +91,7 @@ export const CodeBlockActions = ({
inHeader && "p-[4.5px]", inHeader && "p-[4.5px]",
"cursor-pointer" "cursor-pointer"
)} )}
onClick={() => onApiTesting(true)} onClick={() => onApiTesting?.(true)}
> >
<PlaySolid className={clsx(iconClassName)} /> <PlaySolid className={clsx(iconClassName)} />
</span> </span>

View File

@@ -0,0 +1,46 @@
import clsx from "clsx"
import React, { useMemo } from "react"
import { useColorMode } from "../../../../providers"
import { CodeBlockStyle } from "../../../.."
type CodeBlockHeaderWrapperProps = {
blockStyle?: CodeBlockStyle
children: React.ReactNode
}
export const CodeBlockHeaderWrapper = React.forwardRef<
HTMLDivElement,
CodeBlockHeaderWrapperProps
>(function CodeBlockHeaderWrapper({ children, blockStyle = "loud" }, ref) {
const { colorMode } = useColorMode()
const bgColor = useMemo(
() =>
clsx(
blockStyle === "loud" && "bg-medusa-contrast-bg-base",
blockStyle === "subtle" && [
colorMode === "light" && "bg-medusa-bg-component",
colorMode === "dark" && "bg-medusa-code-bg-header",
]
),
[blockStyle, colorMode]
)
return (
<div
className={clsx(
"py-docs_0.5 px-docs_1 mb-0",
"rounded-t-docs_lg relative flex justify-between items-center",
blockStyle === "subtle" && [
"border border-solid border-b-0",
colorMode === "light" && "border-medusa-border-base",
colorMode === "dark" && "border-medusa-code-border",
],
bgColor
)}
ref={ref}
>
{children}
</div>
)
})

View File

@@ -6,6 +6,7 @@ import { CodeBlockStyle } from ".."
import { useColorMode } from "@/providers" import { useColorMode } from "@/providers"
import { Badge, BadgeVariant } from "@/components" import { Badge, BadgeVariant } from "@/components"
import { CodeBlockActions, CodeBlockActionsProps } from "../Actions" import { CodeBlockActions, CodeBlockActionsProps } from "../Actions"
import { CodeBlockHeaderWrapper } from "./Wrapper"
export type CodeBlockHeaderMeta = { export type CodeBlockHeaderMeta = {
badgeLabel?: string badgeLabel?: string
@@ -27,17 +28,6 @@ export const CodeBlockHeader = ({
}: CodeBlockHeaderProps) => { }: CodeBlockHeaderProps) => {
const { colorMode } = useColorMode() const { colorMode } = useColorMode()
const bgColor = useMemo(
() =>
clsx(
blockStyle === "loud" && "bg-medusa-contrast-bg-base",
blockStyle === "subtle" && [
colorMode === "light" && "bg-medusa-bg-component",
colorMode === "dark" && "bg-medusa-code-bg-header",
]
),
[blockStyle, colorMode]
)
const titleColor = useMemo( const titleColor = useMemo(
() => () =>
clsx( clsx(
@@ -51,18 +41,7 @@ export const CodeBlockHeader = ({
) )
return ( return (
<div <CodeBlockHeaderWrapper blockStyle={blockStyle}>
className={clsx(
"py-docs_0.5 px-docs_1 mb-0",
"rounded-t-docs_lg relative flex justify-between items-center",
blockStyle === "subtle" && [
"border border-solid border-b-0",
colorMode === "light" && "border-medusa-border-base",
colorMode === "dark" && "border-medusa-code-border",
],
bgColor
)}
>
<div className={clsx("flex-1", "flex gap-docs_0.75 items-start")}> <div className={clsx("flex-1", "flex gap-docs_0.75 items-start")}>
{badgeLabel && ( {badgeLabel && (
<Badge variant={badgeColor || "code"} className="font-base"> <Badge variant={badgeColor || "code"} className="font-base">
@@ -76,6 +55,6 @@ export const CodeBlockHeader = ({
)} )}
</div> </div>
<CodeBlockActions {...actionsProps} /> <CodeBlockActions {...actionsProps} />
</div> </CodeBlockHeaderWrapper>
) )
} }

View File

@@ -51,6 +51,7 @@ export type CodeBlockProps = {
collapsed?: boolean collapsed?: boolean
blockStyle?: CodeBlockStyle blockStyle?: CodeBlockStyle
children?: React.ReactNode children?: React.ReactNode
style?: React.HTMLAttributes<HTMLDivElement>["style"]
} & CodeBlockMetaFields & } & CodeBlockMetaFields &
Omit<HighlightProps, "code" | "language" | "children"> Omit<HighlightProps, "code" | "language" | "children">
@@ -71,6 +72,7 @@ export const CodeBlock = ({
collapsibleLines, collapsibleLines,
expandButtonLabel, expandButtonLabel,
isTerminal, isTerminal,
style,
...rest ...rest
}: CodeBlockProps) => { }: CodeBlockProps) => {
if (!source && typeof children === "string") { if (!source && typeof children === "string") {
@@ -92,10 +94,14 @@ export const CodeBlock = ({
: isTerminal : isTerminal
}, [isTerminal, lang]) }, [isTerminal, lang])
const codeTitle = useMemo(() => { const codeTitle = useMemo(() => {
if (title || hasTabs) { if (title) {
return title return title
} }
if (hasTabs) {
return ""
}
if (isTerminalCode) { if (isTerminalCode) {
return "Terminal" return "Terminal"
} }
@@ -329,6 +335,7 @@ export const CodeBlock = ({
!hasInnerCodeBlock && "rounded-docs_DEFAULT", !hasInnerCodeBlock && "rounded-docs_DEFAULT",
className className
)} )}
style={style}
> >
<Highlight <Highlight
theme={codeTheme} theme={codeTheme}
@@ -370,9 +377,6 @@ export const CodeBlock = ({
!hasInnerCodeBlock && !hasInnerCodeBlock &&
tokens.length <= 1 && tokens.length <= 1 &&
"px-docs_1 py-[6px]", "px-docs_1 py-[6px]",
!codeTitle.length &&
(!noCopy || !noReport) &&
"xs:max-w-[83%]",
(noLineNumbers || (noLineNumbers ||
(tokens.length <= 1 && !isTerminalCode)) && (tokens.length <= 1 && !isTerminalCode)) &&
"pl-docs_1", "pl-docs_1",

View File

@@ -10,6 +10,8 @@ import {
useTabs, useTabs,
} from "../.." } from "../.."
import clsx from "clsx" import clsx from "clsx"
import { CodeBlockActions, CodeBlockActionsProps } from "../CodeBlock/Actions"
import { CodeBlockHeaderWrapper } from "../CodeBlock/Header/Wrapper"
type CodeTab = BaseTabType & { type CodeTab = BaseTabType & {
codeProps: CodeBlockProps codeProps: CodeBlockProps
@@ -132,6 +134,23 @@ export const CodeTabs = ({
} }
}, [codeTabSelectorRef, tabRefs, changeTabSelectorCoordinates, selectedTab]) }, [codeTabSelectorRef, tabRefs, changeTabSelectorCoordinates, selectedTab])
const actionsProps: CodeBlockActionsProps | undefined = useMemo(() => {
if (!selectedTab) {
return
}
return {
source: selectedTab?.codeProps.source,
blockStyle,
noReport: selectedTab?.codeProps.noReport,
noCopy: selectedTab?.codeProps.noCopy,
inInnerCode: true,
showGradientBg: false,
inHeader: true,
isCollapsed: false,
}
}, [selectedTab])
return ( return (
<div <div
className={clsx( className={clsx(
@@ -142,16 +161,7 @@ export const CodeTabs = ({
className className
)} )}
> >
<div <CodeBlockHeaderWrapper blockStyle={blockStyle} ref={codeTabsWrapperRef}>
className={clsx(
"flex gap-docs_0.75 relative",
"pt-[10px] px-docs_1 pb-px",
blockStyle === "loud" &&
selectedTab?.codeProps.title &&
"border border-solid border-b border-medusa-contrast-border-bot"
)}
ref={codeTabsWrapperRef}
>
<span <span
className={clsx( className={clsx(
"xs:absolute xs:transition-all xs:duration-200 xs:ease-ease xs:bottom-0", "xs:absolute xs:transition-all xs:duration-200 xs:ease-ease xs:bottom-0",
@@ -198,7 +208,8 @@ export const CodeTabs = ({
{selectedTab.codeProps.badgeLabel} {selectedTab.codeProps.badgeLabel}
</Badge> </Badge>
)} )}
</div> {actionsProps && <CodeBlockActions {...actionsProps} />}
</CodeBlockHeaderWrapper>
{selectedTab?.codeBlock} {selectedTab?.codeBlock}
</div> </div>
) )

View File

@@ -3197,6 +3197,18 @@ __metadata:
languageName: node languageName: node
linkType: hard linkType: hard
"@react-hook/resize-observer@npm:^2.0.2":
version: 2.0.2
resolution: "@react-hook/resize-observer@npm:2.0.2"
dependencies:
"@react-hook/latest": ^1.0.2
"@react-hook/passive-layout-effect": ^1.2.0
peerDependencies:
react: ">=18"
checksum: a88f088bd5b87fea80daca391bdea9823dc38651bd112f0c607b057d9c8381f37395cf5a01a79ba7ab24369c4b48acf912cfef0244e6610d72ea3074415e9c32
languageName: node
linkType: hard
"@react-stately/datepicker@npm:^3.5.0, @react-stately/datepicker@npm:^3.9.2": "@react-stately/datepicker@npm:^3.5.0, @react-stately/datepicker@npm:^3.9.2":
version: 3.9.2 version: 3.9.2
resolution: "@react-stately/datepicker@npm:3.9.2" resolution: "@react-stately/datepicker@npm:3.9.2"
@@ -5553,6 +5565,7 @@ __metadata:
"@medusajs/ui": ^3.0.0 "@medusajs/ui": ^3.0.0
"@next/bundle-analyzer": ^14.2.14 "@next/bundle-analyzer": ^14.2.14
"@next/mdx": 14.2.14 "@next/mdx": 14.2.14
"@react-hook/resize-observer": ^2.0.2
"@readme/openapi-parser": ^2.5.0 "@readme/openapi-parser": ^2.5.0
"@types/jsdom": ^21.1.1 "@types/jsdom": ^21.1.1
"@types/mapbox__rehype-prism": ^0.8.0 "@types/mapbox__rehype-prism": ^0.8.0