diff --git a/packages/demo/src/components/Transition/demo/Base.tsx b/packages/demo/src/components/Transition/demo/Base.tsx
index 99e5b8a..ff59922 100644
--- a/packages/demo/src/components/Transition/demo/Base.tsx
+++ b/packages/demo/src/components/Transition/demo/Base.tsx
@@ -1,4 +1,4 @@
-import { Transition } from 'pivot-design';
+import { Button, Transition } from 'pivot-design';
import React, { useState } from 'react';
import './index.scss';
@@ -19,7 +19,7 @@ const App: React.FC = () => {
};
return (
-
+
{(state: any) => {
return (
@@ -35,13 +35,13 @@ const App: React.FC = () => {
);
}}
-
+
);
};
diff --git a/packages/demo/src/components/Transition/demo/CSSTransition.tsx b/packages/demo/src/components/Transition/demo/CSSTransition.tsx
index 0308c19..1290681 100644
--- a/packages/demo/src/components/Transition/demo/CSSTransition.tsx
+++ b/packages/demo/src/components/Transition/demo/CSSTransition.tsx
@@ -1,26 +1,54 @@
-import { CSSTransiton as MyCSSTransition } from 'pivot-design';
+import { Button, CSSTransiton } from 'pivot-design';
import React, { useState } from 'react';
-
import './index.scss';
-
-// const App: React.FC = () => {};
-
const App: React.FC = () => {
- const [inProp, setInProp] = useState(false);
+ const [showButton, setShowButton] = useState(true);
+ const [showMessage, setShowMessage] = useState(false);
return (
<>
-
- {"I'll receive my-node-* classes"}
-
-
+ {showButton && (
+
+ )}
+
setShowButton(false)}
+ onExited={() => setShowButton(true)}
+ >
+
+
出现的标题
+
文本内容在消失时会自动卸载,出现时挂载
+
+
+
>
);
};
-// 第一次点击按钮时 ,通过审查元素可以看到 div#test 标签的类名发生了变化,
-// 依次为 “my-node-enter”、“my-node-enter my-node-enter-active” >>>(2s later) “my-node-enter-done”
-
-// 第二次点击按钮时,通过审查元素可以看到 div#test 标签的类名发生了变化,
-// 依次为 “my-node-exit”、“my-node-exit my-node-exit-active” >>> (2s later) “my-node-exit-done”
export default App;
+
+/** css样式
+ .show-box {
+ opacity: 0;
+ &-enter {
+ opacity: 0;
+ transform: scale(0.9);
+ }
+ &-enter-active {
+ opacity: 1;
+ transform: translateX(0);
+ transition: opacity 500ms, transform 500ms;
+ }
+ &-exit {
+ opacity: 1;
+ }
+ &-exit-active {
+ opacity: 0;
+ transform: scale(0.9);
+ transition: opacity 500ms, transform 500ms;
+ }
+ }
+*/
diff --git a/packages/demo/src/components/Transition/demo/Callback.tsx b/packages/demo/src/components/Transition/demo/Callback.tsx
index 48131a9..b3cf4bd 100644
--- a/packages/demo/src/components/Transition/demo/Callback.tsx
+++ b/packages/demo/src/components/Transition/demo/Callback.tsx
@@ -16,7 +16,7 @@ const App: React.FC = () => {
exited: { opacity: 0 },
};
return (
-
+
{
exited: { opacity: 0, transition: `opacity ${duration}ms` },
};
return (
-
+
{(state: any) => {
return (
diff --git a/packages/demo/src/components/Transition/demo/Unmount.tsx b/packages/demo/src/components/Transition/demo/Unmount.tsx
index 6ac41bb..cc53009 100644
--- a/packages/demo/src/components/Transition/demo/Unmount.tsx
+++ b/packages/demo/src/components/Transition/demo/Unmount.tsx
@@ -19,7 +19,7 @@ const App: React.FC = () => {
};
return (
-
+
{(state: any) => {
return (
diff --git a/packages/demo/src/components/Transition/demo/index.scss b/packages/demo/src/components/Transition/demo/index.scss
index 6cd7b89..cd86761 100644
--- a/packages/demo/src/components/Transition/demo/index.scss
+++ b/packages/demo/src/components/Transition/demo/index.scss
@@ -1,13 +1,26 @@
@import '../../common.scss';
-button {
- margin: 20px;
- padding: 3px 15px;
- background-color: #fff;
- border: 1px solid black;
- border-radius: 5px;
- cursor: pointer;
-}
.show-box {
height: 20px;
}
+
+.css-show-box {
+ opacity: 0;
+ &-enter {
+ opacity: 0;
+ transform: scale(0.9);
+ }
+ &-enter-active {
+ opacity: 1;
+ transform: translateX(0);
+ transition: opacity 500ms, transform 500ms;
+ }
+ &-exit {
+ opacity: 1;
+ }
+ &-exit-active {
+ opacity: 0;
+ transform: scale(0.9);
+ transition: opacity 500ms, transform 500ms;
+ }
+}
diff --git a/packages/demo/src/components/Transition/index.mdx b/packages/demo/src/components/Transition/index.mdx
index 71f69a4..bf6fae4 100644
--- a/packages/demo/src/components/Transition/index.mdx
+++ b/packages/demo/src/components/Transition/index.mdx
@@ -1,5 +1,5 @@
# Popover
-css
+CSSTransition使用
diff --git a/packages/demo/src/pages/component/index.tsx b/packages/demo/src/pages/component/index.tsx
index 9884e8f..bb58f26 100644
--- a/packages/demo/src/pages/component/index.tsx
+++ b/packages/demo/src/pages/component/index.tsx
@@ -22,7 +22,7 @@ import { list as TransitionList } from '../../components/Transition/.catalog';
import './index.scss';
function Index() {
- const [select, setSelect] = useState('Switch');
+ const [select, setSelect] = useState('Transition');
const demoSelect = () => {
return (
diff --git a/packages/design-props/components/transition.ts b/packages/design-props/components/transition.ts
index 4a8e634..4c56f58 100644
--- a/packages/design-props/components/transition.ts
+++ b/packages/design-props/components/transition.ts
@@ -4,16 +4,17 @@ import React from 'react';
export type timeoutType = number | { enter?: number, exit?: number, appear?: number };
export interface TransitionPropTypes {
+ /**
+ * @version 1.0.0
+ * @description 动画绑定的元素
+ */
+ nodeRef?: React.RefObject
;
/**
* @version 1.0.0
* @description 用来控制进场、出场状态切换
* @default true
*/
in?: boolean;
- /**
- * 子组件,是一个函数或者ReactNode,
- * 如果为函数时其接受参数为刚刚介绍到的entering、entered 、exiting、exited 四个状态值
- */
/**
* @version 1.0.0
* @description 子组件,是一个函数或者ReactNode,如果为函数时其接受参数为entering、entered 、exiting、exited
@@ -57,37 +58,51 @@ export interface TransitionPropTypes {
/**
* @version 1.0.0
* @description 进场动画执行前调用回调函数
- * @default () => {}
*/
- onEnter?: (node?: Element | null, isAppearing?: boolean) => void;
+ onEnter?: (node?: HTMLElement | null, isAppearing?: boolean) => void;
/**
* @version 1.0.0
* @description 进场动画执行中调用
- * @default () => {}
*/
- onEntering?: (node?: Element | null, isAppearing?: boolean) => void;
+ onEntering?: (node?: HTMLElement | null, isAppearing?: boolean) => void;
/**
* @version 1.0.0
* @description 进场动画执行完毕调用
- * @default () => {}
*/
- onEntered?: (node?: Element | null, isAppearing?: boolean) => void;
+ onEntered?: (node?: HTMLElement | null, isAppearing?: boolean) => void;
/**
* @version 1.0.0
* @description 退场动画开始执行时调用
- * @default () => {}
*/
- onExit?: (node?: Element | null) => void;
+ onExit?: (node?: HTMLElement | null) => void;
/**
* @version 1.0.0
* @description 退场动画执行中时调用
- * @default () => {}
*/
- onExiting?: (node?: Element | null) => void;
+ onExiting?: (node?: HTMLElement | null) => void;
/**
* @version 1.0.0
* @description 退场动画执行完毕调用
- * @default () => {}
*/
- onExited?: (node?: Element | null) => void;
+ onExited?: (node?: HTMLElement | null) => void;
+}
+
+export interface CSSTransitionPropsTypes extends TransitionPropTypes {
+ /**
+ * @version 1.0.0
+ * @description class类型,可以传入对应的class类名,在元素不同阶段会自动变更
+ */
+ classNames?:
+ | string
+ | {
+ appear?: string,
+ appearActive?: string,
+ appearDone?: string,
+ enter?: string,
+ enterActive?: string,
+ enterDone?: string,
+ exit?: string,
+ exitActive?: string,
+ exitDone?: string,
+ };
}
diff --git a/packages/design/components/Transition/CSSTransiton.tsx b/packages/design/components/Transition/CSSTransiton.tsx
index eb9e08c..2fc10f0 100644
--- a/packages/design/components/Transition/CSSTransiton.tsx
+++ b/packages/design/components/Transition/CSSTransiton.tsx
@@ -1,92 +1,84 @@
-import { useState } from 'react';
-import PropTypes from 'prop-types';
-import { addOneClass, removeOneClass } from '../utils/domClass';
-// import Transition from './Transition';
+import { forceReflow, removeClass, addClass } from '../utils/domClass';
import Transition from './index';
+import useStateRef from '../utils/useStateRef';
+import { CSSTransitionPropsTypes } from 'pivot-design-props';
-import { classNamesShape } from '../utils/PropTypes';
-
-const forceReflow = (node: any) => node.scrollTop;
-const addClassF = (node: any, classes: any) =>
- node && classes && classes.split(' ').forEach((c: any) => addOneClass(node, c));
-const removeClass = (node: any, classes: any) =>
- node && classes && classes.split(' ').forEach((c: any) => removeOneClass(node, c));
-
-const CSSTransition: any = (props: any) => {
- const [appliedClasses, setAppliedClasses] = useState({
+const CSSTransition: React.FC = (props) => {
+ const [, setAppliedClasses, appliedClassesRef] = useStateRef({
appear: {},
enter: {},
exit: {},
});
- const onEnter = (maybeNode: any, maybeAppearing: any) => {
- const [node, appearing] = resolveArguments(maybeNode, maybeAppearing);
+ const onEnter = (maybeNode: HTMLElement, maybeAppearing?: boolean) => {
+ const [node, appearing] = [maybeNode, maybeAppearing];
removeClasses(node, 'exit');
- addClass(node, appearing ? 'appear' : 'enter', 'base');
+ addClasses(node, appearing ? 'appear' : 'enter', 'base');
if (props.onEnter) {
props.onEnter(maybeNode, maybeAppearing);
}
};
- const onEntering = (maybeNode: any, maybeAppearing: any) => {
+ const onEntering = (maybeNode: HTMLElement, maybeAppearing?: boolean) => {
const [node, appearing] = resolveArguments(maybeNode, maybeAppearing);
const type = appearing ? 'appear' : 'enter';
- addClass(node, type, 'active');
+ addClasses(node, type, 'active');
if (props.onEntering) {
props.onEntering(maybeNode, maybeAppearing);
}
};
- const onEntered = (maybeNode: any, maybeAppearing: any) => {
+ const onEntered = (maybeNode: HTMLElement, maybeAppearing: boolean) => {
const [node, appearing] = resolveArguments(maybeNode, maybeAppearing);
const type = appearing ? 'appear' : 'enter';
removeClasses(node, type);
- addClass(node, type, 'done');
+ addClasses(node, type, 'done');
if (props.onEntered) {
props.onEntered(maybeNode, maybeAppearing);
}
};
- const onExit = (maybeNode: any) => {
+ const onExit = (maybeNode: HTMLElement) => {
const [node] = resolveArguments(maybeNode);
removeClasses(node, 'appear');
removeClasses(node, 'enter');
- addClass(node, 'exit', 'base');
+ addClasses(node, 'exit', 'base');
if (props.onExit) {
props.onExit(maybeNode);
}
};
- const onExiting = (maybeNode: any) => {
+ const onExiting = (maybeNode: HTMLElement) => {
const [node] = resolveArguments(maybeNode);
- addClass(node, 'exit', 'active');
+ addClasses(node, 'exit', 'active');
if (props.onExiting) {
props.onExiting(maybeNode);
}
};
- const onExited = (maybeNode: any) => {
+ const onExited = (maybeNode: HTMLElement) => {
const [node] = resolveArguments(maybeNode);
removeClasses(node, 'exit');
- addClass(node, 'exit', 'done');
+ addClasses(node, 'exit', 'done');
if (props.onExited) {
props.onExited(maybeNode);
}
};
- const resolveArguments = (maybeNode: any, maybeAppearing: any = null) =>
+ // 如果外层绑定了ref,就使用外层传入的nodeRef
+ const resolveArguments = (maybeNode: HTMLElement, maybeAppearing?: boolean) =>
props.nodeRef
- ? [props.nodeRef.current, maybeNode] // here `maybeNode` is actually `appearing`
- : [maybeNode, maybeAppearing]; // `findDOMNode` was used
+ ? ([props.nodeRef.current, maybeNode] as unknown as [HTMLElement, boolean])
+ : ([maybeNode, maybeAppearing] as [HTMLElement, boolean]);
- const getClassNames = (type: any) => {
- const { classNames } = props;
+ const getClassNames = (type: string) => {
+ const { classNames = '' } = props;
const isStringClassNames = typeof classNames === 'string';
const prefix = isStringClassNames && classNames ? `${classNames}-` : '';
@@ -103,7 +95,8 @@ const CSSTransition: any = (props: any) => {
};
};
- const addClass = (node: any, type: any, phase: any = '') => {
+ // 添加对应的类型
+ const addClasses = (node: HTMLElement, type: string, phase = '') => {
let className = getClassNames(type)[`${phase}ClassName`];
const { doneClassName } = getClassNames('enter');
@@ -111,31 +104,37 @@ const CSSTransition: any = (props: any) => {
className += ` ${doneClassName}`;
}
- // This is to force a repaint,
- // which is necessary in order to transition styles when adding a class name.
+ // 强制刷新
if (phase === 'active') {
if (node) forceReflow(node);
}
if (className) {
- setAppliedClasses((prevAppliedClasses) => ({
- ...prevAppliedClasses,
- [type]: {
- ...prevAppliedClasses[type],
- [phase]: className,
- },
- }));
- addClassF(node, className);
+ setAppliedClasses((prevAppliedClasses) => {
+ return {
+ ...prevAppliedClasses,
+ [type]: {
+ ...prevAppliedClasses[type],
+ [phase]: className,
+ },
+ };
+ });
+ addClass(node, className);
}
+ //
};
- const removeClasses = (node: any, type: any) => {
- const { base: baseClassName, active: activeClassName, done: doneClassName } = appliedClasses[type];
+ // 移除所有class
+ const removeClasses = (node: HTMLElement, type: string) => {
+ const newAppliedClasses = appliedClassesRef.current || {};
+ const { base: baseClassName, active: activeClassName, done: doneClassName } = newAppliedClasses[type];
- setAppliedClasses((prevAppliedClasses) => ({
- ...prevAppliedClasses,
- [type]: {},
- }));
+ setAppliedClasses((prevAppliedClasses) => {
+ return {
+ ...prevAppliedClasses,
+ [type]: {},
+ };
+ });
if (baseClassName) {
removeClass(node, baseClassName);
@@ -163,22 +162,4 @@ const CSSTransition: any = (props: any) => {
);
};
-CSSTransition.propTypes = {
- ...Transition.propTypes,
-
- classNames: classNamesShape,
-
- onEnter: PropTypes.func,
-
- onEntering: PropTypes.func,
-
- onEntered: PropTypes.func,
-
- onExit: PropTypes.func,
-
- onExiting: PropTypes.func,
-
- onExited: PropTypes.func,
-};
-
export default CSSTransition;
diff --git a/packages/design/components/utils/domClass.ts b/packages/design/components/utils/domClass.ts
index aa463be..a0b0c80 100644
--- a/packages/design/components/utils/domClass.ts
+++ b/packages/design/components/utils/domClass.ts
@@ -1,11 +1,13 @@
+// 检查给定的 DOM 元素是否包含给定的类名
function hasClass(element: Element, className: string): boolean {
if (element.classList) {
return !!className && element.classList.contains(className);
}
- return ` ${element.className.baseVal || element.className} `.indexOf(` ${className} `) !== -1;
+ return ` ${element.className} `.indexOf(` ${className} `) !== -1;
}
-export function addOneClass(element: Element, className: string): void {
+// 将给定的类名添加到给定的 DOM 元素上
+function addOneClass(element: Element, className: string): void {
if (element.classList) {
element.classList.add(className);
} else if (!hasClass(element, className)) {
@@ -13,7 +15,8 @@ export function addOneClass(element: Element, className: string): void {
}
}
-export function removeOneClass(element: Element, className: string): void {
+// DOM 元素移除类名
+function removeOneClass(element: Element, className: string): void {
if (element.classList) {
element.classList.remove(className);
} else {
@@ -23,3 +26,14 @@ export function removeOneClass(element: Element, className: string): void {
.replace(/^\s*|\s*$/g, '');
}
}
+
+// 强制浏览器重新计算元素的布局
+export const forceReflow = (node: { scrollTop: number }) => node.scrollTop;
+
+// 添加类名到 dom 元素
+export const addClass = (node: HTMLElement, classes: string) =>
+ node && classes && classes.split(' ').forEach((c: any) => addOneClass(node, c));
+
+// 从 dom 元素删除类名
+export const removeClass = (node: HTMLElement, classes: string) =>
+ node && classes && classes.split(' ').forEach((c: any) => removeOneClass(node, c));
diff --git a/packages/design/components/utils/useStateRef.ts b/packages/design/components/utils/useStateRef.ts
new file mode 100644
index 0000000..3090be6
--- /dev/null
+++ b/packages/design/components/utils/useStateRef.ts
@@ -0,0 +1,29 @@
+import { useCallback, useRef, useState, SetStateAction, Dispatch } from 'react';
+
+const isFunction = (setStateAction: SetStateAction): setStateAction is (prevState: S) => S =>
+ typeof setStateAction === 'function';
+
+type ReadOnlyRefObject = {
+ readonly current: T;
+};
+
+type UseStateRef = {
+ (initialState: S | (() => S)): [S, Dispatch>, ReadOnlyRefObject];
+ (): [S | undefined, Dispatch>, ReadOnlyRefObject];
+};
+
+/** 返回的第三个参数为绑定的stateRef,会实时更新 */
+const useStateRef: UseStateRef = (initialState?: S | (() => S)) => {
+ const [state, setState] = useState(initialState);
+ const ref = useRef(state);
+
+ const dispatch: typeof setState = useCallback((setStateAction: any) => {
+ ref.current = isFunction(setStateAction) ? setStateAction(ref.current) : setStateAction;
+
+ setState(ref.current);
+ }, []);
+
+ return [state, dispatch, ref];
+};
+
+export default useStateRef;
diff --git a/scripts/build_props.mjs b/scripts/build_props.mjs
index 6ad5779..ea3cf22 100644
--- a/scripts/build_props.mjs
+++ b/scripts/build_props.mjs
@@ -1,127 +1,130 @@
-import { readdirSync, readFileSync, writeFileSync } from "fs";
-import { resolve, extname } from "path";
-import { transformFromAstSync } from "@babel/core";
-import { declare } from "@babel/helper-plugin-utils";
-import { parse } from "@babel/parser";
-import { ComponentsPath, ConpopnentDocsPath } from "./env.mjs";
+import { readdirSync, readFileSync, writeFileSync } from 'fs';
+import { resolve, extname } from 'path';
+import { transformFromAstSync } from '@babel/core';
+import { declare } from '@babel/helper-plugin-utils';
+import { parse } from '@babel/parser';
+import { ComponentsPath, ConpopnentDocsPath } from './env.mjs';
-
-
-const firstUpper = ([letter, ...rest]) => letter.toUpperCase() + rest.join("");
+const firstUpper = ([letter, ...rest]) => letter.toUpperCase() + rest.join('');
const COMMENT_REG = /\@(\w+)\s+([\S^\\]+)/g;
const inherit = [];
function parseComment(comment) {
- if (!comment) return {}
- const r = {};
- let m;
- while ((m = COMMENT_REG.exec(comment))) {
- r[m[1]] = m[2];
- }
- return r;
+ if (!comment) return {};
+ const r = {};
+ let m;
+ while ((m = COMMENT_REG.exec(comment))) {
+ r[m[1]] = m[2];
+ }
+ return r;
}
function h(componentMdxPath, component) {
- const sourceCode = readFileSync(componentMdxPath, { encoding: "utf-8" });
- const ast = parse(sourceCode, {
- sourceType: "unambiguous",
- plugins: ["typescript"],
- });
- const { code } = transformFromAstSync(ast, sourceCode, {
- plugins: [[generatorPropsPlugin, { name: component }]],
- });
- return code;
+ const sourceCode = readFileSync(componentMdxPath, { encoding: 'utf-8' });
+ const ast = parse(sourceCode, {
+ sourceType: 'unambiguous',
+ plugins: ['typescript'],
+ });
+ const { code } = transformFromAstSync(ast, sourceCode, {
+ plugins: [[generatorPropsPlugin, { name: component }]],
+ });
+ return code;
}
/**
- * @param {*} name
- * @param {*} docs
+ * @param {*} name
+ * @param {*} docs
*/
function generatePropsMd(name, docs) {
- const DocsPath = resolve(ConpopnentDocsPath, `./${firstUpper(name)}/props.mdx`)
- let table = `import Table from '../table.tsx'\n\rexport const params = ${JSON.stringify(docs)}\n\r## API 列表\n\r`
- // let table = `|参数名称|参数类型|是否可选|默认值|备注|版本支持|\n\r|:---|:---:|:---:|:---:|:---:|---:|\n\r`
- // for (let doc of docs) {
- // const { key, value, optional, version, description, default: defaultVal } = doc;
- // table += `|${key}|${value}|${optional ? '可选' : '必选'}|${defaultVal}| ${description}| ${version}|\n\r`
- // }
- writeFileSync(DocsPath, table)
+ const DocsPath = resolve(
+ ConpopnentDocsPath,
+ `./${firstUpper(name)}/props.mdx`
+ );
+ let table = `import Table from '../table.tsx'\n\rexport const params = ${JSON.stringify(
+ docs
+ )}\n\r## API 列表\n\r`;
+ // let table = `|参数名称|参数类型|是否可选|默认值|备注|版本支持|\n\r|:---|:---:|:---:|:---:|:---:|---:|\n\r`
+ // for (let doc of docs) {
+ // const { key, value, optional, version, description, default: defaultVal } = doc;
+ // table += `|${key}|${value}|${optional ? '可选' : '必选'}|${defaultVal}| ${description}| ${version}|\n\r`
+ // }
+ writeFileSync(DocsPath, table);
}
const generatorPropsPlugin = declare((api, options, dirname) => {
- api.assertVersion(7);
- return {
- pre: (file) => {
- // 用于存储props对象Array<{...}>
- file.docs = [];
- },
- visitor: {
- TSInterfaceDeclaration: (path, scope) => {
- if (options.name === "index") {
- path.traverse({
- TSPropertySignature: (p) => {
- // console.log(p.get('typeAnnotation').toString(),p.get('optional').node);
- const key = p.get("key").toString();
- const value = p.get("typeAnnotation").toString();
- const optional = p.get("optional").node;
- const commentStr = p.get("leadingComments")[0].node.value;
- const comments = parseComment(commentStr);
- inherit.push({ key, value, optional, ...comments });
- },
- });
- return;
- }
- // ComponentProps
- if (path.get("id").toString() === `${firstUpper(options.name)}Props`) {
- // 匹配是否继承
- for (let extend of path.get("extends")) {
- if (extend.toString() === "PivotDesignProps") {
- /**
- * ```json
- * {
- * key: 'className',
- * value: ': string',
- * optional: true,
- * comment: [version: '1.0.0', description: '自定义类名']
- * },
- * ```
- */
- scope.file.docs.push(...inherit);
- break;
- }
- }
- // 解析自己的props
- // console.log(options.name, scope.file.docs);
- path.traverse({
- TSPropertySignature: (p) => {
- // console.log(p.get('typeAnnotation').toString(),p.get('optional').node);
- const key = p.get("key").toString();
- const value = p.get("typeAnnotation").toString();
- const optional = p.get("optional").node;
- const commentStr = p.get("leadingComments").length > 0 && p.get("leadingComments")[0].node.value;
- const comments = parseComment(commentStr);
- scope.file.docs.push({ key, value, optional, ...comments });
- },
- });
- }
- },
- },
- post(file) {
- if (options.name === 'index') return
- console.log(file.docs);
- // todo:create md table 使用自己的自定义组件吧
- generatePropsMd(options.name, file.docs)
- },
- };
+ api.assertVersion(7);
+ return {
+ pre: (file) => {
+ // 用于存储props对象Array<{...}>
+ file.docs = [];
+ },
+ visitor: {
+ TSInterfaceDeclaration: (path, scope) => {
+ if (options.name === 'index') {
+ path.traverse({
+ TSPropertySignature: (p) => {
+ // console.log(p.get('typeAnnotation').toString(),p.get('optional').node);
+ const key = p.get('key').toString();
+ const value = p.get('typeAnnotation').toString();
+ const optional = p.get('optional').node;
+ const commentStr = p.get('leadingComments')[0].node.value;
+ const comments = parseComment(commentStr);
+ inherit.push({ key, value, optional, ...comments });
+ },
+ });
+ return;
+ }
+ // ComponentProps
+ if (path.get('id').toString() === `${firstUpper(options.name)}Props`) {
+ // 匹配是否继承
+ for (let extend of path.get('extends')) {
+ if (extend.toString() === 'PivotDesignProps') {
+ /**
+ * ```json
+ * {
+ * key: 'className',
+ * value: ': string',
+ * optional: true,
+ * comment: [version: '1.0.0', description: '自定义类名']
+ * },
+ * ```
+ */
+ scope.file.docs.push(...inherit);
+ break;
+ }
+ }
+ // 解析自己的props
+ // console.log(options.name, scope.file.docs);
+ path.traverse({
+ TSPropertySignature: (p) => {
+ // console.log(p.get('typeAnnotation').toString(),p.get('optional').node);
+ const key = p.get('key').toString();
+ const value = p.get('typeAnnotation').toString();
+ const optional = p.get('optional').node;
+ const commentStr =
+ p.get('leadingComments').length > 0 &&
+ p.get('leadingComments')[0].node.value;
+ const comments = parseComment(commentStr);
+ scope.file.docs.push({ key, value, optional, ...comments });
+ },
+ });
+ }
+ },
+ },
+ post(file) {
+ if (options.name === 'index') return;
+ // console.log(file.docs);
+ // todo:create md table 使用自己的自定义组件吧
+ generatePropsMd(options.name, file.docs);
+ },
+ };
});
-
-
const components = readdirSync(ComponentsPath).filter((dir) => extname(dir));
-h(resolve(ComponentsPath, `./index.ts`), "index");
+h(resolve(ComponentsPath, `./index.ts`), 'index');
for (let componentPath of components) {
- if (componentPath === "index.ts") continue;
- const componentMdxPath = resolve(ComponentsPath, `./${componentPath}`);
- const component = componentPath.split(".")[0];
- // if (component === "index") continue;
- h(componentMdxPath, component);
+ if (componentPath === 'index.ts') continue;
+ const componentMdxPath = resolve(ComponentsPath, `./${componentPath}`);
+ const component = componentPath.split('.')[0];
+ // if (component === "index") continue;
+ h(componentMdxPath, component);
}