ivue-material-plus
Version:
A high quality UI components Library with Vue.js
293 lines (266 loc) • 6.61 kB
text/typescript
import type { ComponentResolver, ComponentInfo } from './types';
export interface resolverOptions {
// use commonjs lib & source css or scss for ssr
ssr?: boolean;
// 是否引入style
importStyle?: boolean;
// 组件名称
name?: string;
}
// 转换为驼峰
function kebabCase(key) {
const result = key.replace(/([A-Z])/g, ' $1').trim();
return result.split(' ').join('-').toLowerCase();
}
// 安装包路径
const pakPath = 'ivue-material-plus/dist/unplugin-vue-components';
// 颜色路径
const basePath = 'ivue-material-plus/dist/styles/base.css';
// 动画路径
const animationPath = 'ivue-material-plus/dist/styles/animation.css';
// 没有样式的组件
const noStylesComponents = [
'ivue-content',
'ivue-carousel-item',
'ivue-bottom-nav-item',
'ivue-breadcrumb-item',
'ivue-checkbox-group',
'ivue-collapse-panel',
'ivue-count-down',
'ivue-count-up',
'ivue-radio-group',
'ivue-option',
'ivue-option-group',
'ivue-image-preview',
'ivue-relative-time',
'ivue-submenu',
'ivue-menu-group',
'ivue-menu-item',
'ivue-form-item',
'ivue-skeleton-item',
];
// 使用依赖组件
const useDependentComponents = [
// ivue-table
{
name: 'ivue-table',
dependent: ['IvueTableColumn'],
},
// ivue-tabs
{
name: 'ivue-tabs',
dependent: ['IvueTabItem', 'IvueTab'],
},
// ivue-form
{
name: 'ivue-form',
dependent: ['IvueFormItem'],
},
// ivue-select
{
name: 'ivue-select',
dependent: ['IvueOption', 'IvueOptionGroup'],
},
// ivue-steps
{
name: 'ivue-steps',
dependent: ['IvueStep'],
},
// ivue-skeleton
{
name: 'ivue-skeleton',
dependent: ['IvueSkeletonItem'],
},
];
// 样式
const sideEffects = [
// ivue-page
{
name: 'ivue-page',
sideEffects: ['ivue-select'],
},
// ivue-modal
{
name: 'ivue-modal',
sideEffects: ['ivue-button', 'ivue-spin'],
},
// ivue-cascader
{
name: 'ivue-cascader',
sideEffects: ['ivue-input', 'ivue-select', 'ivue-loading'],
},
// ivue-auto-complete
{
name: 'ivue-auto-complete',
sideEffects: ['ivue-loading', 'ivue-input', 'ivue-select'],
},
// ivue-button
{
name: 'ivue-button',
sideEffects: ['ivue-ripple'],
},
// ivue-switch
{
name: 'ivue-switch',
sideEffects: ['ivue-ripple'],
},
// ivue-table
{
name: 'ivue-table',
sideEffects: ['ivue-tooltip', 'ivue-checkbox', 'ivue-scrollbar'],
},
];
// 设置样式文件
function getSideEffects(componentsName: string, options) {
// 没有样式文件
if (!options.importStyle) {
return;
}
// 单文件引入
if (options.singleFile) {
return [`${pakPath}/styles/${componentsName}.css`];
}
let list = [
`${pakPath}/styles/reset.css`,
`${pakPath}/styles/ivue-icon.css`,
`${basePath}`,
`${animationPath}`,
`${pakPath}/styles/${componentsName}.css`,
];
sideEffects.forEach((item) => {
if (item.name === componentsName) {
item.sideEffects.forEach((sideEffectsItem) => {
list.push(`${pakPath}/styles/${sideEffectsItem}.css`);
});
}
});
return list;
}
// 请求组件
const resolveComponent = (
componentsName: string,
options: resolverOptions
): ComponentInfo | undefined => {
// 使用依赖组件
let useDependentComponentsData: {
name: string;
from: string;
} | null = null;
useDependentComponents.forEach((item) => {
item.dependent.forEach((dependent) => {
// 转换为驼峰
const _kebabCase = kebabCase(dependent);
// 匹配输入的组件是否符合
if (_kebabCase === componentsName) {
useDependentComponentsData = {
name: dependent,
from: `${pakPath}/${options.ssr ? 'lib' : 'es'}`,
};
}
});
});
// 注册依赖的组件
if (useDependentComponentsData) {
return useDependentComponentsData;
}
return {
name: options.name,
from: `${pakPath}/${options.ssr ? 'lib' : 'es'}`,
sideEffects: getSideEffects(componentsName, options),
};
};
// 请求指令
const resolveDirective = (name: string, options: resolverOptions) => {
const directives = {
// loading
Loading: {
name: 'IvueLoading',
importName: 'ivue-loading',
styleName: 'ivue-loading',
importStyle: true,
},
// 水波纹
Ripple: {
name: 'Ripple',
importName: 'ivue-ripple',
styleName: 'ivue-ripple',
importStyle: true,
},
// 点击外层触发
ClickOutside: {
name: 'ClickOutside',
importName: 'ivue-click-outside',
styleName: 'ivue-click-outside',
importStyle: false,
},
// 手指事件
Touch: {
name: 'Touch',
importName: 'ivue-touch',
styleName: 'ivue-touch',
importStyle: false,
},
// 文本缩略
LineClamp: {
name: 'LineClamp',
importName: 'ivue-line-clamp',
styleName: 'ivue-line-clamp',
importStyle: true,
// 单文件引入
singleFile: true,
},
};
const directive = directives[name];
if (!directive) {
return;
}
return {
name: directive.name,
from: `${pakPath}/${options.ssr ? 'lib' : 'es'}`,
sideEffects: getSideEffects(directive.styleName, {
importStyle: directive.importStyle,
singleFile: directive.singleFile,
}),
};
};
export function IvueMaterialPlusResolver(
options?: resolverOptions
): ComponentResolver[] {
let optionsResolved = {
ssr: false,
...options,
};
return [
{
type: 'component',
resolve: (name: string) => {
// 是否是 ivue组件
if (!name.match(/^Ivue[A-Z]/)) {
return;
}
// 转换为驼峰
const _kebabCase = kebabCase(name);
// 没有样式组件
if ([...noStylesComponents].includes(_kebabCase)) {
return resolveComponent(_kebabCase, {
name,
importStyle: false,
...optionsResolved,
});
}
// 有样式组件
return resolveComponent(_kebabCase, {
name,
importStyle: true,
...optionsResolved,
});
},
},
{
type: 'directive',
resolve: (name: string) => {
return resolveDirective(name, optionsResolved);
},
},
];
}