Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[docs] Update buildAPI script to handle the "styled" components #23370

Merged
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 35 additions & 0 deletions docs/pages/api-docs/slider-styled.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,9 @@ You can learn more about the difference by [reading this guide](/guides/minimizi



## Component name

The `MuiSlider` name can be used for providing [default props](/customization/globals/#default-props) or [style overrides](/customization/globals/#css) at the theme level.

## Props

Expand Down Expand Up @@ -56,6 +58,39 @@ The `ref` is forwarded to the root element.

Any other props supplied will be provided to the root element (native element).

## CSS

| Rule name | Global class | Description |
|:-----|:-------------|:------------|
| <span class="prop-name">root</span> | <span class="prop-name">.undefined</span> | Styles applied to the root element.
| <span class="prop-name">colorPrimary</span> | <span class="prop-name">.undefined</span> | Styles applied to the root element if `color="primary"`.
| <span class="prop-name">colorSecondary</span> | <span class="prop-name">.undefined</span> | Styles applied to the root element if `color="secondary"`.
| <span class="prop-name">marked</span> | <span class="prop-name">.undefined</span> | Styles applied to the root element if `marks` is provided with at least one label.
| <span class="prop-name">vertical</span> | <span class="prop-name">.undefined</span> | Pseudo-class applied to the root element if `orientation="vertical"`.
| <span class="prop-name">disabled</span> | <span class="prop-name">.undefined</span> | Pseudo-class applied to the root and thumb element if `disabled={true}`.
| <span class="prop-name">rail</span> | <span class="prop-name">.undefined</span> | Styles applied to the rail element.
| <span class="prop-name">track</span> | <span class="prop-name">.undefined</span> | Styles applied to the track element.
| <span class="prop-name">trackFalse</span> | <span class="prop-name">.undefined</span> | Styles applied to the track element if `track={false}`.
| <span class="prop-name">trackInverted</span> | <span class="prop-name">.undefined</span> | Styles applied to the track element if `track="inverted"`.
| <span class="prop-name">thumb</span> | <span class="prop-name">.undefined</span> | Styles applied to the thumb element.
| <span class="prop-name">thumbColorPrimary</span> | <span class="prop-name">.undefined</span> | Styles applied to the thumb element if `color="primary"`.
| <span class="prop-name">thumbColorSecondary</span> | <span class="prop-name">.undefined</span> | Styles applied to the thumb element if `color="secondary"`.
| <span class="prop-name">active</span> | <span class="prop-name">.undefined</span> | Pseudo-class applied to the thumb element if it's active.
| <span class="prop-name">focusVisible</span> | <span class="prop-name">.undefined</span> | Pseudo-class applied to the thumb element if keyboard focused.
| <span class="prop-name">valueLabel</span> | <span class="prop-name">.undefined</span> | Styles applied to the thumb label element.
| <span class="prop-name">mark</span> | <span class="prop-name">.undefined</span> | Styles applied to the mark element.
| <span class="prop-name">markActive</span> | <span class="prop-name">.undefined</span> | Styles applied to the mark element if active (depending on the value).
| <span class="prop-name">markLabel</span> | <span class="prop-name">.undefined</span> | Styles applied to the mark label element.
| <span class="prop-name">markLabelActive</span> | <span class="prop-name">.undefined</span> | Styles applied to the mark label element if active (depending on the value).

You can override the style of the component thanks to one of these customization points:

- With a rule name of the [`classes` object prop](/customization/components/#overriding-styles-with-classes).
- With a [global class name](/customization/components/#overriding-styles-with-global-class-names).
- With a theme and an [`overrides` property](/customization/globals/#css).

If that's not sufficient, you can check the [implementation of the component](https://github.com/mui-org/material-ui/blob/next/packages/material-ui-lab/src/SliderStyled/SliderStyled.js) for more detail.

## Demos

- [Slider Styled](/components/slider-styled/)
Expand Down
77 changes: 74 additions & 3 deletions docs/scripts/buildApi.ts
Original file line number Diff line number Diff line change
Expand Up @@ -134,8 +134,8 @@ async function annotateComponentDefinition(context: {
}

const { leadingComments } = node;
const jsdocBlock = leadingComments != null ? leadingComments[0] : null;
if (leadingComments != null && leadingComments.length > 1) {
const jsdocBlock = leadingComments !== null ? leadingComments[0] : null;
mnajdova marked this conversation as resolved.
Show resolved Hide resolved
if (leadingComments !== null && leadingComments.length > 1) {
mnajdova marked this conversation as resolved.
Show resolved Hide resolved
throw new Error('Should only have a single leading jsdoc block');
}
if (jsdocBlock != null) {
Expand Down Expand Up @@ -192,6 +192,71 @@ async function annotateComponentDefinition(context: {
writeFileSync(typesFilename, typesSourceNew, { encoding: 'utf8' });
}

function trimComment(comment: string) {
let i = 0;
for (; i < comment.length; i++) {
if (comment[i] !== '*' && comment[i] !== ' ') {
break;
}
}
return comment.substr(i, comment.length - 1);
}

async function updateStylesDefinition(context: { api: ReactApi; component: { filename: string } }) {
const { api, component } = context;

const typesFilename = component.filename.replace(/\.js$/, '.d.ts');
const typesSource = readFileSync(typesFilename, { encoding: 'utf8' });
const typesAST = await babel.parseAsync(typesSource, {
configFile: false,
filename: typesFilename,
presets: [require.resolve('@babel/preset-typescript')],
});

if (typesAST === null) {
throw new Error('No AST returned from babel.');
}

if (api.styles.classes.length === 0) {
const componentName = path.basename(typesFilename).replace(/\.d\.ts$/, '');

(typesAST as any).program.body.forEach((node: any) => {
mnajdova marked this conversation as resolved.
Show resolved Hide resolved
oliviertassinari marked this conversation as resolved.
Show resolved Hide resolved
const name = node.type === 'ExportNamedDeclaration' ? node?.declaration?.id?.name : undefined;
if (name === `${componentName}ClassKey` && node.declaration.typeAnnotation.types) {
const classes = node.declaration.typeAnnotation.types.map(
(node: babel.types.TSLiteralType) => node.literal.value,
);

const nodeLeadingComments = node.declaration.typeAnnotation.leadingComments || [];

node.declaration.typeAnnotation.types.forEach(
(typeNode: babel.types.TSLiteralType, idx: number) => {
let leadingComments = typeNode.leadingComments;
if (idx === 0) {
if (leadingComments) {
leadingComments = leadingComments.concat(nodeLeadingComments);
} else {
leadingComments = nodeLeadingComments;
}
}
if (leadingComments) {
for (let i = 0; i < leadingComments.length; i++) {
if (leadingComments[i].end + 6 === typeNode.literal.start) {
api.styles.descriptions[typeNode.literal.value as string] = trimComment(
leadingComments[i].value,
);
}
}
}
return '';
},
);
api.styles.classes = classes;
}
});
}
}

async function annotateClassesDefinition(context: {
api: ReactApi;
component: { filename: string };
Expand Down Expand Up @@ -300,12 +365,13 @@ async function buildDocs(options: {
globalClasses: {},
};

styles.name = component?.default?.options?.name;

if (component.styles && component.default.options) {
// Collect the customization points of the `classes` property.
styles.classes = Object.keys(getStylesCreator(component.styles).create(theme)).filter(
(className) => !className.match(/^(@media|@keyframes|@global)/),
);
styles.name = component.default.options.name;
styles.globalClasses = styles.classes.reduce((acc, key) => {
acc[key] = generateClassName(
// @ts-expect-error
Expand Down Expand Up @@ -376,6 +442,11 @@ async function buildDocs(options: {
reactAPI.filename = componentObject.filename.replace(workspaceRoot, '');
reactAPI.inheritance = getInheritance(testInfo, src);

await updateStylesDefinition({
api: reactAPI,
component: componentObject,
});

let markdown;
try {
markdown = generateMarkdown(reactAPI);
Expand Down
42 changes: 42 additions & 0 deletions packages/material-ui-lab/src/SliderStyled/SliderStyled.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -48,4 +48,46 @@ export const SliderValueLabel: React.FC<SliderValueLabel>;
*/
declare const Slider: ExtendSliderUnstyled<SliderStyledTypeMap>;

export type SliderStyledClassKey =
eps1lon marked this conversation as resolved.
Show resolved Hide resolved
/** Styles applied to the root element. */
mnajdova marked this conversation as resolved.
Show resolved Hide resolved
| 'root'
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This won't do anything. JSDOC for literals is ignored: microsoft/TypeScript#25499.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Aha, now I understand why I didn't have these on the node directly, so I had to iterate all leadingComments and see which one is right before the specific classKey - see #23370 (comment) I am open to other ideas of how to do this.

/** Styles applied to the root element if `color="primary"`. */
| 'colorPrimary'
/** Styles applied to the root element if `color="secondary"`. */
| 'colorSecondary'
/** Styles applied to the root element if `marks` is provided with at least one label. */
| 'marked'
/** Pseudo-class applied to the root element if `orientation="vertical"`. */
mnajdova marked this conversation as resolved.
Show resolved Hide resolved
| 'vertical'
/** Pseudo-class applied to the root and thumb element if `disabled={true}`. */
| 'disabled'
/** Styles applied to the rail element. */
| 'rail'
/** Styles applied to the track element. */
| 'track'
/** Styles applied to the track element if `track={false}`. */
| 'trackFalse'
/** Styles applied to the track element if `track="inverted"`. */
| 'trackInverted'
/** Styles applied to the thumb element. */
| 'thumb'
/** Styles applied to the thumb element if `color="primary"`. */
| 'thumbColorPrimary'
oliviertassinari marked this conversation as resolved.
Show resolved Hide resolved
/** Styles applied to the thumb element if `color="secondary"`. */
| 'thumbColorSecondary'
/** Pseudo-class applied to the thumb element if it's active. */
| 'active'
/** Pseudo-class applied to the thumb element if keyboard focused. */
| 'focusVisible'
/** Styles applied to the thumb label element. */
| 'valueLabel'
/** Styles applied to the mark element. */
| 'mark'
/** Styles applied to the mark element if active (depending on the value). */
| 'markActive'
/** Styles applied to the mark label element. */
| 'markLabel'
/** Styles applied to the mark label element if active (depending on the value). */
| 'markLabelActive';

export default Slider;
4 changes: 4 additions & 0 deletions packages/material-ui-lab/src/SliderStyled/SliderStyled.js
Original file line number Diff line number Diff line change
Expand Up @@ -303,6 +303,10 @@ const Slider = React.forwardRef(function Slider(inputProps, ref) {
);
});

Slider.options = {
mnajdova marked this conversation as resolved.
Show resolved Hide resolved
eps1lon marked this conversation as resolved.
Show resolved Hide resolved
name: 'MuiSlider',
};

Slider.propTypes = {
// ----------------------------- Warning --------------------------------
// | These PropTypes are generated from the TypeScript type definitions |
Expand Down