[其他] 初始化项目结构
This commit is contained in:
commit
b2fa2b90b8
3
.browserslistrc
Normal file
3
.browserslistrc
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
current node
|
||||||
|
last 2 versions and > 2%
|
||||||
|
ie > 10
|
26
.eslintrc.js
Normal file
26
.eslintrc.js
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
module.exports = {
|
||||||
|
env: {
|
||||||
|
browser: true,
|
||||||
|
node: true,
|
||||||
|
},
|
||||||
|
parser: 'vue-eslint-parser',
|
||||||
|
parserOptions: {
|
||||||
|
parser: '@typescript-eslint/parser',
|
||||||
|
sourceType: 'module',
|
||||||
|
ecmaVersion: 10,
|
||||||
|
},
|
||||||
|
plugins: ['@typescript-eslint', 'prettier'],
|
||||||
|
extends: [
|
||||||
|
'eslint:recommended',
|
||||||
|
'plugin:vue/vue3-recommended',
|
||||||
|
'plugin:@typescript-eslint/recommended',
|
||||||
|
],
|
||||||
|
rules: {
|
||||||
|
'no-console': process.env.NODE_ENV === 'production' ? 'error' : 'off',
|
||||||
|
'no-debugger': process.env.NODE_ENV === 'production' ? 'error' : 'off',
|
||||||
|
quotes: ['error', 'single'],
|
||||||
|
semi: ['error', 'never'],
|
||||||
|
'no-unused-vars': 'off',
|
||||||
|
'@typescript-eslint/no-unused-vars': 'off',
|
||||||
|
},
|
||||||
|
}
|
27
.github/workflows/build docs.yml
vendored
Normal file
27
.github/workflows/build docs.yml
vendored
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
name: build docs
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches: [ master ]
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build-and-deploy:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: Checkout
|
||||||
|
uses: actions/checkout@v2.3.1
|
||||||
|
with:
|
||||||
|
persist-credentials: false
|
||||||
|
|
||||||
|
- name: Install and Build
|
||||||
|
run: |
|
||||||
|
npm install
|
||||||
|
npm run build:docs
|
||||||
|
- name: Deploy
|
||||||
|
uses: JamesIves/github-pages-deploy-action@3.6.2
|
||||||
|
with:
|
||||||
|
GITHUB_TOKEN: ${{ secrets.TOKEN }}
|
||||||
|
BRANCH: gh-pages
|
||||||
|
FOLDER: docs/dist
|
||||||
|
CLEAN: true
|
20
.github/workflows/test.yml
vendored
Normal file
20
.github/workflows/test.yml
vendored
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
name: test
|
||||||
|
|
||||||
|
on:
|
||||||
|
pull_request:
|
||||||
|
branches: [ master ]
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
test:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: Checkout
|
||||||
|
uses: actions/checkout@v2.3.1
|
||||||
|
with:
|
||||||
|
persist-credentials: false
|
||||||
|
|
||||||
|
- name: Install and Test
|
||||||
|
run: |
|
||||||
|
npm install
|
||||||
|
npm run test
|
20
.gitignore
vendored
Normal file
20
.gitignore
vendored
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
.DS_Store
|
||||||
|
node_modules/
|
||||||
|
dist/
|
||||||
|
example/dist/
|
||||||
|
lib/
|
||||||
|
/types/
|
||||||
|
npm-debug.log*
|
||||||
|
yarn-debug.log*
|
||||||
|
yarn-error.log*
|
||||||
|
yarn.lock
|
||||||
|
package-lock.json
|
||||||
|
|
||||||
|
|
||||||
|
# Editor directories and files
|
||||||
|
.idea
|
||||||
|
.vscode
|
||||||
|
*.suo
|
||||||
|
*.ntvs*
|
||||||
|
*.njsproj
|
||||||
|
*.sln
|
53
.helperrc.js
Normal file
53
.helperrc.js
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
const helper = require('components-helper')
|
||||||
|
const { name, version } = require('./package.json')
|
||||||
|
|
||||||
|
helper({
|
||||||
|
name,
|
||||||
|
version,
|
||||||
|
entry: 'docs/docs/en-US/components/*.md',
|
||||||
|
outDir: 'lib',
|
||||||
|
reComponentName,
|
||||||
|
reDocUrl,
|
||||||
|
reAttribute,
|
||||||
|
titleRegExp: '#+\\s+(.*)\n+>\\s*([^(#|\\n)]*)',
|
||||||
|
tableRegExp:
|
||||||
|
'#+\\s+(.*\\s*Props|.*\\s*Events|.*\\s*Slots|.*\\s*Directives)\\s*\\n+(\\|?.+\\|.+)\\n\\|?\\s*:?-+:?\\s*\\|.+((\\n\\|?.+\\|.+)+)',
|
||||||
|
})
|
||||||
|
|
||||||
|
function reComponentName(title) {
|
||||||
|
return 'ele-' + title.replace(/\B([A-Z])/g, '-$1').toLowerCase()
|
||||||
|
}
|
||||||
|
|
||||||
|
function reDocUrl(fileName, header) {
|
||||||
|
// TODO: `zh-CN` -> `en-US`
|
||||||
|
const docs = 'https://gitee.com/Jmysy/layui-vue'
|
||||||
|
const _header = header ? header.replace(/[ ]+/g, '-') : undefined
|
||||||
|
return docs + fileName + (_header ? '#' + header : '')
|
||||||
|
}
|
||||||
|
|
||||||
|
function reAttribute(value, key) {
|
||||||
|
if (key === 'Name' && /^(-|—)$/.test(value)) {
|
||||||
|
return 'default'
|
||||||
|
} else if (key === 'Name' && /v-model:(.+)/.test(value)) {
|
||||||
|
const _value = value.match(/v-model:(.+)/)
|
||||||
|
return _value ? _value[1] : undefined
|
||||||
|
} else if (key === 'Name' && /v-model/.test(value)) {
|
||||||
|
return 'model-value'
|
||||||
|
} else if (key === 'Name') {
|
||||||
|
return value.replace(/\B([A-Z])/g, '-$1').toLowerCase()
|
||||||
|
} else if (key === 'Type') {
|
||||||
|
return value
|
||||||
|
.replace(/\s*\/\s*/g, '|')
|
||||||
|
.replace(/\s*,\s*/g, '|')
|
||||||
|
.replace(/\(.*\)/g, '')
|
||||||
|
.toLowerCase()
|
||||||
|
} else if (value === '' || /^(-|—)$/.test(value)) {
|
||||||
|
return undefined
|
||||||
|
} else if (key === 'Options') {
|
||||||
|
return /\[.+\]\(.+\)/.test(value) || /^\*$/.test(value)
|
||||||
|
? undefined
|
||||||
|
: value.replace(/`/g, '')
|
||||||
|
} else {
|
||||||
|
return value
|
||||||
|
}
|
||||||
|
}
|
4
.lintstagedrc
Normal file
4
.lintstagedrc
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
{
|
||||||
|
"*.{ts,vue,js,tsx,jsx}": ["prettier --write --no-verify ", "eslint --fix"],
|
||||||
|
"*.{html,css,md,json}": "prettier --write",
|
||||||
|
}
|
9
.postcssrc.json
Normal file
9
.postcssrc.json
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
{
|
||||||
|
"map": false,
|
||||||
|
"plugins": {
|
||||||
|
"postcss-preset-env": {
|
||||||
|
"stage": 1
|
||||||
|
},
|
||||||
|
"autoprefixer": {}
|
||||||
|
}
|
||||||
|
}
|
4
.prettierrc
Normal file
4
.prettierrc
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
{
|
||||||
|
"singleQuote": true,
|
||||||
|
"semi": false
|
||||||
|
}
|
20
LICENSE
Normal file
20
LICENSE
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
The MIT License (MIT)
|
||||||
|
|
||||||
|
Copyright 2019 Jmys
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||||
|
this software and associated documentation files (the "Software"), to deal in
|
||||||
|
the Software without restriction, including without limitation the rights to
|
||||||
|
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||||
|
the Software, and to permit persons to whom the Software is furnished to do so,
|
||||||
|
subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in all
|
||||||
|
copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||||
|
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||||
|
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||||
|
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
|
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
102
README.md
Normal file
102
README.md
Normal file
@ -0,0 +1,102 @@
|
|||||||
|
<img src="/docs/src/assets/logo.svg" width="400px" style="margin:50px" />
|
||||||
|
|
||||||
|
a component library for Vue 3 base on element-plus
|
||||||
|
|
||||||
|
<p>
|
||||||
|
<a href="#">
|
||||||
|
<img src="https://img.shields.io/badge/Vue-3.0.0+-green.svg" alt="Vue Version">
|
||||||
|
</a>
|
||||||
|
<a href="#">
|
||||||
|
<img src="https://img.shields.io/badge/Vue Router-4.0.0+-green.svg" alt="Vue Router Version">
|
||||||
|
</a>
|
||||||
|
<a href="#">
|
||||||
|
<img src="https://img.shields.io/badge/Element Plus-1.0.0+-green.svg" alt="Element Plus Version">
|
||||||
|
</a>
|
||||||
|
</p>
|
||||||
|
|
||||||
|
[开 发 文 档](https://jmysy.github.io/layui-vue) | [更 新 日 志](https://gitee.com/Jmysy/layui-vue/releases) | [常 见 问 题](https://gitee.com/Jmysy/layui-vue/issues)
|
||||||
|
|
||||||
|
##### 📖 概述
|
||||||
|
|
||||||
|
Element Enhance 是基于 Element Plus 而开发的模板组件,提供了更高级别的抽象支持,开箱即用,更加专注于页面。
|
||||||
|
|
||||||
|
### Status: Beta
|
||||||
|
|
||||||
|
This project is still under heavy development. Feel free to join us and make your first pull request.
|
||||||
|
|
||||||
|
[![Edit layui-vue](https://codesandbox.io/static/img/play-codesandbox.svg)](https://codesandbox.io/s/layui-vue-template-vh9bg?fontsize=14&hidenavigation=1&theme=dark)
|
||||||
|
|
||||||
|
##### 📢 理念
|
||||||
|
|
||||||
|
Element Plus 定义了基础的设计规范,对应也提供了大量的基础组件。但是对于中后台类应用,我们希望提供更高程度的抽象,提供更上层的设计规范,并且对应提供相应的组件使得开发者可以快速搭建出高质量的页面。
|
||||||
|
|
||||||
|
列表页应该可以用 EleLayout + EleTable 完成,编辑页应该使用 EleLayout + EleForm 完成,详情页可以用 EleLayout + EleDescriptions 完成。 一个页面在开发工程中只需要关注几个重型组件,降低心智负担,专注于更核心的业务逻辑。
|
||||||
|
|
||||||
|
##### ✒️ 特性
|
||||||
|
|
||||||
|
该组件库的开发理念就是面向未来,如果查看源码你就会发现像是 vue 3 的 [script setup](https://github.com/vuejs/rfcs/pull/227.) 实验性功能、像是 CSSNext 的 [CSS Variables](https://developer.mozilla.org/en-US/docs/Web/CSS/--*)。在保证大部分浏览器的兼容性的情况下,会更多的使用新特性、新功能来开发
|
||||||
|
|
||||||
|
##### 💡 计划
|
||||||
|
|
||||||
|
- [x] PageContainer: 为了减少繁杂的面包屑配置和标题。
|
||||||
|
- [ ] StatisticCard: 指标卡结合统计数值用于展示某主题的核心指标。
|
||||||
|
- [ ] Search: 有些是时候表单要与别的组件组合使用,需要一些特殊形态的表单。
|
||||||
|
|
||||||
|
##### ☁️ 入门
|
||||||
|
|
||||||
|
让 Element Plus 更简单, 更通用, 更流行
|
||||||
|
|
||||||
|
<img src="/docs/src/assets/banner.png"/>
|
||||||
|
|
||||||
|
安装
|
||||||
|
|
||||||
|
```
|
||||||
|
npm install element-plus --save
|
||||||
|
|
||||||
|
npm install layui-vue --save
|
||||||
|
```
|
||||||
|
|
||||||
|
引入
|
||||||
|
|
||||||
|
```js
|
||||||
|
import { createApp } from 'vue'
|
||||||
|
import App from './App.vue'
|
||||||
|
import ElementEnhance from 'layui-vue'
|
||||||
|
import 'layui-vue/lib/style.css'
|
||||||
|
import ElementPlus from 'element-plus'
|
||||||
|
import 'element-plus/lib/theme-chalk/index.css'
|
||||||
|
|
||||||
|
const app = createApp(App)
|
||||||
|
|
||||||
|
app.use(ElementEnhance)
|
||||||
|
app.use(ElementPlus)
|
||||||
|
app.mount('#app')
|
||||||
|
```
|
||||||
|
|
||||||
|
使用
|
||||||
|
|
||||||
|
```vue
|
||||||
|
<template>
|
||||||
|
<ele-layout multi-tab="true" breadcrumb="true">
|
||||||
|
<template #logo></template>
|
||||||
|
</ele-layout>
|
||||||
|
</template>
|
||||||
|
```
|
||||||
|
|
||||||
|
效果
|
||||||
|
|
||||||
|
![输入图片说明](https://images.gitee.com/uploads/images/2021/0530/172502_95f955fc_4835367.png '屏幕截图.png')
|
||||||
|
|
||||||
|
##### 🔥 案例
|
||||||
|
|
||||||
|
[Element Enhance Admin](https://gitee.com/Jmysy/layui-vue-admin) : 基于 Element Enhance 的 前端 Cli template
|
||||||
|
|
||||||
|
##### 📈 趋势
|
||||||
|
|
||||||
|
[![Giteye chart](https://chart.giteye.net/gitee/Jmysy/layui-vue/9X8CXNEY.png)](https://giteye.net/chart/9X8CXNEY)
|
||||||
|
|
||||||
|
##### 🍚 贡献
|
||||||
|
|
||||||
|
组件库还处于早期开发阶段,功能还需要完善。如果你希望参与贡献,欢迎 [Pull Request](https://github.com/Jmysy/layui-vue/pulls)。如果只是简单的文档相关的错误修正,你可以直接 PR,但如果是当前组件的 BUG 或者新功能、新组件等,最好优先提 [issues](https://github.com/Jmysy/layui-vue/issues)
|
||||||
|
|
||||||
|
[![Giteye chart](https://chart.giteye.net/gitee/Jmysy/layui-vue/57W94KFG.png)](https://giteye.net/chart/57W94KFG)
|
700
docs/docs/en-US/components/button.md
Normal file
700
docs/docs/en-US/components/button.md
Normal file
@ -0,0 +1,700 @@
|
|||||||
|
##### 基础
|
||||||
|
|
||||||
|
::: demo 传入 columns 数据,自动生成表格
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<ele-table
|
||||||
|
:data="data"
|
||||||
|
:columns="columns"
|
||||||
|
/>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import { ref } from 'vue'
|
||||||
|
|
||||||
|
export default {
|
||||||
|
setup() {
|
||||||
|
const columns = ref([
|
||||||
|
{
|
||||||
|
label: '日期',
|
||||||
|
prop: 'date',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '姓名',
|
||||||
|
prop: 'name',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '地址',
|
||||||
|
prop: 'address',
|
||||||
|
},
|
||||||
|
])
|
||||||
|
const data = ref([
|
||||||
|
{
|
||||||
|
date: '2016-05-03',
|
||||||
|
name: 'Tom',
|
||||||
|
address: 'No. 189, Grove St, Los Angeles',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
date: '2016-05-02',
|
||||||
|
name: 'Tom',
|
||||||
|
address: 'No. 189, Grove St, Los Angeles',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
date: '2016-05-04',
|
||||||
|
name: 'Tom',
|
||||||
|
address: 'No. 189, Grove St, Los Angeles',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
date: '2016-05-01',
|
||||||
|
name: 'Tom',
|
||||||
|
address: 'No. 189, Grove St, Los Angeles',
|
||||||
|
},
|
||||||
|
])
|
||||||
|
|
||||||
|
return {
|
||||||
|
data,
|
||||||
|
columns,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
:::
|
||||||
|
|
||||||
|
##### 索引
|
||||||
|
|
||||||
|
::: demo 通过配置 index 显示索引列,支持 columns 的参数
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<ele-table
|
||||||
|
:data="data"
|
||||||
|
:columns="columns"
|
||||||
|
:index="{ label: '#' }"
|
||||||
|
/>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import { ref } from 'vue'
|
||||||
|
|
||||||
|
export default {
|
||||||
|
setup() {
|
||||||
|
const columns = ref([
|
||||||
|
{
|
||||||
|
label: '日期',
|
||||||
|
prop: 'date',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '姓名',
|
||||||
|
prop: 'name',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '地址',
|
||||||
|
prop: 'address',
|
||||||
|
},
|
||||||
|
])
|
||||||
|
const data = ref([
|
||||||
|
{
|
||||||
|
date: '2016-05-03',
|
||||||
|
name: 'Tom',
|
||||||
|
address: 'No. 189, Grove St, Los Angeles',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
date: '2016-05-02',
|
||||||
|
name: 'Tom',
|
||||||
|
address: 'No. 189, Grove St, Los Angeles',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
date: '2016-05-04',
|
||||||
|
name: 'Tom',
|
||||||
|
address: 'No. 189, Grove St, Los Angeles',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
date: '2016-05-01',
|
||||||
|
name: 'Tom',
|
||||||
|
address: 'No. 189, Grove St, Los Angeles',
|
||||||
|
},
|
||||||
|
])
|
||||||
|
|
||||||
|
return {
|
||||||
|
data,
|
||||||
|
columns,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
:::
|
||||||
|
|
||||||
|
##### 多选
|
||||||
|
|
||||||
|
::: demo 通过配置 selection 显示多选框,支持 columns 的参数
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<ele-table
|
||||||
|
:data="data"
|
||||||
|
:columns="columns"
|
||||||
|
selection
|
||||||
|
/>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import { ref } from 'vue'
|
||||||
|
|
||||||
|
export default {
|
||||||
|
setup() {
|
||||||
|
const columns = ref([
|
||||||
|
{
|
||||||
|
label: '日期',
|
||||||
|
prop: 'date',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '姓名',
|
||||||
|
prop: 'name',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '地址',
|
||||||
|
prop: 'address',
|
||||||
|
},
|
||||||
|
])
|
||||||
|
const data = ref([
|
||||||
|
{
|
||||||
|
date: '2016-05-03',
|
||||||
|
name: 'Tom',
|
||||||
|
address: 'No. 189, Grove St, Los Angeles',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
date: '2016-05-02',
|
||||||
|
name: 'Tom',
|
||||||
|
address: 'No. 189, Grove St, Los Angeles',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
date: '2016-05-04',
|
||||||
|
name: 'Tom',
|
||||||
|
address: 'No. 189, Grove St, Los Angeles',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
date: '2016-05-01',
|
||||||
|
name: 'Tom',
|
||||||
|
address: 'No. 189, Grove St, Los Angeles',
|
||||||
|
},
|
||||||
|
])
|
||||||
|
|
||||||
|
return {
|
||||||
|
data,
|
||||||
|
columns,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
:::
|
||||||
|
|
||||||
|
##### 展开
|
||||||
|
|
||||||
|
::: demo 通过配置 expand 开启展开插槽,通过 #expand 插槽定制显示内容,支持 columns 的参数
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<ele-table
|
||||||
|
:data="data"
|
||||||
|
:columns="columns"
|
||||||
|
expand
|
||||||
|
>
|
||||||
|
<template #expand="{ row }">
|
||||||
|
{{ row }}
|
||||||
|
</template>
|
||||||
|
</ele-table>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import { ref } from 'vue'
|
||||||
|
|
||||||
|
export default {
|
||||||
|
setup() {
|
||||||
|
const columns = ref([
|
||||||
|
{
|
||||||
|
label: '日期',
|
||||||
|
prop: 'date',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '姓名',
|
||||||
|
prop: 'name',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '地址',
|
||||||
|
prop: 'address',
|
||||||
|
},
|
||||||
|
])
|
||||||
|
const data = ref([
|
||||||
|
{
|
||||||
|
date: '2016-05-03',
|
||||||
|
name: 'Tom',
|
||||||
|
address: 'No. 189, Grove St, Los Angeles',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
date: '2016-05-02',
|
||||||
|
name: 'Tom',
|
||||||
|
address: 'No. 189, Grove St, Los Angeles',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
date: '2016-05-04',
|
||||||
|
name: 'Tom',
|
||||||
|
address: 'No. 189, Grove St, Los Angeles',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
date: '2016-05-01',
|
||||||
|
name: 'Tom',
|
||||||
|
address: 'No. 189, Grove St, Los Angeles',
|
||||||
|
},
|
||||||
|
])
|
||||||
|
|
||||||
|
return {
|
||||||
|
data,
|
||||||
|
columns,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
:::
|
||||||
|
|
||||||
|
##### 操作
|
||||||
|
|
||||||
|
::: demo 通过配置 menu 开启按钮插槽,通过 #menu 插槽定制显示内容,支持 columns 的参数
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<ele-table
|
||||||
|
:data="data"
|
||||||
|
:columns="columns"
|
||||||
|
:menu="menu"
|
||||||
|
>
|
||||||
|
<template #menu="{ size }">
|
||||||
|
<el-button
|
||||||
|
:size="size"
|
||||||
|
type="text"
|
||||||
|
>
|
||||||
|
详情
|
||||||
|
</el-button>
|
||||||
|
</template>
|
||||||
|
</ele-table>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import { ref } from 'vue'
|
||||||
|
|
||||||
|
export default {
|
||||||
|
setup() {
|
||||||
|
const menu = ref({
|
||||||
|
label: '操作',
|
||||||
|
align: 'center',
|
||||||
|
})
|
||||||
|
const columns = ref([
|
||||||
|
{
|
||||||
|
label: '日期',
|
||||||
|
prop: 'date',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '姓名',
|
||||||
|
prop: 'name',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '地址',
|
||||||
|
prop: 'address',
|
||||||
|
},
|
||||||
|
])
|
||||||
|
const data = ref([
|
||||||
|
{
|
||||||
|
date: '2016-05-03',
|
||||||
|
name: 'Tom',
|
||||||
|
address: 'No. 189, Grove St, Los Angeles',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
date: '2016-05-02',
|
||||||
|
name: 'Tom',
|
||||||
|
address: 'No. 189, Grove St, Los Angeles',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
date: '2016-05-04',
|
||||||
|
name: 'Tom',
|
||||||
|
address: 'No. 189, Grove St, Los Angeles',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
date: '2016-05-01',
|
||||||
|
name: 'Tom',
|
||||||
|
address: 'No. 189, Grove St, Los Angeles',
|
||||||
|
},
|
||||||
|
])
|
||||||
|
|
||||||
|
return {
|
||||||
|
menu,
|
||||||
|
data,
|
||||||
|
columns,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
:::
|
||||||
|
|
||||||
|
##### 插槽
|
||||||
|
|
||||||
|
::: demo
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<ele-table
|
||||||
|
:data="data"
|
||||||
|
:columns="columns3"
|
||||||
|
>
|
||||||
|
<template #name-header="{ column }">
|
||||||
|
<s>{{ column.label }}</s>
|
||||||
|
</template>
|
||||||
|
<template #name="{ row, size }">
|
||||||
|
<el-tag :size="size">
|
||||||
|
{{ row?.name }}
|
||||||
|
</el-tag>
|
||||||
|
</template>
|
||||||
|
<template #menu="{ size }">
|
||||||
|
<el-button
|
||||||
|
:size="size"
|
||||||
|
type="text"
|
||||||
|
>
|
||||||
|
详情
|
||||||
|
</el-button>
|
||||||
|
</template>
|
||||||
|
</ele-table>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import { ref } from 'vue'
|
||||||
|
|
||||||
|
export default {
|
||||||
|
setup() {
|
||||||
|
const columns3 = ref([
|
||||||
|
{
|
||||||
|
label: '日期',
|
||||||
|
prop: 'date',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '姓名',
|
||||||
|
prop: 'name',
|
||||||
|
slot: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '地址',
|
||||||
|
prop: 'address',
|
||||||
|
},
|
||||||
|
])
|
||||||
|
const data = ref([
|
||||||
|
{
|
||||||
|
date: '2016-05-03',
|
||||||
|
name: 'Tom',
|
||||||
|
address: 'No. 189, Grove St, Los Angeles',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
date: '2016-05-02',
|
||||||
|
name: 'Tom',
|
||||||
|
address: 'No. 189, Grove St, Los Angeles',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
date: '2016-05-04',
|
||||||
|
name: 'Tom',
|
||||||
|
address: 'No. 189, Grove St, Los Angeles',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
date: '2016-05-01',
|
||||||
|
name: 'Tom',
|
||||||
|
address: 'No. 189, Grove St, Los Angeles',
|
||||||
|
},
|
||||||
|
])
|
||||||
|
|
||||||
|
return {
|
||||||
|
data,
|
||||||
|
columns3,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
:::
|
||||||
|
|
||||||
|
##### 分页
|
||||||
|
|
||||||
|
::: demo 当传入 total 数据时,将自动显示分页。可以通过 `v-model:current-page` 绑定当前页数、通过 `v-model:page-size` 绑定每页显示条目个数
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<ele-table
|
||||||
|
v-model:current-page="currentPage"
|
||||||
|
v-model:page-size="pageSize"
|
||||||
|
:data="data"
|
||||||
|
:columns="columns"
|
||||||
|
:total="total"
|
||||||
|
/>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import { ref } from 'vue'
|
||||||
|
|
||||||
|
export default {
|
||||||
|
setup() {
|
||||||
|
const currentPage = ref(1)
|
||||||
|
const pageSize = ref(10)
|
||||||
|
const total = ref(50)
|
||||||
|
const columns = ref([
|
||||||
|
{
|
||||||
|
label: '日期',
|
||||||
|
prop: 'date',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '姓名',
|
||||||
|
prop: 'name',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '地址',
|
||||||
|
prop: 'address',
|
||||||
|
},
|
||||||
|
])
|
||||||
|
const data = ref([
|
||||||
|
{
|
||||||
|
date: '2016-05-03',
|
||||||
|
name: 'Tom',
|
||||||
|
address: 'No. 189, Grove St, Los Angeles',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
date: '2016-05-02',
|
||||||
|
name: 'Tom',
|
||||||
|
address: 'No. 189, Grove St, Los Angeles',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
date: '2016-05-04',
|
||||||
|
name: 'Tom',
|
||||||
|
address: 'No. 189, Grove St, Los Angeles',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
date: '2016-05-01',
|
||||||
|
name: 'Tom',
|
||||||
|
address: 'No. 189, Grove St, Los Angeles',
|
||||||
|
},
|
||||||
|
])
|
||||||
|
|
||||||
|
return {
|
||||||
|
currentPage,
|
||||||
|
pageSize,
|
||||||
|
total,
|
||||||
|
data,
|
||||||
|
columns,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
:::
|
||||||
|
|
||||||
|
##### 多级
|
||||||
|
|
||||||
|
::: demo 通过 columns 的 `children` 配置多级表头
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<ele-table
|
||||||
|
:data="data"
|
||||||
|
:columns="columns2"
|
||||||
|
/>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import { ref } from 'vue'
|
||||||
|
|
||||||
|
export default {
|
||||||
|
setup() {
|
||||||
|
const columns2 = ref([
|
||||||
|
{
|
||||||
|
label: '日期',
|
||||||
|
prop: 'date',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '用户',
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
label: '姓名',
|
||||||
|
prop: 'name',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '地址',
|
||||||
|
prop: 'address',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
])
|
||||||
|
const data = ref([
|
||||||
|
{
|
||||||
|
date: '2016-05-03',
|
||||||
|
name: 'Tom',
|
||||||
|
address: 'No. 189, Grove St, Los Angeles',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
date: '2016-05-02',
|
||||||
|
name: 'Tom',
|
||||||
|
address: 'No. 189, Grove St, Los Angeles',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
date: '2016-05-04',
|
||||||
|
name: 'Tom',
|
||||||
|
address: 'No. 189, Grove St, Los Angeles',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
date: '2016-05-01',
|
||||||
|
name: 'Tom',
|
||||||
|
address: 'No. 189, Grove St, Los Angeles',
|
||||||
|
},
|
||||||
|
])
|
||||||
|
|
||||||
|
return {
|
||||||
|
data,
|
||||||
|
columns2,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
:::
|
||||||
|
|
||||||
|
##### 配置
|
||||||
|
|
||||||
|
| 参数 | 说明 | 类型 | 可选值 | 默认值 |
|
||||||
|
| :---------------------- | :------------------------------------------------------------------ | :------------------------------------------------------ | :----------------------------- | :--------------------------------------------------- |
|
||||||
|
| data | 显示的数据 | array | - | - |
|
||||||
|
| columns | 自动生成表单的参数,参考下面 columns | array | - | - |
|
||||||
|
| selection | 显示多选框,支持 columns 的配置 | boolean / object | - | false |
|
||||||
|
| index | 显示索引,支持 columns 的配置 | boolean / object | - | false |
|
||||||
|
| expand | 开启展开插槽,支持 columns 的配置 | boolean / object | - | false |
|
||||||
|
| menu | 开启操作按钮插槽,支持 columns 的配置 | boolean / object | - | false |
|
||||||
|
| show-overflow-tooltip | 当内容过长被隐藏时显示 tooltip | boolean | - | false |
|
||||||
|
| align | 对齐方式 | string | left / center / right | left |
|
||||||
|
| header-align | 表头对齐方式 | string | left / center / right | 同 align |
|
||||||
|
| total | 总条目数 | number | - | - |
|
||||||
|
| current-page | 当前页数,可以通过 `v-model:current-page` 绑定值 | number | - | - |
|
||||||
|
| page-size | 每页显示条目个数,可以通过 `v-model:page-size` 绑定值 | number | - | - |
|
||||||
|
| pagination | pagination 的配置,同 el-pagination | object | - | [参考全局配置](../guide/index#全局配置) |
|
||||||
|
| height | Table 的高度 | string / number | - | 自动高度 |
|
||||||
|
| max-height | Table 的最大高度 | string / number | - | - |
|
||||||
|
| stripe | 是否为斑马纹 table | boolean | - | false |
|
||||||
|
| border | 是否带有纵向边框 | boolean | - | false |
|
||||||
|
| size | Table 的尺寸 | string | medium / small / mini | - |
|
||||||
|
| fit | 列的宽度是否自撑开 | boolean | - | true |
|
||||||
|
| show-header | 是否显示表头 | boolean | - | true |
|
||||||
|
| highlight-current-row | 是否要高亮当前行 | boolean | - | false |
|
||||||
|
| current-row-key | 当前行的 key,只写属性 | string / number | - | - |
|
||||||
|
| row-class-name | 为行增加 className | Function({row, rowIndex}) / string | - | - |
|
||||||
|
| row-style | 为行增加 style | Function({row, rowIndex}) / object | - | - |
|
||||||
|
| cell-class-name | 为单元格增加 className | Function({row, column, rowIndex, columnIndex}) / string | - | - |
|
||||||
|
| cell-style | 为单元格增加 style | Function({row, column, rowIndex, columnIndex}) / object | - | - |
|
||||||
|
| header-row-class-name | 为表头行增加 className | Function({row, rowIndex}) / string | - | - |
|
||||||
|
| header-row-style | 为表头行增加 style | Function({row, rowIndex}) / object | - | - |
|
||||||
|
| header-cell-class-name | 为表头单元格增加 className | Function({row, column, rowIndex, columnIndex}) / string | - | - |
|
||||||
|
| header-cell-style | 为表头单元格增加 style | Function({row, column, rowIndex, columnIndex}) / object | - | - |
|
||||||
|
| row-key | 行数据的 Key,使用 reserveSelection 功能时必填 | Function(row) / string | - | - |
|
||||||
|
| empty-text | 空数据时显示的文本内容 | string | - | 暂无数据 |
|
||||||
|
| default-expand-all | 是否默认展开所有行 | boolean | - | false |
|
||||||
|
| expand-row-keys | Table 目前的展开行,与 row-key 配合使用 | array | - | - |
|
||||||
|
| default-sort | 默认的排序列的 prop 和顺序 | Object | `order`: ascending, descending | ascending |
|
||||||
|
| tooltip-effect | tooltip `effect` 属性 | String | dark / light | - |
|
||||||
|
| show-summary | 是否在表尾显示合计行 | Boolean | - | false |
|
||||||
|
| sum-text | 合计行第一列的文本 | String | - | 合计 |
|
||||||
|
| summary-method | 自定义的合计计算方法 | Function({ columns, data }) | - | - |
|
||||||
|
| span-method | 合并行或列的计算方法 | Function({ row, column, rowIndex, columnIndex }) | - | - |
|
||||||
|
| select-on-indeterminate | 当仅有部分行被选中时,点击表头的多选框时的行为,配合 selection 使用 | boolean | - | true |
|
||||||
|
| indent | 展示树形数据时,树节点的缩进 | number | - | 16 |
|
||||||
|
| lazy | 是否懒加载子节点数据 | boolean | - | - |
|
||||||
|
| load | 加载子节点数据的函数,lazy 为 true 时生效 | Function(row, treeNode, resolve) | - | - |
|
||||||
|
| tree-props | 渲染嵌套数据的配置选项 | Object | - | { hasChildren: 'hasChildren', children: 'children' } |
|
||||||
|
|
||||||
|
##### 参数
|
||||||
|
|
||||||
|
| 参数 | 说明 | 类型 | 可选值 | 默认值 |
|
||||||
|
| :------------------ | :-------------------------------------------------------------------- | :-------------------------------------- | :------------------------------------------------------------------------------------------------------------------------------ | :-------------------------------- |
|
||||||
|
| prop | 对应 data 的字段名 (**必填,需要是唯一值**) | string | - | - |
|
||||||
|
| label | 显示的标题 | string | - | - |
|
||||||
|
| slot | 是否开启自定义插槽功能 | boolean | - | false |
|
||||||
|
| hide | 是否在表格中隐藏 | boolean | - | false |
|
||||||
|
| children | 实现多级表头 | array | - | - |
|
||||||
|
| columnKey | 当前项的 key,使用 filter-change 事件时需要 | string | - | - |
|
||||||
|
| width | 对应列的宽度 | string | - | - |
|
||||||
|
| minWidth | 对应列的最小宽度 | string | - | - |
|
||||||
|
| fixed | 列是否固定,true 表示固定在左侧 | string / boolean | true / left / right | - |
|
||||||
|
| renderHeader | 列标题 Label 区域渲染使用的 Function | Function(h, { column, $index }) | - | - |
|
||||||
|
| sortable | 对应列是否可以排序 | boolean / string | true / false / 'custom' | false |
|
||||||
|
| sortMethod | 对数据进行排序的时候使用的方法 | Function(a, b) | - | - |
|
||||||
|
| sortBy | 指定数据按照哪个属性进行排序 | string / array / Function(row, index) | - | - |
|
||||||
|
| sortOrders | 数据在排序时所使用排序策略的轮转顺序 | array | `ascending` 表示升序,`descending` 表示降序,`null` 表示还原为原始顺序 | ['ascending', 'descending', null] |
|
||||||
|
| resizable | 对应列是否可以通过拖动改变宽度,配合 border 使用 | boolean | - | true |
|
||||||
|
| formatter | 用来格式化内容 | Function(row, column, cellValue, index) | - | - |
|
||||||
|
| showOverflowTooltip | 当内容过长被隐藏时显示 tooltip | Boolean | - | false |
|
||||||
|
| align | 对齐方式 | string | left / center / right | left |
|
||||||
|
| headerAlign | 表头对齐方式 | string | left / center / right | 同 align |
|
||||||
|
| className | 列的 className | string | - | - |
|
||||||
|
| labelClassName | 当前列标题的自定义类名 | string | - | - |
|
||||||
|
| filters | 数据过滤的选项 | Array[{ text, value }] | - | - |
|
||||||
|
| filterPlacement | 过滤弹出框的定位 | string | top / top-start / top-end / bottom / bottom-start / bottom-end / left / left-start / left-end / right / right-start / right-end | - |
|
||||||
|
| filterMultiple | 数据过滤的选项是否多选 | boolean | - | true |
|
||||||
|
| filterMethod | 数据过滤使用的方法 | Function(value, row, column) | - | - |
|
||||||
|
| filteredValue | 选中的数据过滤项 | array | - | - |
|
||||||
|
| index | 自定义索引,只能够在 index 中配置 | Function(index) / number | - | - |
|
||||||
|
| selectable | 这一行的 CheckBox 是否可以勾选,只能够在 selection 中配置 | Function(row, index) | - | - |
|
||||||
|
| reserveSelection | 是否保留之前选中的数据(需指定 `row-key`),只能够在 selection 中配置 | boolean | - | false |
|
||||||
|
|
||||||
|
##### 事件
|
||||||
|
|
||||||
|
| 事件名 | 说明 | 参数 |
|
||||||
|
| ------------------ | -------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------- |
|
||||||
|
| select | 当用户手动勾选数据行的 Checkbox 时触发的事件 | selection, row |
|
||||||
|
| select-all | 当用户手动勾选全选 Checkbox 时触发的事件 | selection |
|
||||||
|
| selection-change | 当选择项发生变化时会触发该事件 | selection |
|
||||||
|
| cell-mouse-enter | 当单元格 hover 进入时会触发该事件 | row, column, cell, event |
|
||||||
|
| cell-mouse-leave | 当单元格 hover 退出时会触发该事件 | row, column, cell, event |
|
||||||
|
| cell-click | 当某个单元格被点击时会触发该事件 | row, column, cell, event |
|
||||||
|
| cell-dblclick | 当某个单元格被双击击时会触发该事件 | row, column, cell, event |
|
||||||
|
| row-click | 当某一行被点击时会触发该事件 | row, column, event |
|
||||||
|
| row-contextmenu | 当某一行被鼠标右键点击时会触发该事件 | row, column, event |
|
||||||
|
| row-dblclick | 当某一行被双击时会触发该事件 | row, column, event |
|
||||||
|
| header-click | 当某一列的表头被点击时会触发该事件 | column, event |
|
||||||
|
| header-contextmenu | 当某一列的表头被鼠标右键点击时触发该事件 | column, event |
|
||||||
|
| sort-change | 当表格的排序条件发生变化的时候会触发该事件 | { column, prop, order } |
|
||||||
|
| filter-change | 当表格的筛选条件发生变化的时候会触发该事件,参数的值是一个对象,对象的 key 是 column 的 columnKey,对应的 value 为用户选择的筛选条件的数组。 | filters |
|
||||||
|
| current-change | 当表格的当前行发生变化的时候会触发该事件,如果要高亮当前行,请打开表格的 highlight-current-row 属性 | currentRow, oldCurrentRow |
|
||||||
|
| header-dragend | 当拖动表头改变了列的宽度的时候会触发该事件 | newWidth, oldWidth, column, event |
|
||||||
|
| expand-change | 当用户对某一行展开或者关闭的时候会触发该事件(展开行时,回调的第二个参数为 expandedRows;树形表格时第二参数为 expanded) | row, (expandedRows \| expanded) |
|
||||||
|
| size-change | pageSize 改变时会触发 | 每页条数 |
|
||||||
|
| current-change | currentPage 改变时会触发 | 当前页 |
|
||||||
|
| prev-click | 用户点击上一页按钮改变当前页后触发 | 当前页 |
|
||||||
|
| next-click | 用户点击下一页按钮改变当前页后触发 | 当前页 |
|
||||||
|
|
||||||
|
##### 方法
|
||||||
|
|
||||||
|
| 方法名 | 说明 | 参数 |
|
||||||
|
| ------------------ | ----------------------------------------------------------------------------------------------------------------------- | --------------------------- |
|
||||||
|
| clearSelection | 用于多选表格,清空用户的选择 | - |
|
||||||
|
| toggleRowSelection | 用于多选表格,切换某一行的选中状态,如果使用了第二个参数,则是设置这一行选中与否(selected 为 true 则选中) | row, selected |
|
||||||
|
| toggleAllSelection | 用于多选表格,切换全选和全不选 | - |
|
||||||
|
| toggleRowExpansion | 用于可展开表格与树形表格,切换某一行的展开状态,如果使用了第二个参数,则是设置这一行展开与否(expanded 为 true 则展开) | row, expanded |
|
||||||
|
| setCurrentRow | 用于单选表格,设定某一行为选中行,如果调用时不加参数,则会取消目前高亮行的选中状态。 | row |
|
||||||
|
| clearSort | 用于清空排序条件,数据会恢复成未排序的状态 | - |
|
||||||
|
| clearFilter | 不传入参数时用于清空所有过滤条件,数据会恢复成未过滤的状态,也可传入由 columnKey 组成的数组以清除指定列的过滤条件 | columnKey |
|
||||||
|
| doLayout | 对 Table 进行重新布局。当 Table 或其祖先元素由隐藏切换为显示时,可能需要调用此方法 | - |
|
||||||
|
| sort | 手动对 Table 进行排序。参数`prop`属性指定排序列,`order`指定排序顺序。 | prop: string, order: string |
|
||||||
|
|
||||||
|
::: tip 提示
|
||||||
|
如果使用 `typescript` 可以从组件中导出 `ITableExpose` 提供更好的类型推导
|
||||||
|
:::
|
||||||
|
|
||||||
|
### 插槽
|
||||||
|
|
||||||
|
| name | 说明 |
|
||||||
|
| :------------ | :----------------------------------------------------------------------- |
|
||||||
|
| - | 在右侧菜单前插入的任意内容 |
|
||||||
|
| menu | 表格右侧自定义按钮,参数为 { size, row, column, $index } |
|
||||||
|
| expand | 当 expand 为 true 时,配置展开显示的内容,参数为 { row, column, $index } |
|
||||||
|
| append | 插入至表格最后一行之后的内容 |
|
||||||
|
| [prop] | 当前这列的内容,参数为 { size, row, column, $index } |
|
||||||
|
| [prop]-header | 当前这列表头的内容,参数为 { size, column, $index } |
|
||||||
|
|
||||||
|
::: tip 提示
|
||||||
|
[prop] 为 columns 中定义的 prop
|
||||||
|
:::
|
1
docs/docs/en-US/guide/home.md
Normal file
1
docs/docs/en-US/guide/home.md
Normal file
@ -0,0 +1 @@
|
|||||||
|
##### 介绍
|
5
docs/docs/en-US/guide/index.md
Normal file
5
docs/docs/en-US/guide/index.md
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
##### 安装
|
||||||
|
|
||||||
|
```
|
||||||
|
npm install layui-vue --save
|
||||||
|
```
|
32
docs/docs/zh-CN/components/button.md
Normal file
32
docs/docs/zh-CN/components/button.md
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
##### 基础
|
||||||
|
|
||||||
|
::: demo 传入 columns 数据,自动生成表格
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<lay-button type="primary">原始按钮</lay-button>
|
||||||
|
<lay-button type="default">默认按钮</lay-button>
|
||||||
|
<lay-button type="normal">百搭按钮</lay-button>
|
||||||
|
<lay-button type="warm">暖色按钮</lay-button>
|
||||||
|
<lay-button type="danger">警告按钮</lay-button>
|
||||||
|
<lay-button type="disabled">禁用按钮</lay-button>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import { ref } from 'vue'
|
||||||
|
|
||||||
|
export default {
|
||||||
|
setup() {
|
||||||
|
|
||||||
|
return {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
:::
|
||||||
|
|
||||||
|
#### 插槽
|
||||||
|
|
||||||
|
| name | 说明 |
|
||||||
|
| :------------ | :----------------------------------------------------------------------- |
|
||||||
|
| type | 按钮类型 |
|
1
docs/docs/zh-CN/guide/home.md
Normal file
1
docs/docs/zh-CN/guide/home.md
Normal file
@ -0,0 +1 @@
|
|||||||
|
##### 介绍
|
5
docs/docs/zh-CN/guide/index.md
Normal file
5
docs/docs/zh-CN/guide/index.md
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
##### 安装
|
||||||
|
|
||||||
|
```
|
||||||
|
npm install layui-vue --save
|
||||||
|
```
|
23
docs/index.html
Normal file
23
docs/index.html
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8" />
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||||
|
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1" />
|
||||||
|
<meta name="renderer" content="webkit" />
|
||||||
|
<meta name="force-rendering" content="webkit" />
|
||||||
|
<meta name="applicable-device" content="pc,mobile" />
|
||||||
|
<meta name="author" content="Jmys <jmys1992@gmail.com>" />
|
||||||
|
<meta
|
||||||
|
name="keywords"
|
||||||
|
content="element-pro,pro-components,admin,element-plus,components,vue,ui"
|
||||||
|
/>
|
||||||
|
<link rel="icon" href="/favicon.ico" />
|
||||||
|
<title></title>
|
||||||
|
<!--preload-links-->
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div id="app"><!--app-html--></div>
|
||||||
|
<script type="module" src="/src/entry-client.ts"></script>
|
||||||
|
</body>
|
||||||
|
</html>
|
47
docs/prerender.js
Normal file
47
docs/prerender.js
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
/* eslint-disable @typescript-eslint/no-var-requires */
|
||||||
|
const fs = require('fs')
|
||||||
|
const path = require('path')
|
||||||
|
|
||||||
|
const toAbsolute = (p) => path.resolve(__dirname, p).replace(/\\/, '/')
|
||||||
|
|
||||||
|
const manifest = require('./dist/static/ssr-manifest.json')
|
||||||
|
const template = fs.readFileSync(toAbsolute('dist/static/index.html'), 'utf-8')
|
||||||
|
const { render } = require('./dist/server/entry-server.js')
|
||||||
|
|
||||||
|
const writeFileRecursive = function (path, buffer) {
|
||||||
|
const lastPath = path.substring(0, path.lastIndexOf('/'))
|
||||||
|
|
||||||
|
fs.mkdir(lastPath, { recursive: true }, () => {
|
||||||
|
fs.writeFileSync(path, buffer)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
const fileDisplay = (file) => {
|
||||||
|
fs.readdirSync(toAbsolute(file)).forEach(async (filename) => {
|
||||||
|
const filedir = path.join(file, filename).replace(/\\/, '/')
|
||||||
|
|
||||||
|
if (fs.statSync(toAbsolute(filedir)).isDirectory()) {
|
||||||
|
fileDisplay(filedir)
|
||||||
|
} else {
|
||||||
|
const url = filedir
|
||||||
|
.replace(/^docs/, '')
|
||||||
|
.replace(/\.(vue|md)$/, '')
|
||||||
|
.replace(/index$/, '')
|
||||||
|
.replace(/\/([^/]*)$/, (item) =>
|
||||||
|
item.replace(/\B([A-Z])/g, '-$1').toLowerCase()
|
||||||
|
)
|
||||||
|
const [appHtml, preloadLinks] = await render(url, manifest)
|
||||||
|
const html = template
|
||||||
|
.replace('<!--preload-links-->', preloadLinks)
|
||||||
|
.replace('<!--app-html-->', appHtml)
|
||||||
|
|
||||||
|
const filePath = `dist/static${url.replace(/\/$/, '/index')}.html`
|
||||||
|
writeFileRecursive(toAbsolute(filePath), html)
|
||||||
|
console.log('pre-rendered:', filePath)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
fileDisplay('docs')
|
||||||
|
|
||||||
|
fs.unlinkSync(toAbsolute('dist/static/ssr-manifest.json'))
|
BIN
docs/public/favicon.ico
Normal file
BIN
docs/public/favicon.ico
Normal file
Binary file not shown.
After Width: | Height: | Size: 4.2 KiB |
3
docs/src/App.vue
Normal file
3
docs/src/App.vue
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
<template>
|
||||||
|
<router-view />
|
||||||
|
</template>
|
152
docs/src/components/LayCode.vue
Normal file
152
docs/src/components/LayCode.vue
Normal file
@ -0,0 +1,152 @@
|
|||||||
|
<template>
|
||||||
|
<div class="lay-code">
|
||||||
|
<div class="source">
|
||||||
|
<slot />
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
ref="meta"
|
||||||
|
class="meta"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
v-if="$slots.description"
|
||||||
|
class="description"
|
||||||
|
>
|
||||||
|
<slot name="description" />
|
||||||
|
</div>
|
||||||
|
<div class="language-html">
|
||||||
|
<slot name="code" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
:class="{ 'is-fixed': isFixContorl }"
|
||||||
|
class="control"
|
||||||
|
@click="toggleShow"
|
||||||
|
>
|
||||||
|
<i :class="[show ? 'el-icon-caret-top' : 'el-icon-caret-bottom']" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { onMounted, onUnmounted, ref, watch } from 'vue'
|
||||||
|
|
||||||
|
const meta = ref<HTMLElement>({} as HTMLElement)
|
||||||
|
const isFixContorl = ref(false)
|
||||||
|
const codeAreaHeight = ref(0)
|
||||||
|
|
||||||
|
const show = ref(false);
|
||||||
|
|
||||||
|
const toggleShow = function() {
|
||||||
|
show.value = !show.value;
|
||||||
|
}
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
const foundDescs = meta.value.getElementsByClassName('description')
|
||||||
|
const foundCodes = meta.value.getElementsByClassName('language-html')
|
||||||
|
|
||||||
|
if (foundDescs.length) {
|
||||||
|
codeAreaHeight.value =
|
||||||
|
foundDescs[0].clientHeight + foundCodes[0].clientHeight + 30
|
||||||
|
} else {
|
||||||
|
codeAreaHeight.value = foundCodes[0].clientHeight + 20
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
onUnmounted(() => {
|
||||||
|
window.removeEventListener('scroll', handleScroll)
|
||||||
|
})
|
||||||
|
|
||||||
|
watch(show, (value) => {
|
||||||
|
if (value) {
|
||||||
|
meta.value.style.height = `${codeAreaHeight.value}px`
|
||||||
|
window.addEventListener('scroll', handleScroll)
|
||||||
|
setTimeout(handleScroll, 100)
|
||||||
|
} else {
|
||||||
|
meta.value.style.height = '0'
|
||||||
|
window.removeEventListener('scroll', handleScroll)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
function handleScroll() {
|
||||||
|
const { top, bottom } = meta.value.getBoundingClientRect()
|
||||||
|
isFixContorl.value =
|
||||||
|
bottom > window.innerHeight && top + 44 <= window.innerHeight
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
.lay-code {
|
||||||
|
margin: 1rem 0;
|
||||||
|
border: 1px solid whitesmoke;
|
||||||
|
border-radius: 3px;
|
||||||
|
background: var(--c-bg);
|
||||||
|
transition: all 0.2s;
|
||||||
|
}
|
||||||
|
.lay-code:hover {
|
||||||
|
box-shadow: var(--shadow-2);
|
||||||
|
}
|
||||||
|
.lay-code .source {
|
||||||
|
padding: 24px;
|
||||||
|
}
|
||||||
|
.lay-code .meta {
|
||||||
|
padding: 0 10px;
|
||||||
|
height: 0;
|
||||||
|
background-color: var(--c-page-background);
|
||||||
|
overflow: hidden;
|
||||||
|
transition: height 0.2s;
|
||||||
|
}
|
||||||
|
.lay-code .meta .description {
|
||||||
|
padding: 20px;
|
||||||
|
margin: 10px 0;
|
||||||
|
border: 1px solid var(--c-divider);
|
||||||
|
box-sizing: border-box;
|
||||||
|
background: var(--c-bg);
|
||||||
|
font-size: 14px;
|
||||||
|
line-height: 22px;
|
||||||
|
color: var(--c-text-light-1);
|
||||||
|
word-break: break-word;
|
||||||
|
}
|
||||||
|
.lay-code .meta .description p {
|
||||||
|
margin: 0 !important;
|
||||||
|
line-height: 26px !important;
|
||||||
|
}
|
||||||
|
.lay-code .meta .description code {
|
||||||
|
display: inline-block;
|
||||||
|
padding: 1px 5px;
|
||||||
|
margin: 0 4px;
|
||||||
|
height: 18px;
|
||||||
|
border-radius: 3px;
|
||||||
|
background-color: var(--code-inline-bg-color);
|
||||||
|
font-size: 12px;
|
||||||
|
line-height: 18px;
|
||||||
|
color: var(--c-text-light);
|
||||||
|
}
|
||||||
|
.lay-code .control {
|
||||||
|
height: 44px;
|
||||||
|
box-sizing: border-box;
|
||||||
|
border-top: 1px solid whitesmoke;
|
||||||
|
border-bottom-left-radius: 4px;
|
||||||
|
border-bottom-right-radius: 4px;
|
||||||
|
background: var(--c-bg);
|
||||||
|
text-align: center;
|
||||||
|
color: var(--c-text);
|
||||||
|
cursor: pointer;
|
||||||
|
width: 100%;
|
||||||
|
user-select: none;
|
||||||
|
}
|
||||||
|
.lay-code .control.is-fixed {
|
||||||
|
position: sticky;
|
||||||
|
z-index: 11;
|
||||||
|
bottom: 0;
|
||||||
|
}
|
||||||
|
.lay-code .control:hover {
|
||||||
|
background-color: var(--c-page-background);
|
||||||
|
color: var(--c-brand);
|
||||||
|
}
|
||||||
|
.lay-code .control > i {
|
||||||
|
display: inline-block;
|
||||||
|
font-size: 16px;
|
||||||
|
line-height: 44px;
|
||||||
|
transition: all 0.3s;
|
||||||
|
}
|
||||||
|
</style>
|
7
docs/src/entry-client.ts
Normal file
7
docs/src/entry-client.ts
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
import { createApp } from './main'
|
||||||
|
|
||||||
|
const { app, router } = createApp()
|
||||||
|
|
||||||
|
router.isReady().then(() => {
|
||||||
|
app.mount('#app')
|
||||||
|
})
|
51
docs/src/entry-server.ts
Normal file
51
docs/src/entry-server.ts
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
import { createApp } from './main'
|
||||||
|
import { renderToString } from '@vue/server-renderer'
|
||||||
|
|
||||||
|
export async function render(url, manifest): Promise<string[]> {
|
||||||
|
const { app, router } = createApp()
|
||||||
|
|
||||||
|
// set the router to the desired URL before rendering
|
||||||
|
router.push(url)
|
||||||
|
await router.isReady()
|
||||||
|
|
||||||
|
// passing SSR context object which will be available via useSSRContext()
|
||||||
|
// @vitejs/plugin-vue injects code into a component's setup() that registers
|
||||||
|
// itself on ctx.modules. After the render, ctx.modules would contain all the
|
||||||
|
// components that have been instantiated during this render call.
|
||||||
|
const ctx = {}
|
||||||
|
const html = await renderToString(app, ctx)
|
||||||
|
|
||||||
|
// the SSR manifest generated by Vite contains module -> chunk/asset mapping
|
||||||
|
// which we can then use to determine what files need to be preloaded for this
|
||||||
|
// request.
|
||||||
|
const preloadLinks = renderPreloadLinks(ctx.modules, manifest)
|
||||||
|
return [html, preloadLinks]
|
||||||
|
}
|
||||||
|
|
||||||
|
function renderPreloadLinks(modules, manifest) {
|
||||||
|
let links = ''
|
||||||
|
const seen = new Set()
|
||||||
|
modules.forEach((id) => {
|
||||||
|
const files = manifest[id]
|
||||||
|
if (files) {
|
||||||
|
files.forEach((file) => {
|
||||||
|
if (!seen.has(file)) {
|
||||||
|
seen.add(file)
|
||||||
|
links += renderPreloadLink(file)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
})
|
||||||
|
return links
|
||||||
|
}
|
||||||
|
|
||||||
|
function renderPreloadLink(file) {
|
||||||
|
if (file.endsWith('.js')) {
|
||||||
|
return `<link rel="modulepreload" crossorigin href="${file}">`
|
||||||
|
} else if (file.endsWith('.css')) {
|
||||||
|
return `<link rel="stylesheet" href="${file}">`
|
||||||
|
} else {
|
||||||
|
// TODO
|
||||||
|
return ''
|
||||||
|
}
|
||||||
|
}
|
25
docs/src/layouts/Layout.vue
Normal file
25
docs/src/layouts/Layout.vue
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
<template>
|
||||||
|
<lay-layout>
|
||||||
|
<lay-header>
|
||||||
|
<lay-logo>layui-logo</lay-logo>
|
||||||
|
</lay-header>
|
||||||
|
<lay-side>
|
||||||
|
<router-link to="/zh-CN/components/layout">布局</router-link>
|
||||||
|
<router-link to="/zh-CN/components/button">按钮</router-link>
|
||||||
|
</lay-side>
|
||||||
|
<lay-body>
|
||||||
|
<div style="padding: 20px">
|
||||||
|
<router-view></router-view>
|
||||||
|
</div>
|
||||||
|
</lay-body>
|
||||||
|
<lay-footer></lay-footer>
|
||||||
|
</lay-layout>
|
||||||
|
</template>
|
||||||
|
<script>
|
||||||
|
import { ref } from 'vue'
|
||||||
|
export default {
|
||||||
|
setup() {
|
||||||
|
return {}
|
||||||
|
},
|
||||||
|
}
|
||||||
|
</script>
|
25
docs/src/main.ts
Normal file
25
docs/src/main.ts
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
import Layout from './App.vue'
|
||||||
|
import { App, createApp as _createApp, createSSRApp } from 'vue'
|
||||||
|
import { createRouter } from './router/index'
|
||||||
|
import { Router } from 'vue-router'
|
||||||
|
import Layui from '/@src/index'
|
||||||
|
import LayCode from './components/LayCode.vue'
|
||||||
|
import './styles/index.css'
|
||||||
|
|
||||||
|
export function createApp(): {
|
||||||
|
app: App<Element>
|
||||||
|
router: Router
|
||||||
|
} {
|
||||||
|
const app =
|
||||||
|
import.meta.env.MODE === 'production'
|
||||||
|
? createSSRApp(Layout)
|
||||||
|
: _createApp(Layout)
|
||||||
|
const router = createRouter()
|
||||||
|
|
||||||
|
app
|
||||||
|
.use(router)
|
||||||
|
.component('LayCode', LayCode)
|
||||||
|
.use(Layui)
|
||||||
|
|
||||||
|
return { app, router }
|
||||||
|
}
|
47
docs/src/plugin/common-plugins.ts
Normal file
47
docs/src/plugin/common-plugins.ts
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
import vue from '@vitejs/plugin-vue'
|
||||||
|
import Markdown from 'vite-plugin-md'
|
||||||
|
import container from 'markdown-it-container'
|
||||||
|
import highlight from './highlight'
|
||||||
|
import snippet from './snippet'
|
||||||
|
import demo from './demo'
|
||||||
|
import createContainer from './create-container'
|
||||||
|
import preWrapper from './pre-wrapper'
|
||||||
|
import type Token from 'markdown-it/lib/token'
|
||||||
|
|
||||||
|
const plugins = [
|
||||||
|
vue({
|
||||||
|
include: [/\.vue$/, /\.md$/],
|
||||||
|
}),
|
||||||
|
Markdown({
|
||||||
|
markdownItOptions: {
|
||||||
|
html: true,
|
||||||
|
linkify: true,
|
||||||
|
typographer: true,
|
||||||
|
highlight,
|
||||||
|
},
|
||||||
|
markdownItSetup(md) {
|
||||||
|
md.use(snippet)
|
||||||
|
.use(preWrapper)
|
||||||
|
.use(container, 'demo', demo)
|
||||||
|
.use(...createContainer('tip', 'TIP'))
|
||||||
|
.use(...createContainer('warning', 'WARNING'))
|
||||||
|
.use(...createContainer('danger', 'WARNING'))
|
||||||
|
.use(container, 'v-pre', {
|
||||||
|
render: (tokens: Token[], idx: number) =>
|
||||||
|
tokens[idx].nesting === 1 ? '<div v-pre>\n' : '</div>\n',
|
||||||
|
})
|
||||||
|
.use(container, 'details', {
|
||||||
|
render: (tokens: Token[], idx: number) => {
|
||||||
|
const info = tokens[idx].info.trim().slice(7).trim() // 7 = 'details'.length
|
||||||
|
return tokens[idx].nesting === 1
|
||||||
|
? `<details class="custom-block details">${
|
||||||
|
info ? `<summary>${info}</summary>` : ''
|
||||||
|
}\n`
|
||||||
|
: '</details>'
|
||||||
|
},
|
||||||
|
})
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
]
|
||||||
|
|
||||||
|
export default plugins
|
33
docs/src/plugin/create-container.ts
Normal file
33
docs/src/plugin/create-container.ts
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
import container from 'markdown-it-container'
|
||||||
|
import type Token from 'markdown-it/lib/token'
|
||||||
|
|
||||||
|
type ContainerArgs = [
|
||||||
|
typeof container,
|
||||||
|
string,
|
||||||
|
{
|
||||||
|
render(tokens: Token[], idx: number): string
|
||||||
|
}
|
||||||
|
]
|
||||||
|
|
||||||
|
export default function createContainer(
|
||||||
|
klass: string,
|
||||||
|
defaultTitle: string
|
||||||
|
): ContainerArgs {
|
||||||
|
return [
|
||||||
|
container,
|
||||||
|
klass,
|
||||||
|
{
|
||||||
|
render(tokens, idx) {
|
||||||
|
const token = tokens[idx]
|
||||||
|
const info = token.info.trim().slice(klass.length).trim()
|
||||||
|
if (token.nesting === 1) {
|
||||||
|
return `<div class="${klass} custom-block"><p class="custom-block-title">${
|
||||||
|
info || defaultTitle
|
||||||
|
}</p>\n`
|
||||||
|
} else {
|
||||||
|
return '</div>\n'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
},
|
||||||
|
]
|
||||||
|
}
|
146
docs/src/plugin/demo.ts
Normal file
146
docs/src/plugin/demo.ts
Normal file
@ -0,0 +1,146 @@
|
|||||||
|
import markdown from 'markdown-it'
|
||||||
|
import highlight from './highlight'
|
||||||
|
import type Token from 'markdown-it/lib/token'
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Combine the script content
|
||||||
|
* @param {string} script script string
|
||||||
|
*/
|
||||||
|
function assignScript(script: string) {
|
||||||
|
const dependencies = {} as Record<string, string[]>
|
||||||
|
const attrs = {} as Record<string, string>
|
||||||
|
const content = script
|
||||||
|
// import { ref } from 'vue' -> ''
|
||||||
|
.replace(/import\s?\{.*\}.*/g, (item) => {
|
||||||
|
const key = getInnerString(item.replace(/'/g, '"'), '"', '"')
|
||||||
|
const value = getInnerString(item.replace(/\s+/g, ''), '{', '}')
|
||||||
|
const list = value ? value.split(',') : []
|
||||||
|
if (key && dependencies[key]) {
|
||||||
|
dependencies[key] = dependencies[key].concat(list)
|
||||||
|
} else if (key) {
|
||||||
|
dependencies[key] = list
|
||||||
|
}
|
||||||
|
return ''
|
||||||
|
})
|
||||||
|
/**
|
||||||
|
* const -> let
|
||||||
|
*
|
||||||
|
* const a = -> let a =
|
||||||
|
* const a = -> a =
|
||||||
|
*/
|
||||||
|
.replace(/(const|let|var)\s\w*\s?=/g, (item) => {
|
||||||
|
const attr = getInnerString(item, '\\s', '\\s?=')
|
||||||
|
if (attr && !(attr in attrs)) {
|
||||||
|
attrs[attr] = attr
|
||||||
|
return `let ${attr} =`
|
||||||
|
} else {
|
||||||
|
return attr + ' ='
|
||||||
|
}
|
||||||
|
})
|
||||||
|
// Remove extra line breaks
|
||||||
|
.replace(/\n+/gm, '\n')
|
||||||
|
// Combine the import
|
||||||
|
const reImport = Object.keys(dependencies).reduce((all, item) => {
|
||||||
|
const filterAttrs = [...new Set(dependencies[item])]
|
||||||
|
return all + `import {${filterAttrs + ','}} from '${item}';\n`
|
||||||
|
}, '')
|
||||||
|
|
||||||
|
return reImport + content
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Extract part of the new string from the middle of the string
|
||||||
|
* @param {string} string string
|
||||||
|
* @param {string} prefix RegExp string
|
||||||
|
* @param {string} postfix RegExp string
|
||||||
|
* @param {string} type g | m | i
|
||||||
|
*/
|
||||||
|
function getInnerString(
|
||||||
|
string: string,
|
||||||
|
prefix: string,
|
||||||
|
postfix = '',
|
||||||
|
type: 'i' | 'g' | 'm' = 'i'
|
||||||
|
): string | undefined {
|
||||||
|
const result = new RegExp(`${prefix}(.*)${postfix}`, type)
|
||||||
|
const match = string.match(result)
|
||||||
|
return match ? match[1].trim() : undefined
|
||||||
|
}
|
||||||
|
|
||||||
|
let script = '' // Record the <script> label of the current page
|
||||||
|
|
||||||
|
export default {
|
||||||
|
render: (tokens: Token[], idx: number): string => {
|
||||||
|
// the `demo` block of the current page
|
||||||
|
const htmlBlock = tokens.filter((item) => item.type === 'html_block')
|
||||||
|
const { nesting, info = '', map } = tokens[idx]
|
||||||
|
|
||||||
|
if (nesting === -1) {
|
||||||
|
return '</lay-code>'
|
||||||
|
}
|
||||||
|
|
||||||
|
const matchedInfo = info.trim().match(/^demo\s+(.*)$/)
|
||||||
|
const description = matchedInfo && matchedInfo[1]
|
||||||
|
const descTemplate = markdown().render(description || '')
|
||||||
|
let str = '' // copy the current `demo` block code
|
||||||
|
let lastLine = NaN
|
||||||
|
|
||||||
|
for (let i = 0; i < htmlBlock.length; i++) {
|
||||||
|
const item = htmlBlock[i]
|
||||||
|
|
||||||
|
if (item.map && map && item.map[0] >= map[0] && item.map[1] <= map[1]) {
|
||||||
|
const { map, content } = item
|
||||||
|
const delta = map[0] - (lastLine || map[1])
|
||||||
|
|
||||||
|
if (delta > 0) {
|
||||||
|
str += '\n'.repeat(delta)
|
||||||
|
}
|
||||||
|
str += content
|
||||||
|
lastLine = map[1]
|
||||||
|
if (i === 0) {
|
||||||
|
script = ''
|
||||||
|
}
|
||||||
|
// Remove top <template>
|
||||||
|
if (/^<template>/.test(content)) {
|
||||||
|
const reContent = content.match(/^<template>((\s|\S)*)<\/template>/m)
|
||||||
|
|
||||||
|
htmlBlock[i].content = (reContent && reContent[1]) || ''
|
||||||
|
}
|
||||||
|
// Extract the <script> label content
|
||||||
|
if (content.includes('<script')) {
|
||||||
|
if (/export\sdefault\s?\{/m.test(content)) {
|
||||||
|
const setup = content.match(
|
||||||
|
/setup\s?\(\)\s?\{((\s|\S)*)return\s?\{/m
|
||||||
|
)
|
||||||
|
const reContent = content.replace(
|
||||||
|
/export\sdefault\s?\{((\s|\S)*)\}/m,
|
||||||
|
(setup && setup[1]) || ''
|
||||||
|
)
|
||||||
|
const reScript = reContent.match(
|
||||||
|
/^<script\s?.*?>((\s|\S)*)<\/script>/m
|
||||||
|
)
|
||||||
|
script += (reScript && reScript[1]) || ''
|
||||||
|
} else {
|
||||||
|
const reScript = content.match(
|
||||||
|
/^<script\s?.*?>((\s|\S)*)<\/script>/m
|
||||||
|
)
|
||||||
|
script += (reScript && reScript[1]) || ''
|
||||||
|
}
|
||||||
|
htmlBlock[i].content = ''
|
||||||
|
}
|
||||||
|
// Change the last content to <script> of the current page
|
||||||
|
if (i + 1 === htmlBlock.length) {
|
||||||
|
htmlBlock[i].content = `
|
||||||
|
<script setup>
|
||||||
|
${assignScript(script)}
|
||||||
|
</script>`
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return `
|
||||||
|
<lay-code>
|
||||||
|
${description ? `<template #description>${descTemplate}</template>` : ''}
|
||||||
|
<template #code>${highlight(str, 'vue')}</template>
|
||||||
|
`
|
||||||
|
},
|
||||||
|
}
|
46
docs/src/plugin/highlight.ts
Normal file
46
docs/src/plugin/highlight.ts
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
// copy from [vitepress](https://github.com/vuejs/vitepress)
|
||||||
|
import prism from 'prismjs'
|
||||||
|
import loadLanguages from 'prismjs/components/index'
|
||||||
|
import escapeHtml from 'escape-html'
|
||||||
|
|
||||||
|
// required to make embedded highlighting work...
|
||||||
|
loadLanguages(['markup', 'css', 'javascript'])
|
||||||
|
|
||||||
|
function wrap(code: string, lang: string): string {
|
||||||
|
if (lang === 'text') {
|
||||||
|
code = escapeHtml(code)
|
||||||
|
}
|
||||||
|
return `<pre v-pre><code>${code}</code></pre>`
|
||||||
|
}
|
||||||
|
|
||||||
|
export default (str: string, lang: string): string => {
|
||||||
|
if (!lang) {
|
||||||
|
return wrap(str, 'text')
|
||||||
|
}
|
||||||
|
lang = lang.toLowerCase()
|
||||||
|
const rawLang = lang
|
||||||
|
if (lang === 'vue' || lang === 'html') {
|
||||||
|
lang = 'markup'
|
||||||
|
}
|
||||||
|
if (lang === 'md') {
|
||||||
|
lang = 'markdown'
|
||||||
|
}
|
||||||
|
if (lang === 'ts') {
|
||||||
|
lang = 'typescript'
|
||||||
|
}
|
||||||
|
if (lang === 'py') {
|
||||||
|
lang = 'python'
|
||||||
|
}
|
||||||
|
if (!prism.languages[lang]) {
|
||||||
|
try {
|
||||||
|
loadLanguages([lang])
|
||||||
|
} catch (e) {
|
||||||
|
console.warn(lang, e)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (prism.languages[lang]) {
|
||||||
|
const code = prism.highlight(str, prism.languages[lang], lang)
|
||||||
|
return wrap(code, rawLang)
|
||||||
|
}
|
||||||
|
return wrap(str, 'text')
|
||||||
|
}
|
11
docs/src/plugin/pre-wrapper.ts
Normal file
11
docs/src/plugin/pre-wrapper.ts
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
import MarkdownIt from 'markdown-it'
|
||||||
|
|
||||||
|
export default (md: MarkdownIt): void => {
|
||||||
|
const fence = md.renderer.rules.fence!
|
||||||
|
md.renderer.rules.fence = (...args) => {
|
||||||
|
const [tokens, idx] = args
|
||||||
|
const token = tokens[idx]
|
||||||
|
const rawCode = fence(...args)
|
||||||
|
return `<div class="language-${token.info.trim()}">${rawCode}</div>`
|
||||||
|
}
|
||||||
|
}
|
49
docs/src/plugin/snippet.ts
Normal file
49
docs/src/plugin/snippet.ts
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
// copy from [vitepress](https://github.com/vuejs/vitepress)
|
||||||
|
import fs from 'fs'
|
||||||
|
import MarkdownIt from 'markdown-it'
|
||||||
|
import { RuleBlock } from 'markdown-it/lib/parser_block'
|
||||||
|
|
||||||
|
export default (md: MarkdownIt): void => {
|
||||||
|
const parser: RuleBlock = (state, startLine, endLine, silent) => {
|
||||||
|
const CH = '<'.charCodeAt(0)
|
||||||
|
const pos = state.bMarks[startLine] + state.tShift[startLine]
|
||||||
|
const max = state.eMarks[startLine]
|
||||||
|
|
||||||
|
// if it's indented more than 3 spaces, it should be a code block
|
||||||
|
if (state.sCount[startLine] - state.blkIndent >= 4) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
for (let i = 0; i < 3; ++i) {
|
||||||
|
const ch = state.src.charCodeAt(pos + i)
|
||||||
|
if (ch !== CH || pos + i >= max) return false
|
||||||
|
}
|
||||||
|
|
||||||
|
if (silent) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
const start = pos + 3
|
||||||
|
const end = state.skipSpacesBack(max, pos)
|
||||||
|
const rawPath = state.src
|
||||||
|
.slice(start, end)
|
||||||
|
.trim()
|
||||||
|
.replace(/^@/, process.cwd())
|
||||||
|
const content = fs.existsSync(rawPath)
|
||||||
|
? fs.readFileSync(rawPath).toString()
|
||||||
|
: 'Not found: ' + rawPath
|
||||||
|
const meta = rawPath.replace(rawPath, '')
|
||||||
|
|
||||||
|
state.line = startLine + 1
|
||||||
|
|
||||||
|
const token = state.push('fence', 'code', 0)
|
||||||
|
token.info = rawPath.split('.').pop() + meta
|
||||||
|
token.content = content
|
||||||
|
token.markup = '```'
|
||||||
|
token.map = [startLine, startLine + 1]
|
||||||
|
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
md.block.ruler.before('fence', 'snippet', parser)
|
||||||
|
}
|
20
docs/src/router/index.ts
Normal file
20
docs/src/router/index.ts
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
import {
|
||||||
|
createMemoryHistory,
|
||||||
|
createRouter as _createRouter,
|
||||||
|
createWebHistory,
|
||||||
|
Router,
|
||||||
|
} from 'vue-router'
|
||||||
|
import zhCN from './zh-CN'
|
||||||
|
import type { IRouteRecordRaw } from '/@src/index'
|
||||||
|
|
||||||
|
const routes: IRouteRecordRaw[] = [...zhCN]
|
||||||
|
|
||||||
|
export function createRouter(): Router {
|
||||||
|
const baseUrl = import.meta.env.BASE_URL
|
||||||
|
return _createRouter({
|
||||||
|
history: import.meta.env.SSR
|
||||||
|
? createMemoryHistory(baseUrl)
|
||||||
|
: createWebHistory(baseUrl),
|
||||||
|
routes: routes
|
||||||
|
})
|
||||||
|
}
|
32
docs/src/router/zh-CN.ts
Normal file
32
docs/src/router/zh-CN.ts
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
import BaseLayout from '../layouts/Layout.vue'
|
||||||
|
|
||||||
|
const zhCN = [
|
||||||
|
{
|
||||||
|
path: '/',
|
||||||
|
redirect: '/zh-CN/guide/',
|
||||||
|
component: BaseLayout,
|
||||||
|
meta: { title: '指南', icon: 'el-icon-position' },
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
path: '/zh-CN/guide/',
|
||||||
|
component: () => import('../../docs/zh-CN/guide/home.md'),
|
||||||
|
meta: { title: '介绍' },
|
||||||
|
}
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: '/zh-CN/components/',
|
||||||
|
redirect: '/zh-CN/components/button',
|
||||||
|
component: BaseLayout,
|
||||||
|
meta: { title: '组件', icon: 'el-icon-copy-document' },
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
path: '/zh-CN/components/button',
|
||||||
|
component: () => import('../../docs/zh-CN/components/button.md'),
|
||||||
|
meta: { title: '按钮' },
|
||||||
|
}
|
||||||
|
],
|
||||||
|
},
|
||||||
|
]
|
||||||
|
|
||||||
|
export default zhCN
|
214
docs/src/styles/code.css
Normal file
214
docs/src/styles/code.css
Normal file
@ -0,0 +1,214 @@
|
|||||||
|
/* copy from [vitepress](https://github.com/vuejs/vitepress) */
|
||||||
|
code {
|
||||||
|
margin: 0;
|
||||||
|
border-radius: 3px;
|
||||||
|
padding: 0.25rem 0.5rem;
|
||||||
|
font-family: var(--code-font-family);
|
||||||
|
font-size: 0.85em;
|
||||||
|
color: var(--c-text-light);
|
||||||
|
background-color: var(--code-inline-bg-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
code .token.deleted {
|
||||||
|
color: #ec5975;
|
||||||
|
}
|
||||||
|
|
||||||
|
code .token.inserted {
|
||||||
|
color: var(--c-brand);
|
||||||
|
}
|
||||||
|
|
||||||
|
div[class*='language-'] {
|
||||||
|
position: relative;
|
||||||
|
margin: 1rem -1.5rem;
|
||||||
|
background-color: #fafafa;
|
||||||
|
overflow-x: auto;
|
||||||
|
border: 1px solid #eaeefb;
|
||||||
|
}
|
||||||
|
|
||||||
|
li > div[class*='language-'] {
|
||||||
|
border-radius: 6px 0 0 6px;
|
||||||
|
margin: 1rem -1.5rem 1rem -1.25rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (min-width: 420px) {
|
||||||
|
div[class*='language-'] {
|
||||||
|
margin: 1rem 0;
|
||||||
|
border-radius: 6px;
|
||||||
|
}
|
||||||
|
|
||||||
|
li > div[class*='language-'] {
|
||||||
|
margin: 1rem 0 1rem 0rem;
|
||||||
|
border-radius: 6px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[class*='language-'] pre,
|
||||||
|
[class*='language-'] code {
|
||||||
|
text-align: left;
|
||||||
|
white-space: pre;
|
||||||
|
word-spacing: normal;
|
||||||
|
word-break: normal;
|
||||||
|
word-wrap: normal;
|
||||||
|
-moz-tab-size: 4;
|
||||||
|
-o-tab-size: 4;
|
||||||
|
tab-size: 4;
|
||||||
|
-webkit-hyphens: none;
|
||||||
|
-moz-hyphens: none;
|
||||||
|
-ms-hyphens: none;
|
||||||
|
hyphens: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
[class*='language-'] pre {
|
||||||
|
position: relative;
|
||||||
|
z-index: 1;
|
||||||
|
margin: 0;
|
||||||
|
padding: 1.25rem 1.5rem;
|
||||||
|
background: transparent;
|
||||||
|
overflow-x: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
[class*='language-'] pre p {
|
||||||
|
margin: auto !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
[class*='language-'] code {
|
||||||
|
padding: 0;
|
||||||
|
line-height: var(--code-line-height);
|
||||||
|
font-size: var(--code-font-size);
|
||||||
|
color: #000;
|
||||||
|
background-color: #fafafa;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Line highlighting */
|
||||||
|
|
||||||
|
.highlight-lines {
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
bottom: 0;
|
||||||
|
left: 0;
|
||||||
|
padding: 1.25rem 0;
|
||||||
|
width: 100%;
|
||||||
|
line-height: var(--code-line-height);
|
||||||
|
font-family: var(--code-font-family);
|
||||||
|
font-size: var(--code-font-size);
|
||||||
|
user-select: none;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.highlight-lines .highlighted {
|
||||||
|
background-color: rgba(0, 0, 0, 0.66);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Line numbers mode */
|
||||||
|
|
||||||
|
div[class*='language-'].line-numbers-mode {
|
||||||
|
padding-left: 3.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.line-numbers-wrapper {
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
bottom: 0;
|
||||||
|
left: 0;
|
||||||
|
z-index: 3;
|
||||||
|
border-right: 1px solid rgba(0, 0, 0, 0.5);
|
||||||
|
padding: 1.25rem 0;
|
||||||
|
width: 3.5rem;
|
||||||
|
text-align: center;
|
||||||
|
line-height: var(--code-line-height);
|
||||||
|
font-family: var(--code-font-family);
|
||||||
|
font-size: var(--code-font-size);
|
||||||
|
color: #888;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Language marker */
|
||||||
|
|
||||||
|
[class*='language-']:before {
|
||||||
|
position: absolute;
|
||||||
|
top: 0.6em;
|
||||||
|
right: 1em;
|
||||||
|
z-index: 2;
|
||||||
|
font-size: 0.8rem;
|
||||||
|
color: #888;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* prism.js tomorrow night eighties for JavaScript, CoffeeScript, CSS and HTML.
|
||||||
|
* Based on https://github.com/chriskempson/tomorrow-theme
|
||||||
|
*
|
||||||
|
* @author Rose Pritchard
|
||||||
|
*/
|
||||||
|
.token.comment,
|
||||||
|
.token.block-comment,
|
||||||
|
.token.prolog,
|
||||||
|
.token.doctype,
|
||||||
|
.token.cdata {
|
||||||
|
color: #999;
|
||||||
|
}
|
||||||
|
|
||||||
|
.token.punctuation {
|
||||||
|
color: #ccc;
|
||||||
|
}
|
||||||
|
|
||||||
|
.token.tag,
|
||||||
|
.token.attr-name,
|
||||||
|
.token.namespace,
|
||||||
|
.token.deleted {
|
||||||
|
color: #e2777a;
|
||||||
|
}
|
||||||
|
|
||||||
|
.token.function-name {
|
||||||
|
color: #6196cc;
|
||||||
|
}
|
||||||
|
|
||||||
|
.token.boolean,
|
||||||
|
.token.number,
|
||||||
|
.token.function {
|
||||||
|
color: #f08d49;
|
||||||
|
}
|
||||||
|
|
||||||
|
.token.property,
|
||||||
|
.token.class-name,
|
||||||
|
.token.constant,
|
||||||
|
.token.symbol {
|
||||||
|
color: #f8c555;
|
||||||
|
}
|
||||||
|
|
||||||
|
.token.selector,
|
||||||
|
.token.important,
|
||||||
|
.token.atrule,
|
||||||
|
.token.keyword,
|
||||||
|
.token.builtin {
|
||||||
|
color: #cc99cd;
|
||||||
|
}
|
||||||
|
|
||||||
|
.token.string,
|
||||||
|
.token.char,
|
||||||
|
.token.attr-value,
|
||||||
|
.token.regex,
|
||||||
|
.token.variable {
|
||||||
|
color: #7ec699;
|
||||||
|
}
|
||||||
|
|
||||||
|
.token.operator,
|
||||||
|
.token.entity,
|
||||||
|
.token.url {
|
||||||
|
color: #67cdcc;
|
||||||
|
}
|
||||||
|
|
||||||
|
.token.important,
|
||||||
|
.token.bold {
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
.token.italic {
|
||||||
|
font-style: italic;
|
||||||
|
}
|
||||||
|
|
||||||
|
.token.entity {
|
||||||
|
cursor: help;
|
||||||
|
}
|
||||||
|
|
||||||
|
.token.inserted {
|
||||||
|
color: green;
|
||||||
|
}
|
71
docs/src/styles/custom-blocks.css
Normal file
71
docs/src/styles/custom-blocks.css
Normal file
@ -0,0 +1,71 @@
|
|||||||
|
.custom-block.tip,
|
||||||
|
.custom-block.warning,
|
||||||
|
.custom-block.danger {
|
||||||
|
margin: 1rem 0;
|
||||||
|
border-left: 0.3rem solid;
|
||||||
|
padding: 0.1rem 1.5rem;
|
||||||
|
overflow-x: auto;
|
||||||
|
border-radius: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.custom-block.tip {
|
||||||
|
background-color: #f3f5f7;
|
||||||
|
border-color: #409eff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.custom-block.warning {
|
||||||
|
border-color: #e7c000;
|
||||||
|
color: #6b5900;
|
||||||
|
background-color: rgba(255, 229, 100, 0.3);
|
||||||
|
}
|
||||||
|
|
||||||
|
.custom-block.warning .custom-block-title {
|
||||||
|
color: #b29400;
|
||||||
|
}
|
||||||
|
|
||||||
|
.custom-block.warning a {
|
||||||
|
color: var(--c-text);
|
||||||
|
}
|
||||||
|
|
||||||
|
.custom-block.danger {
|
||||||
|
border-color: #c00;
|
||||||
|
color: #4d0000;
|
||||||
|
background-color: #ffe6e6;
|
||||||
|
}
|
||||||
|
|
||||||
|
.custom-block.danger .custom-block-title {
|
||||||
|
color: #900;
|
||||||
|
}
|
||||||
|
|
||||||
|
.custom-block.danger a {
|
||||||
|
color: var(--c-text);
|
||||||
|
}
|
||||||
|
|
||||||
|
.custom-block.details {
|
||||||
|
position: relative;
|
||||||
|
display: block;
|
||||||
|
border-radius: 2px;
|
||||||
|
margin: 1.6em 0;
|
||||||
|
padding: 1.6em;
|
||||||
|
background-color: #eee;
|
||||||
|
}
|
||||||
|
|
||||||
|
.custom-block.details h4 {
|
||||||
|
margin-top: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.custom-block.details figure:last-child,
|
||||||
|
.custom-block.details p:last-child {
|
||||||
|
margin-bottom: 0;
|
||||||
|
padding-bottom: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.custom-block.details summary {
|
||||||
|
outline: none;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.custom-block-title {
|
||||||
|
margin-bottom: -0.4rem;
|
||||||
|
font-weight: 600;
|
||||||
|
}
|
4
docs/src/styles/index.css
Normal file
4
docs/src/styles/index.css
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
@import './code.css';
|
||||||
|
@import './custom-blocks.css';
|
||||||
|
@import './markdown.css';
|
||||||
|
@import './vars.css';
|
220
docs/src/styles/markdown.css
Normal file
220
docs/src/styles/markdown.css
Normal file
@ -0,0 +1,220 @@
|
|||||||
|
html {
|
||||||
|
line-height: 1.4;
|
||||||
|
font-size: 16px;
|
||||||
|
-webkit-text-size-adjust: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
h4 {
|
||||||
|
font-weight: 700 !important;
|
||||||
|
font-size: 16.8px !important;
|
||||||
|
margin-top: 20px !important;
|
||||||
|
margin-bottom: 20px !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
h5 {
|
||||||
|
font-weight: 700;
|
||||||
|
font-size: 16.8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
h1,
|
||||||
|
h2,
|
||||||
|
h3,
|
||||||
|
h4,
|
||||||
|
h5,
|
||||||
|
h6 {
|
||||||
|
margin: 0;
|
||||||
|
color: #303133;
|
||||||
|
line-height: 1.25;
|
||||||
|
}
|
||||||
|
|
||||||
|
h1,
|
||||||
|
h2,
|
||||||
|
h3,
|
||||||
|
h4,
|
||||||
|
h5,
|
||||||
|
h6,
|
||||||
|
strong,
|
||||||
|
b {
|
||||||
|
font-weight: 600;
|
||||||
|
}
|
||||||
|
|
||||||
|
h1:hover .header-anchor,
|
||||||
|
h1:focus .header-anchor,
|
||||||
|
h2:hover .header-anchor,
|
||||||
|
h2:focus .header-anchor,
|
||||||
|
h3:hover .header-anchor,
|
||||||
|
h3:focus .header-anchor,
|
||||||
|
h4:hover .header-anchor,
|
||||||
|
h4:focus .header-anchor,
|
||||||
|
h5:hover .header-anchor,
|
||||||
|
h5:focus .header-anchor,
|
||||||
|
h6:hover .header-anchor,
|
||||||
|
h6:focus .header-anchor {
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
h1 {
|
||||||
|
margin-top: 1.5rem;
|
||||||
|
font-size: 1.9rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media screen and (min-width: 420px) {
|
||||||
|
h1 {
|
||||||
|
font-size: 2.2rem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
h2 {
|
||||||
|
margin-top: 2.25rem;
|
||||||
|
margin-bottom: 1.25rem;
|
||||||
|
border-bottom: 1px solid var(--c-divider);
|
||||||
|
padding-bottom: 0.3rem;
|
||||||
|
line-height: 1.25;
|
||||||
|
font-size: 1.65rem;
|
||||||
|
/* overflow-x: auto; */
|
||||||
|
}
|
||||||
|
|
||||||
|
h2 + h3 {
|
||||||
|
margin-top: 1.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
h3 {
|
||||||
|
margin-top: 2rem;
|
||||||
|
font-size: 1.35rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
h4 {
|
||||||
|
font-size: 1.15rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
h1 {
|
||||||
|
margin-top: 4px !important;
|
||||||
|
margin-bottom: 22px !important;
|
||||||
|
color: #000000d9 !important;
|
||||||
|
font-weight: 500 !important;
|
||||||
|
font-size: 20px !important;
|
||||||
|
font-family: Avenir, -apple-system, BlinkMacSystemFont, segoe ui, Roboto,
|
||||||
|
helvetica neue, Arial, noto sans, sans-serif, apple color emoji,
|
||||||
|
segoe ui emoji, segoe ui symbol, noto color emoji, sans-serif;
|
||||||
|
line-height: 38px;
|
||||||
|
}
|
||||||
|
|
||||||
|
h2 {
|
||||||
|
margin-top: 4px !important;
|
||||||
|
margin-bottom: 16px !important;
|
||||||
|
color: #000000d9 !important;
|
||||||
|
font-weight: 500 !important;
|
||||||
|
font-size: 16px !important;
|
||||||
|
border-bottom: 0px;
|
||||||
|
font-family: Avenir, -apple-system, BlinkMacSystemFont, segoe ui, Roboto,
|
||||||
|
helvetica neue, Arial, noto sans, sans-serif, apple color emoji,
|
||||||
|
segoe ui emoji, segoe ui symbol, noto color emoji, sans-serif;
|
||||||
|
line-height: 38px;
|
||||||
|
}
|
||||||
|
|
||||||
|
p,
|
||||||
|
ol,
|
||||||
|
ul {
|
||||||
|
margin: 1rem 0;
|
||||||
|
line-height: 1.7;
|
||||||
|
}
|
||||||
|
|
||||||
|
p {
|
||||||
|
color: #454d64 !important;
|
||||||
|
margin-top: 20px !important;
|
||||||
|
font-size: 14px !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
a,
|
||||||
|
area,
|
||||||
|
button,
|
||||||
|
[role='button'],
|
||||||
|
input,
|
||||||
|
label,
|
||||||
|
select,
|
||||||
|
summary,
|
||||||
|
textarea {
|
||||||
|
touch-action: manipulation;
|
||||||
|
}
|
||||||
|
|
||||||
|
a {
|
||||||
|
text-decoration: none;
|
||||||
|
color: var(--c-brand);
|
||||||
|
}
|
||||||
|
|
||||||
|
a:hover {
|
||||||
|
text-decoration: underline;
|
||||||
|
}
|
||||||
|
|
||||||
|
a.header-anchor {
|
||||||
|
float: left;
|
||||||
|
margin-top: 0.125em;
|
||||||
|
margin-left: -0.87em;
|
||||||
|
padding-right: 0.23em;
|
||||||
|
font-size: 0.85em;
|
||||||
|
opacity: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
a.header-anchor:hover,
|
||||||
|
a.header-anchor:focus {
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
figure {
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
img {
|
||||||
|
max-width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
ul,
|
||||||
|
ol {
|
||||||
|
padding-left: 1.25em;
|
||||||
|
}
|
||||||
|
|
||||||
|
li > ul,
|
||||||
|
li > ol {
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
blockquote {
|
||||||
|
margin: 1rem 0;
|
||||||
|
border-left: 0.2rem solid #dfe2e5;
|
||||||
|
padding: 0.25rem 0 0.25rem 1rem;
|
||||||
|
font-size: 1rem;
|
||||||
|
color: #999;
|
||||||
|
}
|
||||||
|
|
||||||
|
blockquote > p {
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
form {
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
table {
|
||||||
|
width: 100%; /*表格宽度*/
|
||||||
|
border-collapse: collapse; /*使用单一线条的边框*/
|
||||||
|
empty-cells: show; /*单元格无内容依旧绘制边框*/
|
||||||
|
}
|
||||||
|
|
||||||
|
table th,
|
||||||
|
table td {
|
||||||
|
font-size: 14px;
|
||||||
|
color: #606266;
|
||||||
|
height: 50px; /*统一每一行的默认高度*/
|
||||||
|
border-top: 1px solid whitesmoke; /*内部边框样式*/
|
||||||
|
padding: 0 10px; /*内边距*/
|
||||||
|
}
|
||||||
|
|
||||||
|
table tr:hover {
|
||||||
|
background: #efefef;
|
||||||
|
}
|
||||||
|
table th {
|
||||||
|
white-space: nowrap; /*表头内容强制在一行显示*/
|
||||||
|
}
|
||||||
|
table td {
|
||||||
|
white-space: nowrap;
|
||||||
|
}
|
52
docs/src/styles/vars.css
Normal file
52
docs/src/styles/vars.css
Normal file
@ -0,0 +1,52 @@
|
|||||||
|
/* TODO: rebuild... copy from [vitepress](https://github.com/vuejs/vitepress) */
|
||||||
|
:root {
|
||||||
|
--c-white: #ffffff;
|
||||||
|
--c-black: #000000;
|
||||||
|
|
||||||
|
--c-divider-light: rgba(60, 60, 67, 0.12);
|
||||||
|
--c-divider-dark: rgba(84, 84, 88, 0.48);
|
||||||
|
|
||||||
|
--c-text-light-1: #2c3e50;
|
||||||
|
--c-text-light-2: #476582;
|
||||||
|
--c-text-light-3: #90a4b7;
|
||||||
|
|
||||||
|
--c-brand: #409eff;
|
||||||
|
--c-brand-light: #4abf8a;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Typography
|
||||||
|
* --------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
--font-family-base: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto,
|
||||||
|
Oxygen, Ubuntu, Cantarell, 'Fira Sans', 'Droid Sans', 'Helvetica Neue',
|
||||||
|
sans-serif;
|
||||||
|
--font-family-mono: source-code-pro, Menlo, Monaco, Consolas, 'Courier New',
|
||||||
|
monospace;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Shadows
|
||||||
|
* --------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
--shadow-1: 0 1px 2px rgba(0, 0, 0, 0.04), 0 1px 2px rgba(0, 0, 0, 0.06);
|
||||||
|
--shadow-2: 0 3px 12px rgba(0, 0, 0, 0.07), 0 1px 4px rgba(0, 0, 0, 0.07);
|
||||||
|
--shadow-3: 0 12px 32px rgba(0, 0, 0, 0.1), 0 2px 6px rgba(0, 0, 0, 0.08);
|
||||||
|
--shadow-4: 0 14px 44px rgba(0, 0, 0, 0.12), 0 3px 9px rgba(0, 0, 0, 0.12);
|
||||||
|
--shadow-5: 0 18px 56px rgba(0, 0, 0, 0.16), 0 4px 12px rgba(0, 0, 0, 0.16);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Fallback Styles */
|
||||||
|
:root {
|
||||||
|
--c-divider: var(--c-divider-light);
|
||||||
|
|
||||||
|
--c-text: var(--c-text-light-1);
|
||||||
|
--c-text-light: var(--c-text-light-2);
|
||||||
|
--c-text-lighter: var(--c-text-light-3);
|
||||||
|
|
||||||
|
--c-bg: var(--c-white);
|
||||||
|
|
||||||
|
--code-line-height: 24px;
|
||||||
|
--code-font-family: var(--font-family-mono);
|
||||||
|
--code-font-size: 14px;
|
||||||
|
--code-inline-bg-color: rgba(27, 31, 35, 0.05);
|
||||||
|
--code-bg-color: #282c34;
|
||||||
|
}
|
4
docs/src/tsconfig.json
Normal file
4
docs/src/tsconfig.json
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
{
|
||||||
|
"extends": "../../tsconfig.json",
|
||||||
|
"include": [".", "../../shims-vue.d.ts"]
|
||||||
|
}
|
13
docs/vite.config.ts
Normal file
13
docs/vite.config.ts
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
import path from 'path'
|
||||||
|
import { defineConfig } from 'vite'
|
||||||
|
import plugins from './src/plugin/common-plugins'
|
||||||
|
|
||||||
|
export default defineConfig({
|
||||||
|
base: '/layui-vue/',
|
||||||
|
resolve: {
|
||||||
|
alias: {
|
||||||
|
'/@src': path.resolve(__dirname, '../src'),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
plugins,
|
||||||
|
})
|
27
jest.config.js
Normal file
27
jest.config.js
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
module.exports = {
|
||||||
|
roots: ['<rootDir>/test'],
|
||||||
|
preset: 'ts-jest',
|
||||||
|
testEnvironment: 'jsdom',
|
||||||
|
moduleFileExtensions: ['ts', 'vue', 'js', 'jsx', 'tsx', 'json', 'node'],
|
||||||
|
transformIgnorePatterns: ['node_modules/(?!(@vue/shared|element-plus)/)'],
|
||||||
|
moduleNameMapper: { '\\.css$': '<rootDir>/test/__mocks__/css.ts' },
|
||||||
|
transform: {
|
||||||
|
'^.+\\.vue$': 'vue-jest',
|
||||||
|
'^.+\\.(t|j)sx?$': [
|
||||||
|
'babel-jest',
|
||||||
|
{
|
||||||
|
presets: [
|
||||||
|
[
|
||||||
|
'@babel/preset-env',
|
||||||
|
{
|
||||||
|
targets: {
|
||||||
|
node: 'current',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
'@babel/preset-typescript',
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
}
|
98
package.json
Normal file
98
package.json
Normal file
@ -0,0 +1,98 @@
|
|||||||
|
{
|
||||||
|
"name": "layui-vue",
|
||||||
|
"version": "0.3.7",
|
||||||
|
"description": "a component library for Vue 3 base on layui-vue",
|
||||||
|
"main": "lib/layui-vue.umd.js",
|
||||||
|
"module": "lib/layui-vue.es.js",
|
||||||
|
"exports": {
|
||||||
|
".": {
|
||||||
|
"import": "./lib/layui-vue.es.js",
|
||||||
|
"require": "./lib/layui-vue.umd.js"
|
||||||
|
},
|
||||||
|
"./lib/": "./lib/"
|
||||||
|
},
|
||||||
|
"types": "types/index.d.ts",
|
||||||
|
"style": "lib/style.css",
|
||||||
|
"scripts": {
|
||||||
|
"dev": "vite",
|
||||||
|
"build": "vite build --emptyOutDir && npm run build:helper && npm run build:types",
|
||||||
|
"build:types": "rimraf types && tsc -d",
|
||||||
|
"build:helper": "node .helperrc.js",
|
||||||
|
"build:docs": "vite build docs",
|
||||||
|
"test": "jest",
|
||||||
|
"lint": "eslint . --fix --ext .ts,.vue,.js --ignore-pattern \"/lib/\" --ignore-pattern \"/types/\"",
|
||||||
|
"prettier": "prettier --check --write --ignore-unknown \"{example,src,docs,test}/**\""
|
||||||
|
},
|
||||||
|
"repository": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://gitee.com/Jmysy/layui-vue"
|
||||||
|
},
|
||||||
|
"keywords": [
|
||||||
|
"layui-vue",
|
||||||
|
"layui",
|
||||||
|
"vue"
|
||||||
|
],
|
||||||
|
"author": "<就眠仪式 jmys1992@gmail.com>",
|
||||||
|
"license": "MIT",
|
||||||
|
"bugs": {
|
||||||
|
"url": "https://gitee.com/Jmysy/layui-vue/issues"
|
||||||
|
},
|
||||||
|
"homepage": "https://gitee.com/Jmysy/layui-vue/blob/master/README.md",
|
||||||
|
"peerDependencies": {
|
||||||
|
"vue": "^3.1.2",
|
||||||
|
"vue-router": "^4.0.10"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"vue": "^3.1.2",
|
||||||
|
"vue-router": "^4.0.10"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"@babel/core": "^7.14.0",
|
||||||
|
"@babel/preset-env": "^7.14.0",
|
||||||
|
"@babel/preset-typescript": "^7.13.0",
|
||||||
|
"@types/jest": "^26.0.23",
|
||||||
|
"@types/markdown-it": "^12.0.1",
|
||||||
|
"@types/markdown-it-container": "^2.0.3",
|
||||||
|
"@typescript-eslint/eslint-plugin": "^4.22.0",
|
||||||
|
"@typescript-eslint/parser": "^4.22.0",
|
||||||
|
"@vitejs/plugin-vue": "^1.2.2",
|
||||||
|
"@vue/compiler-sfc": "^3.1.2",
|
||||||
|
"@vue/server-renderer": "^3.1.1",
|
||||||
|
"@vue/test-utils": "^2.0.0-rc.6",
|
||||||
|
"babel-jest": "^26.6.3",
|
||||||
|
"components-helper": "^1.0.3",
|
||||||
|
"escape-html": "^1.0.3",
|
||||||
|
"eslint": "^7.25.0",
|
||||||
|
"eslint-plugin-prettier": "^3.4.0",
|
||||||
|
"eslint-plugin-vue": "^7.9.0",
|
||||||
|
"husky": "^4.3.6",
|
||||||
|
"jest": "^26.6.3",
|
||||||
|
"lint-staged": "^10.5.4",
|
||||||
|
"markdown-it-container": "^3.0.0",
|
||||||
|
"postcss": "^8.2.13",
|
||||||
|
"postcss-preset-env": "^6.7.0",
|
||||||
|
"prettier": "2.2.1",
|
||||||
|
"prismjs": "^1.23.0",
|
||||||
|
"rimraf": "^3.0.2",
|
||||||
|
"rollup-plugin-babel": "^4.4.0",
|
||||||
|
"ts-jest": "^26.5.5",
|
||||||
|
"typescript": "^4.2.4",
|
||||||
|
"vite": "2.3.7",
|
||||||
|
"vite-plugin-md": "^0.6.3",
|
||||||
|
"vue-jest": "^5.0.0-alpha.8"
|
||||||
|
},
|
||||||
|
"vetur": {
|
||||||
|
"tags": "lib/tags.json",
|
||||||
|
"attributes": "lib/attributes.json"
|
||||||
|
},
|
||||||
|
"web-types": "lib/web-types.json",
|
||||||
|
"files": [
|
||||||
|
"lib",
|
||||||
|
"types"
|
||||||
|
],
|
||||||
|
"husky": {
|
||||||
|
"hooks": {
|
||||||
|
"pre-commit": "lint-staged"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
25
shims-vue.d.ts
vendored
Normal file
25
shims-vue.d.ts
vendored
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
declare module '*.vue' {
|
||||||
|
import { DefineComponent } from 'vue'
|
||||||
|
const comp: DefineComponent
|
||||||
|
export default comp
|
||||||
|
}
|
||||||
|
|
||||||
|
declare module '*.md' {
|
||||||
|
import { DefineComponent } from 'vue'
|
||||||
|
const comp: DefineComponent
|
||||||
|
export default comp
|
||||||
|
}
|
||||||
|
|
||||||
|
declare module 'prismjs'
|
||||||
|
declare module 'prismjs/components/index'
|
||||||
|
declare module 'escape-html'
|
||||||
|
|
||||||
|
interface ImportMeta {
|
||||||
|
env: {
|
||||||
|
MODE: string
|
||||||
|
BASE_URL: string
|
||||||
|
PROD: boolean
|
||||||
|
DEV: boolean
|
||||||
|
SSR: boolean
|
||||||
|
}
|
||||||
|
}
|
6593
src/css/layui.css
Normal file
6593
src/css/layui.css
Normal file
File diff suppressed because it is too large
Load Diff
BIN
src/font/iconfont.eot
Normal file
BIN
src/font/iconfont.eot
Normal file
Binary file not shown.
387
src/font/iconfont.svg
Normal file
387
src/font/iconfont.svg
Normal file
File diff suppressed because one or more lines are too long
After Width: | Height: | Size: 309 KiB |
BIN
src/font/iconfont.ttf
Normal file
BIN
src/font/iconfont.ttf
Normal file
Binary file not shown.
BIN
src/font/iconfont.woff
Normal file
BIN
src/font/iconfont.woff
Normal file
Binary file not shown.
BIN
src/font/iconfont.woff2
Normal file
BIN
src/font/iconfont.woff2
Normal file
Binary file not shown.
50
src/index.ts
Normal file
50
src/index.ts
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
import type { App } from 'vue'
|
||||||
|
import type { IDefineComponent, InstallOptions } from './module/type/index'
|
||||||
|
|
||||||
|
import "./css/layui.css";
|
||||||
|
import LayRadio from './module/radio/index'
|
||||||
|
import LayButton from './module/button/index'
|
||||||
|
import LayIcon from './module/icon/index'
|
||||||
|
import LayLayout from "./module/layout/index"
|
||||||
|
import LaySide from "./module/side/index"
|
||||||
|
import LayBody from "./module/body/index"
|
||||||
|
import LayHeader from "./module/header/index"
|
||||||
|
import LayFooter from "./module/footer/index"
|
||||||
|
import LayLogo from "./module/logo/index"
|
||||||
|
|
||||||
|
const components: Record<string, IDefineComponent> = {
|
||||||
|
LayRadio,
|
||||||
|
LayButton,
|
||||||
|
LayIcon,
|
||||||
|
LayLayout,
|
||||||
|
LaySide,
|
||||||
|
LayHeader,
|
||||||
|
LayBody,
|
||||||
|
LayFooter,
|
||||||
|
LayLogo
|
||||||
|
}
|
||||||
|
|
||||||
|
const install = (app: App, options?: InstallOptions): void => {
|
||||||
|
const _options = options;
|
||||||
|
app.config.globalProperties.$PROOPTIONS = _options
|
||||||
|
|
||||||
|
for (const key in components) {
|
||||||
|
const item = components[key]
|
||||||
|
app.component(item.name || key, item)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export {
|
||||||
|
LayRadio,
|
||||||
|
LayIcon,
|
||||||
|
LayButton,
|
||||||
|
LayLayout,
|
||||||
|
LaySide,
|
||||||
|
LayHeader,
|
||||||
|
LayBody,
|
||||||
|
LayFooter,
|
||||||
|
LayLogo,
|
||||||
|
install,
|
||||||
|
}
|
||||||
|
|
||||||
|
export default { install }
|
9
src/module/body/index.ts
Normal file
9
src/module/body/index.ts
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
import type { App } from 'vue'
|
||||||
|
import Component from './index.vue'
|
||||||
|
import type { IDefineComponent } from '../type/index'
|
||||||
|
|
||||||
|
Component.install = (app: App) => {
|
||||||
|
app.component(Component.name || 'LayBody', Component)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default Component as IDefineComponent
|
9
src/module/body/index.vue
Normal file
9
src/module/body/index.vue
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
<template>
|
||||||
|
<div class="layui-body">
|
||||||
|
<slot></slot>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup name="LayBody" lang="ts">
|
||||||
|
|
||||||
|
</script>
|
9
src/module/button/index.ts
Normal file
9
src/module/button/index.ts
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
import type { App } from 'vue'
|
||||||
|
import Component from './index.vue'
|
||||||
|
import type { IDefineComponent } from '../../type/index'
|
||||||
|
|
||||||
|
Component.install = (app: App) => {
|
||||||
|
app.component(Component.name || 'LayButton ', Component)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default Component as IDefineComponent
|
14
src/module/button/index.vue
Normal file
14
src/module/button/index.vue
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
<template>
|
||||||
|
<button class="layui-btn" :class="[type ? 'layui-btn-' + type : '']">
|
||||||
|
<slot></slot>
|
||||||
|
</button>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup name="LayButton" lang="ts">
|
||||||
|
import { defineProps } from "@vue/runtime-core";
|
||||||
|
|
||||||
|
const props = defineProps<{
|
||||||
|
type?: string
|
||||||
|
}>()
|
||||||
|
|
||||||
|
</script>
|
9
src/module/footer/index.ts
Normal file
9
src/module/footer/index.ts
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
import type { App } from 'vue'
|
||||||
|
import Component from './index.vue'
|
||||||
|
import type { IDefineComponent } from '../type/index'
|
||||||
|
|
||||||
|
Component.install = (app: App) => {
|
||||||
|
app.component(Component.name || 'LayFooter', Component)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default Component as IDefineComponent
|
9
src/module/footer/index.vue
Normal file
9
src/module/footer/index.vue
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
<template>
|
||||||
|
<div class="layui-footer">
|
||||||
|
<slot></slot>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup name="LayFooter" lang="ts">
|
||||||
|
|
||||||
|
</script>
|
9
src/module/header/index.ts
Normal file
9
src/module/header/index.ts
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
import type { App } from 'vue'
|
||||||
|
import Component from './index.vue'
|
||||||
|
import type { IDefineComponent } from '../type/index'
|
||||||
|
|
||||||
|
Component.install = (app: App) => {
|
||||||
|
app.component(Component.name || 'LayHeader', Component)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default Component as IDefineComponent
|
9
src/module/header/index.vue
Normal file
9
src/module/header/index.vue
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
<template>
|
||||||
|
<div class="layui-header">
|
||||||
|
<slot></slot>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup name="LayHeader" lang="ts">
|
||||||
|
|
||||||
|
</script>
|
9
src/module/icon/index.ts
Normal file
9
src/module/icon/index.ts
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
import type { App } from 'vue'
|
||||||
|
import Component from './index.vue'
|
||||||
|
import type { IDefineComponent } from '../../type/index'
|
||||||
|
|
||||||
|
Component.install = (app: App) => {
|
||||||
|
app.component(Component.name || 'LayIcon', Component)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default Component as IDefineComponent
|
7
src/module/icon/index.vue
Normal file
7
src/module/icon/index.vue
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
<template>
|
||||||
|
<button class="layui-btn">按钮</button>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup name="LayButton" lang="ts">
|
||||||
|
|
||||||
|
</script>
|
9
src/module/layout/index.ts
Normal file
9
src/module/layout/index.ts
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
import type { App } from 'vue'
|
||||||
|
import Component from './index.vue'
|
||||||
|
import type { IDefineComponent } from '../type/index'
|
||||||
|
|
||||||
|
Component.install = (app: App) => {
|
||||||
|
app.component(Component.name || 'LayLayout', Component)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default Component as IDefineComponent
|
9
src/module/layout/index.vue
Normal file
9
src/module/layout/index.vue
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
<template>
|
||||||
|
<div class="layui-layout layui-layout-admin">
|
||||||
|
<slot></slot>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup name="LayLayout" lang="ts">
|
||||||
|
|
||||||
|
</script>
|
9
src/module/logo/index.ts
Normal file
9
src/module/logo/index.ts
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
import type { App } from 'vue'
|
||||||
|
import Component from './index.vue'
|
||||||
|
import type { IDefineComponent } from '../type/index'
|
||||||
|
|
||||||
|
Component.install = (app: App) => {
|
||||||
|
app.component(Component.name || 'LayLogo', Component)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default Component as IDefineComponent
|
9
src/module/logo/index.vue
Normal file
9
src/module/logo/index.vue
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
<template>
|
||||||
|
<div class="layui-logo">
|
||||||
|
<slot></slot>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup name="LayLogo" lang="ts">
|
||||||
|
|
||||||
|
</script>
|
9
src/module/radio/index.ts
Normal file
9
src/module/radio/index.ts
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
import type { App } from 'vue'
|
||||||
|
import Component from './index.vue'
|
||||||
|
import type { IDefineComponent } from '../../type/index'
|
||||||
|
|
||||||
|
Component.install = (app: App) => {
|
||||||
|
app.component(Component.name || 'LayRadio ', Component)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default Component as IDefineComponent
|
7
src/module/radio/index.vue
Normal file
7
src/module/radio/index.vue
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
<template>
|
||||||
|
<div></div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup name="LayRadio" lang="ts">
|
||||||
|
|
||||||
|
</script>
|
9
src/module/side/index.ts
Normal file
9
src/module/side/index.ts
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
import type { App } from 'vue'
|
||||||
|
import Component from './index.vue'
|
||||||
|
import type { IDefineComponent } from '../type/index'
|
||||||
|
|
||||||
|
Component.install = (app: App) => {
|
||||||
|
app.component(Component.name || 'LaySide', Component)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default Component as IDefineComponent
|
9
src/module/side/index.vue
Normal file
9
src/module/side/index.vue
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
<template>
|
||||||
|
<div class="layui-side">
|
||||||
|
<slot></slot>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup name="LaySide" lang="ts">
|
||||||
|
|
||||||
|
</script>
|
1
src/module/type/index.ts
Normal file
1
src/module/type/index.ts
Normal file
@ -0,0 +1 @@
|
|||||||
|
export * from './public'
|
17
src/module/type/public.ts
Normal file
17
src/module/type/public.ts
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
import type { App, DefineComponent } from 'vue'
|
||||||
|
export type StringObject = Record<string, unknown>
|
||||||
|
|
||||||
|
export type UnknownObject = Record<string | number, unknown>
|
||||||
|
|
||||||
|
export type UnknownFunction = (...arg: unknown[]) => unknown
|
||||||
|
|
||||||
|
export type IDefineComponent<Props = UnknownObject> = DefineComponent<Props> & {
|
||||||
|
install: (app: App, options?: InstallOptions) => void
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface InstallOptions extends StringObject {
|
||||||
|
/** Pagination Attributes */
|
||||||
|
pagination?: null
|
||||||
|
/** Menu Attributes */
|
||||||
|
menu?: null
|
||||||
|
}
|
20
tsconfig.json
Normal file
20
tsconfig.json
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
{
|
||||||
|
"compilerOptions": {
|
||||||
|
"baseUrl": ".",
|
||||||
|
"module": "esnext",
|
||||||
|
"target": "es2015",
|
||||||
|
"moduleResolution": "Node",
|
||||||
|
"strict": true,
|
||||||
|
"resolveJsonModule": true,
|
||||||
|
"declaration": true,
|
||||||
|
"emitDeclarationOnly": true,
|
||||||
|
"esModuleInterop": true,
|
||||||
|
"declarationDir": "types",
|
||||||
|
"lib": ["ESNext", "DOM"],
|
||||||
|
"paths": {
|
||||||
|
"/@src/*": ["./src/*"]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"include": ["src/**/*", "shims-vue.d.ts"],
|
||||||
|
"exclude": ["node_modules"]
|
||||||
|
}
|
44
vite.config.ts
Normal file
44
vite.config.ts
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
import path from 'path'
|
||||||
|
import { defineConfig } from 'vite'
|
||||||
|
import babel from 'rollup-plugin-babel'
|
||||||
|
import { name } from './package.json'
|
||||||
|
import plugins from './docs/src/plugin/common-plugins'
|
||||||
|
|
||||||
|
const camelize = (name: string) =>
|
||||||
|
name.replace(/(^|-)(\w)/g, (a, b, c) => c.toUpperCase())
|
||||||
|
|
||||||
|
export default defineConfig({
|
||||||
|
root: path.resolve(__dirname, 'docs'),
|
||||||
|
resolve: {
|
||||||
|
alias: {
|
||||||
|
'/@src': path.resolve(__dirname, 'src'),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
build: {
|
||||||
|
target: 'es2015',
|
||||||
|
outDir: path.resolve(__dirname, 'lib'),
|
||||||
|
lib: {
|
||||||
|
entry: path.resolve(__dirname, 'src/index.ts'),
|
||||||
|
name: camelize(name),
|
||||||
|
},
|
||||||
|
rollupOptions: {
|
||||||
|
output: {
|
||||||
|
exports: 'named',
|
||||||
|
globals: (id: string) => {
|
||||||
|
const name = id.replace(/^@/, '').split('/')[0]
|
||||||
|
return camelize(name)
|
||||||
|
},
|
||||||
|
},
|
||||||
|
external: (id: string) =>
|
||||||
|
/^(vue|@vue|element-plus|resize-observer-polyfill)/.test(id),
|
||||||
|
plugins: [
|
||||||
|
babel({
|
||||||
|
exclude: 'node_modules/**',
|
||||||
|
extensions: ['.js', '.jsx', '.ts', '.tsx', '.vue'],
|
||||||
|
presets: ['@babel/preset-env', '@babel/preset-typescript'],
|
||||||
|
}),
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
plugins,
|
||||||
|
})
|
Loading…
Reference in New Issue
Block a user