diff --git a/addons/docs/src/lib/convert/flow/convert.ts b/addons/docs/src/lib/convert/flow/convert.ts new file mode 100644 index 000000000000..b9ef15867ea7 --- /dev/null +++ b/addons/docs/src/lib/convert/flow/convert.ts @@ -0,0 +1,55 @@ +/* eslint-disable no-case-declarations */ +import { SBType } from '@storybook/client-api'; +import { FlowType, FlowSigType, FlowLiteralType } from './types'; + +const isLiteral = (type: FlowType) => type.name === 'literal'; +const toEnumOption = (element: FlowLiteralType) => element.value.replace(/['|"]/g, ''); + +const convertSig = (type: FlowSigType) => { + switch (type.type) { + case 'function': + return { name: 'function' }; + case 'object': + const values: any = {}; + type.signature.properties.forEach((prop) => { + values[prop.key] = convert(prop.value); + }); + return { + name: 'object', + value: values, + }; + default: + throw new Error(`Unknown: ${type}`); + } +}; + +export const convert = (type: FlowType): SBType | void => { + const { name, raw } = type; + const base: any = {}; + if (typeof raw !== 'undefined') base.raw = raw; + switch (type.name) { + case 'literal': + return { ...base, name: 'other', value: type.value }; + case 'string': + case 'number': + case 'symbol': + case 'boolean': { + return { ...base, name }; + } + case 'Array': { + return { ...base, name: 'array', value: type.elements.map(convert) }; + } + case 'signature': + return { ...base, ...convertSig(type) }; + case 'union': + if (type.elements.every(isLiteral)) { + return { ...base, name: 'enum', value: type.elements.map(toEnumOption) }; + } + return { ...base, name, value: type.elements.map(convert) }; + + case 'intersection': + return { ...base, name, value: type.elements.map(convert) }; + default: + return { ...base, name: 'other', value: name }; + } +}; diff --git a/addons/docs/src/lib/convert/flow/index.ts b/addons/docs/src/lib/convert/flow/index.ts new file mode 100644 index 000000000000..0ef743fdb7ef --- /dev/null +++ b/addons/docs/src/lib/convert/flow/index.ts @@ -0,0 +1,2 @@ +export * from './convert'; +export * from './types'; diff --git a/addons/docs/src/lib/convert/flow/types.ts b/addons/docs/src/lib/convert/flow/types.ts new file mode 100644 index 000000000000..b131ac575526 --- /dev/null +++ b/addons/docs/src/lib/convert/flow/types.ts @@ -0,0 +1,56 @@ +interface FlowBaseType { + name: string; + type?: string; + raw?: string; + required?: boolean; +} + +type FlowArgType = FlowType; + +type FlowCombinationType = FlowBaseType & { + name: 'union' | 'intersection'; + elements: FlowType[]; +}; + +type FlowFuncSigType = FlowBaseType & { + name: 'signature'; + type: 'function'; + signature: { + arguments: FlowArgType[]; + return: FlowType; + }; +}; + +type FlowObjectSigType = FlowBaseType & { + name: 'signature'; + type: 'object'; + signature: { + properties: { + key: string; + value: FlowType; + }[]; + }; +}; + +type FlowScalarType = FlowBaseType & { + name: 'any' | 'boolean' | 'number' | 'void' | 'string' | 'symbol'; +}; + +export type FlowLiteralType = FlowBaseType & { + name: 'literal'; + value: string; +}; + +type FlowArrayType = FlowBaseType & { + name: 'Array'; + elements: FlowType[]; +}; + +export type FlowSigType = FlowObjectSigType | FlowFuncSigType; + +export type FlowType = + | FlowScalarType + | FlowLiteralType + | FlowCombinationType + | FlowSigType + | FlowArrayType; diff --git a/addons/docs/src/lib/convert/index.ts b/addons/docs/src/lib/convert/index.ts index 9b7b0fb4df27..f6cd38a77850 100644 --- a/addons/docs/src/lib/convert/index.ts +++ b/addons/docs/src/lib/convert/index.ts @@ -1,11 +1,13 @@ import { DocgenInfo } from '../docgen/types'; import { convert as tsConvert, TSType } from './typescript'; +import { convert as flowConvert, FlowType } from './flow'; import { convert as propTypesConvert } from './proptypes'; export const convert = (docgenInfo: DocgenInfo) => { - const { type, tsType } = docgenInfo; + const { type, tsType, flowType } = docgenInfo; if (type != null) return propTypesConvert(type); if (tsType != null) return tsConvert(tsType as TSType); + if (flowType != null) return flowConvert(flowType as FlowType); return null; };