/** * @typedef {import('mdx/types.js').MDXComponents} MDXComponents * @typedef {import('react').Component<{}, {}, unknown>} Component * @typedef {import('react').ReactNode} ReactNode */ /** * @callback MergeComponents * Custom merge function. * @param {Readonly} currentComponents * Current components from the context. * @returns {MDXComponents} * Additional components. * * @typedef Props * Configuration for `MDXProvider`. * @property {ReactNode | null | undefined} [children] * Children (optional). * @property {Readonly | MergeComponents | null | undefined} [components] * Additional components to use or a function that creates them (optional). * @property {boolean | null | undefined} [disableParentContext=false] * Turn off outer component context (default: `false`). */ import React from 'react' /** @type {Readonly} */ const emptyComponents = {} const MDXContext = React.createContext(emptyComponents) /** * Get current components from the MDX Context. * * @param {Readonly | MergeComponents | null | undefined} [components] * Additional components to use or a function that creates them (optional). * @returns {MDXComponents} * Current components. */ export function useMDXComponents(components) { const contextComponents = React.useContext(MDXContext) // Memoize to avoid unnecessary top-level context changes return React.useMemo( function () { // Custom merge via a function prop if (typeof components === 'function') { return components(contextComponents) } return {...contextComponents, ...components} }, [contextComponents, components] ) } /** * Provider for MDX context. * * @param {Readonly} properties * Properties. * @returns {JSX.Element} * Element. * @satisfies {Component} */ export function MDXProvider(properties) { /** @type {Readonly} */ let allComponents if (properties.disableParentContext) { allComponents = typeof properties.components === 'function' ? properties.components(emptyComponents) : properties.components || emptyComponents } else { allComponents = useMDXComponents(properties.components) } return React.createElement( MDXContext.Provider, {value: allComponents}, properties.children ) }