@mui/internal-docs-infra
Version:
MUI Infra - internal documentation creation tools.
122 lines (120 loc) • 3.65 kB
JavaScript
'use client';
import * as React from 'react';
import { useTypesDataContext } from "../useType/TypesDataContext.mjs";
import { toKebabCase } from "../pipeline/loaderUtils/toKebabCase.mjs";
/**
* Collects the properties from an EnhancedTypesMeta entry into key/data pairs.
* - Component types: extracts `data.props`
* - Hook/function types: extracts `data.expandedProperties` (the expanded properties of the options object)
*/
function collectTypeProps(typeMeta) {
const slug = typeMeta.slug ?? typeMeta.name.toLowerCase();
const entries = [];
const names = [typeMeta.name, ...(typeMeta.aliases ?? [])];
function addProperties(props) {
for (const [propName, prop] of Object.entries(props)) {
const data = {
property: prop,
href: `#${slug}:${toKebabCase(propName)}`
};
for (const name of names) {
entries.push({
key: `${name}:${propName}`,
data
});
}
}
}
if (typeMeta.type === 'component') {
addProperties(typeMeta.data.props);
} else if (typeMeta.type === 'hook' || typeMeta.type === 'function') {
if (typeMeta.data.expandedProperties) {
addProperties(typeMeta.data.expandedProperties);
}
} else if (typeMeta.type === 'raw') {
if (typeMeta.data.properties) {
addProperties(typeMeta.data.properties);
}
}
return entries;
}
/**
* Hook for accessing types props in TypesTable components.
*
* When rendered inside a `TypesDataProvider`, automatically registers
* the main type and additional types into the context so they can be
* looked up by name via `useType(name)`, and registers their properties
* so they can be looked up via `useTypeProp(typeName, propName)`.
*/
export function useTypes(contentProps) {
const context = useTypesDataContext();
const registerTypes = context?.registerTypes;
const registerTypeProps = context?.registerTypeProps;
const {
type,
additionalTypes
} = contentProps;
React.useEffect(() => {
if (!registerTypes) {
return;
}
const entries = [];
if (type) {
const typeData = {
meta: type,
href: type.slug ? `#${type.slug}` : `#${type.name.toLowerCase()}`
};
entries.push({
name: type.name,
data: typeData
});
// Also register under alias names (e.g., flat export name like "AccordionRootProps")
if (type.aliases) {
for (const alias of type.aliases) {
entries.push({
name: alias,
data: typeData
});
}
}
}
for (const additional of additionalTypes) {
const additionalData = {
meta: additional,
href: additional.slug ? `#${additional.slug}` : `#${additional.name.toLowerCase()}`
};
entries.push({
name: additional.name,
data: additionalData
});
// Also register under alias names
if (additional.aliases) {
for (const alias of additional.aliases) {
entries.push({
name: alias,
data: additionalData
});
}
}
}
if (entries.length > 0) {
registerTypes(entries);
}
}, [registerTypes, type, additionalTypes]);
React.useEffect(() => {
if (!registerTypeProps) {
return;
}
const propEntries = [];
if (type) {
propEntries.push(...collectTypeProps(type));
}
for (const additional of additionalTypes) {
propEntries.push(...collectTypeProps(additional));
}
if (propEntries.length > 0) {
registerTypeProps(propEntries);
}
}, [registerTypeProps, type, additionalTypes]);
return contentProps;
}