@alifd/adaptor-helper
Version:
Next adaptor utils
288 lines (242 loc) • 7.13 kB
text/typescript
import { STATE_MARK, STATE_PREFIX_MARK } from "./state-mark";
import Types from "./types";
import { toLabelWord } from "./utils";
type TObject = { [key: string]: any };
export interface IOption {
label: string;
value: string;
}
export interface IProp {
name: string;
label?: string;
type: Types;
options?: IOption[];
default?: any;
}
export interface IDataOption {
group?: boolean;
hover?: boolean;
active?: boolean;
disable?: boolean;
icon?: boolean;
generate?: boolean;
default: string;
}
export interface IEditorConfig {
props: IProp[];
nodes: IProp[];
data?: IDataOption;
}
export interface IContenOption {
name: string;
label?: string;
options: Array<string | IOption>;
default?: string;
}
export interface IContentConfig {
options: IContenOption[];
transform(props: TObject, options: TObject): TObject;
}
export interface IDemoNode {
adaptor: string;
props: TObject;
}
export interface IDemo {
id: string;
background?: string;
height?: number;
node: IDemoNode;
}
export interface IAdaptor {
name: string;
shape?: Array<string | IOption>;
editor(shape: string): IEditorConfig;
adaptor(props: TObject): any;
content(shape: string): IContentConfig;
demoOptions(demo: IDemo): IDemo;
}
const normalizeOptions = (options: Array<string | IOption> = []): IOption[] => {
return options.filter((v: any) => !!v).map((item: any) => {
const value = item.value || item;
return {
value,
label: item.label || toLabelWord(value),
};
});
};
const normalizeProps = <T>(props: T[] = []): T[] => {
return props.filter((v: any) => !!v).map((prop: any) => {
return {
...prop,
label: prop.label || toLabelWord(prop.name),
options: normalizeOptions(prop.options),
} as T;
});
};
export const normalizeAdaptor = (adaptor: IAdaptor): IAdaptor => {
if (!adaptor.name) {
console.error("[error] muse be have name:");
return adaptor;
}
let shape: IOption[];
if (!adaptor.shape || !Array.isArray(adaptor.shape) || adaptor.shape.length < 1) {
shape = [{ label: adaptor.name, value: "normal" }];
} else {
shape = adaptor.shape.filter((v: string | IOption) => !!v).map((item: any) => {
const value: string = item.value || item;
return {
value,
label: item.label || `${toLabelWord(value)} ${value === "normal" ? "" : adaptor.name}`,
};
});
}
const editor = (s: string): IEditorConfig => {
const p: any = adaptor.editor ? adaptor.editor(s) : {};
if (!p.props) {
p.props = [];
}
if (!p.nodes) {
p.nodes = [];
}
return {
...p,
props: normalizeProps<IProp>(p.props),
nodes: normalizeProps<IProp>(p.nodes),
} as IEditorConfig;
};
const content = (s: string) => {
const p: any = adaptor.content ? adaptor.content(s) : {};
return {
...p,
options: normalizeProps<IContenOption>(p.options),
};
};
return {
...adaptor,
shape,
editor,
content,
} as IAdaptor;
};
export const getDefaultProps = (adaptor: IAdaptor, shape: string): TObject => {
const p = adaptor.editor(shape);
const props: { [key: string]: any } = {
shape,
data: (p.data && p.data.default) || "",
};
p.props.forEach((item: IProp) => {
let { default: defaultValue } = item;
if (defaultValue === undefined || defaultValue === null) {
switch (item.type) {
case Types.string:
defaultValue = "";
break;
case Types.number:
defaultValue = 0;
break;
case Types.bool:
defaultValue = false;
break;
case Types.enum:
defaultValue = item.options ? item.options[0].value : "";
break;
default:
break;
}
}
props[item.name] = defaultValue;
});
p.nodes.forEach(({ name, default: defaultValue }) => {
props[name] = defaultValue;
});
return props;
};
export const findProp = (name: string, props: IProp[] = []): IProp | undefined => {
return props.find((item: IProp) => item.name === name);
};
export const findOptionLabel = (value: string, name: string, props: IProp[] = []): string => {
const prop = findProp(name, props);
if (prop && prop.type === Types.enum) {
const option = (prop.options || []).find((item) => item.value === value);
return option ? option.label : value;
}
return "";
};
let index = 1;
const now = new Date().getTime();
export const uuid = () => (now + index++).toString(16);
export const getStates = (dataOption: IDataOption = { default: "" }, props: IProp[] = []): string[] => {
const stateMap: { [key: string]: boolean } = {
normal: true,
hover: !!dataOption.hover,
active: !!dataOption.active,
disabled: !!dataOption.disable,
};
let states: string[] | null = dataOption.generate === false ?
null : Object.keys(stateMap).filter((key: string) => stateMap[key]);
const stateProp = findProp("state", props);
if (stateProp) {
states = (stateProp.options || []).map(({ value }) => value);
}
return states || ["normal"];
};
export const generateDemos = (adaptor: IAdaptor): IDemo[] => {
const demos: IDemo[] = [];
(adaptor.shape as IOption[]).forEach(({ value } ) => {
const editor = adaptor.editor(value);
const sizeProp = findProp("size", editor.props);
const stateProp = findProp("state", editor.props);
const levelProp = findProp("level", editor.props);
const states = getStates(editor.data, editor.props);
const sizes = sizeProp && sizeProp.options ? sizeProp.options.map(({ value: v }) => v) : ["medium"];
const levels = levelProp && levelProp.options ? levelProp.options.map(({ value: v }) => v) : ["normal"];
states.forEach((state: string) => {
sizes.forEach((size) => {
levels.forEach((level) => {
const props: TObject = {
...getDefaultProps(adaptor, value),
};
if (sizeProp) {
props.size = size;
}
if (levelProp) {
props.level = level;
}
if (states.length > 1) {
if (stateProp) {
props.state = state;
} else {
if (props.data && STATE_MARK[props.data.substring(0, 1)]) {
props.data = props.data.substring(1);
}
props.data = STATE_PREFIX_MARK[state] + props.data;
}
}
const demo: IDemo = {
id: uuid(),
node: {
adaptor: adaptor.name,
props,
},
};
demos.push({
...demo,
...(adaptor.demoOptions && adaptor.demoOptions(demo)),
});
});
});
});
});
return demos;
};
export const filterDemoState = ((state: string) => {
return ({ node }: IDemo ) => {
const { props = {} } = node;
const { data = "" } = props;
let demoState = STATE_MARK[data.substring(0, 1)] || "normal";
if (props.state) {
demoState = props.state;
}
return demoState === state;
};
});