@workday/canvas-kit-docs
Version:
Documentation components of Canvas Kit components
138 lines (137 loc) • 7.33 kB
JavaScript
import React from 'react';
import { Expandable } from '@workday/canvas-kit-labs-react/expandable';
import { defaultJSDoc } from '../../docgen/docParser';
import { MDX } from '../MDXElements';
import { SymbolDoc } from '../SymbolDoc';
import { PropertiesTable, registerWidget, Value } from '../Value';
import { Heading, HeadingLevelContext, SymbolDialog } from '../widgetUtils';
const ParentComponentNameContext = React.createContext('');
/**
* Used to keep track of JSDoc in subcomponent definitions.
*
* For example:
* ```tsx
* subComponents: {
* // JSDoc goes here instead of on `TabsItem` for better dev experience
* Item: TabsItem
* }
* ```
*/
const ParentComponentJSDocContext = React.createContext(defaultJSDoc);
const fileNameToCategoryMap = {
Layout: [
'utils/layout',
'utils/gridArea',
'utils/gridItem',
'utils/flexItem',
'utils/position',
'utils/space',
],
Color: ['utils/color', 'utils/background'],
Border: ['utils/border'],
Depth: ['utils/depth'],
Text: ['utils/text'],
Other: ['utils/other'],
};
registerWidget('enhancedComponent', ({ value, doc, meta }) => {
var _a, _b, _c;
const groups = groupProps(value.props);
const parentComponentName = React.useContext(ParentComponentNameContext);
const headingLevel = React.useContext(HeadingLevelContext);
// We don't want to re-document a subcomponent that is a container component with a different
// model. If we detect another container, only render the intro and a link to the container
// component
if (parentComponentName && value.componentType === 'container') {
return (React.createElement(React.Fragment, null,
React.createElement(MDX, { as: "p" },
"This component references the",
' ',
React.createElement(ParentComponentNameContext.Provider, { value: "" },
React.createElement(ParentComponentJSDocContext.Provider, { value: defaultJSDoc },
React.createElement(SymbolDialog, { value: { kind: 'symbol', name: value.displayName || '' } }))),
' ',
"component.")));
}
return (React.createElement(React.Fragment, null,
value.styleComponent ? (React.createElement(React.Fragment, null,
React.createElement(Heading, { headingOffset: 1, id: parentComponentName
? `${parentComponentName.toLowerCase()}-layout-component-api`
: `${(_a = value.displayName) === null || _a === void 0 ? void 0 : _a.toLowerCase()}-layout-component-api` }, "Layout Component"),
React.createElement(MDX, { as: "p" },
React.createElement("code", null, value.displayName || parentComponentName),
" supports all props from the",
React.createElement("code", null,
React.createElement(ParentComponentJSDocContext.Provider, { value: defaultJSDoc },
React.createElement(SymbolDialog, { value: value.styleComponent }))),
"layout component."))) : null,
React.createElement(Heading, { headingOffset: 1, id: parentComponentName
? `${parentComponentName.toLowerCase()}-props-api`
: `${(_b = value.displayName) === null || _b === void 0 ? void 0 : _b.toLowerCase()}-props-api` }, "Props"),
value.baseElement && (React.createElement(ParentComponentJSDocContext.Provider, { value: defaultJSDoc },
React.createElement(MDX, { as: "p" },
"Props extend from ",
React.createElement(Value, { value: value.baseElement }),
". Changing the ",
React.createElement("code", null, "as"),
" prop will change the element interface."))),
value.componentType === 'container' && value.model ? (React.createElement(MDX, { as: "p" },
"Props extend from ",
React.createElement(SymbolDialog, { value: { kind: 'symbol', name: `${value.model}Config` } }),
". If a ",
React.createElement("code", null, "model"),
" is passed, props from ",
React.createElement("code", null,
value.model,
"Config"),
" are ignored.")) : null,
Object.keys(groups).map(key => {
return (React.createElement(React.Fragment, { key: key }, key === 'Local' ? (React.createElement(PropertiesTable, { properties: groups[key] })) : (React.createElement(Expandable, null,
React.createElement(Expandable.Target, { headingLevel: "h5" },
React.createElement(Expandable.Title, null, key),
React.createElement(Expandable.Icon, { iconPosition: "end" })),
React.createElement(Expandable.Content, null,
React.createElement(PropertiesTable, { properties: groups[key] }))))));
}),
value.elemPropsHook ? (React.createElement(SymbolDoc, { name: value.elemPropsHook, headingStart: headingLevel + 1 })) : null,
value.subComponents
? value.subComponents.map((c, i) => {
var _a;
return (React.createElement(React.Fragment, { key: i },
React.createElement(Heading, { id: `${(_a = value.displayName) === null || _a === void 0 ? void 0 : _a.toLowerCase()}.${c.name.toLowerCase()}-api` },
parentComponentName ? parentComponentName : value.displayName,
".",
c.name),
React.createElement(ParentComponentNameContext.Provider, { value: `${parentComponentName ? parentComponentName : value.displayName}.${c.name}` },
React.createElement(ParentComponentJSDocContext.Provider, { value: c },
React.createElement(SymbolDoc, { name: c.symbol, fileName: c.declarations[c.declarations.length - 1].filePath, hideHeading: true, descriptionOverride: c.description })))));
})
: null,
value.componentType === 'container' && value.model ? (React.createElement(React.Fragment, null,
React.createElement(Heading, { id: `${(_c = value.displayName) === null || _c === void 0 ? void 0 : _c.toLowerCase()}-model-api`, headingOffset: -1 }, "Model"),
React.createElement(SymbolDoc, { name: `use${value.model}` }))) : null));
});
function groupProps(props) {
const categories = { Local: [] };
for (const key in fileNameToCategoryMap) {
categories[key] = [];
}
for (const prop of props) {
let found = false;
for (const key in fileNameToCategoryMap) {
if (fileNameToCategoryMap[key].find(match => { var _a; return (_a = prop.declarations[0]) === null || _a === void 0 ? void 0 : _a.filePath.includes(match); })) {
found = true;
categories[key].push(prop);
}
}
if (!found) {
categories.Local.push(prop);
}
}
// clear out categories that don't have anything in them
return Object.keys(categories).reduce((result, key) => {
if (categories[key].length) {
result[key] = categories[key];
}
return result;
}, {});
}