Compare commits
4 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
799c42d337 | ||
|
|
ef33295a54 | ||
|
|
c71ad7f471 | ||
|
|
8cf15eda72 |
12
.babelrc
@@ -15,18 +15,6 @@
|
||||
"plugins": ["transform-vue-jsx"],
|
||||
"env": {
|
||||
"utils": {
|
||||
"presets": [
|
||||
[
|
||||
"env",
|
||||
{
|
||||
"loose": true,
|
||||
"modules": "commonjs",
|
||||
"targets": {
|
||||
"browsers": ["> 1%", "last 2 versions", "not ie <= 8"]
|
||||
}
|
||||
}
|
||||
],
|
||||
],
|
||||
"plugins": [
|
||||
["module-resolver", {
|
||||
"root": ["element-ui"],
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
src/utils/popper.js
|
||||
src/utils/date.js
|
||||
src/utils/lodash.js
|
||||
examples/play
|
||||
*.sh
|
||||
node_modules
|
||||
|
||||
@@ -1,7 +1,10 @@
|
||||
{
|
||||
"env": {
|
||||
"mocha": true
|
||||
},
|
||||
"globals": {
|
||||
"ga": true,
|
||||
"chrome": true
|
||||
"expect": true,
|
||||
"sinon": true
|
||||
},
|
||||
"plugins": ["html", "json"],
|
||||
"extends": "elemefe",
|
||||
|
||||
2
.github/CONTRIBUTING.en-US.md
vendored
@@ -43,8 +43,6 @@ npm run dev
|
||||
# open http://localhost:8085
|
||||
```
|
||||
|
||||
> **Notice**: modify `examples/play/index.vue` file, use the component you contribute, then run `npm run dev:play`, go ahead [http://localhost:8085](http://localhost:8085), get result, more quickly and friendly.
|
||||
|
||||
To build:
|
||||
|
||||
```shell
|
||||
|
||||
4
.github/CONTRIBUTING.es.md
vendored
@@ -37,7 +37,7 @@ Estamos orgullosos de que usted esta interesado en contribuir al proyecto `Eleme
|
||||
- Fusión de un PR requiere dos mantenedores: el primero aprueba los cambios después de revisar, y entonces el segundo mantenedor revisa los cambios y hace la fusión.
|
||||
|
||||
|
||||
## Requerimientos Técnicos
|
||||
## Requerimientos Técnicos
|
||||
`Node.js 4+`, `yarn` y `npm 3+` son requisitos. Nota: Usamos yarn para bloquear versiones de dependencias, por lo que debería instalar dependencias usando `yarn` en lugar de `npm install`.
|
||||
.
|
||||
```shell
|
||||
@@ -47,8 +47,6 @@ npm run dev
|
||||
# abra http://localhost:8085
|
||||
```
|
||||
|
||||
> **Notice**: modify `examples/play/index.vue` file, use the component you contribute, then run `npm run dev:play`, go ahead [http://localhost:8085](http://localhost:8085), get result, more quickly and friendly.
|
||||
|
||||
Para armar:
|
||||
|
||||
```
|
||||
|
||||
60
.github/CONTRIBUTING.fr-FR.md
vendored
@@ -1,60 +0,0 @@
|
||||
# Guide à destination des contributeurs d'Element UI
|
||||
|
||||
Bonjour! Merci d'avoir choisi Element UI.
|
||||
|
||||
Element UI est une bibliothèque de composants basée sur Vue 2.0 pour les développeurs, les designers et les chefs de produits.
|
||||
|
||||
Nous sommes ravis que vous souhaitiez contribuer à Element. Avant de soumettre votre contribution, veuillez vous assurer de prendre un moment pour lire les indications suivantes.
|
||||
|
||||
## Concernant les issues
|
||||
|
||||
- Les issues concernent exclusivement les bugs, les demandes de fonctionnalités et les sujets liés à la conception. Les questions concernant d'autres sujets peuvent être fermées directement. Si vous avez des questions à propos de l'utilisation d'Element, veuillez vous rendre sur [Gitter](https://gitter.im/element-en/Lobby) pour obtenir de l'aide.
|
||||
|
||||
- Avant de soumettre une issue, veuillez vérifier si des problèmes similaires n'ont pas déjà été signalés.
|
||||
|
||||
- Veuillez spécifier la version de `Element` et `Vue` que vous utilisez, et fournir des informations sur le système d'exploitation et le navigateur. [JSFiddle](https://jsfiddle.net/) est recommandé afin de construire une démo pour que votre problème puisse être reproduit clairement.
|
||||
|
||||
## Concernant les pull requests
|
||||
|
||||
- Faites un fork de ce dépôt vers votre compte. Ne créez pas de branches ici.
|
||||
|
||||
- Les informations de validation doivent être formatées en tant que `[Nom du composant] : Info à propos de ce commit` (par exemple `Button : Fix xxx bug`)
|
||||
|
||||
- **NE PAS** inclure de fichiers dans le répertoire `lib`.
|
||||
|
||||
- Assurez-vous que l'exécution de `npm run dist` génère les bons fichiers.
|
||||
|
||||
- Pour des raisons de compatibilité et de taille de fichier, notre configuration babel n'importait que `preset-2015`, donc les API comme `Array.prototype.find` et `Object.assign` dans `ES2015` ne sont pas recommandées. Vous pouvez importer des polyfills si nécessaire.
|
||||
|
||||
- Faites un rebase avant la création d'une PR pour garder l'historique clair.
|
||||
|
||||
- Assurez-vous que les PRs sont créés dans la branche `dev` au lieu de la branche `master`.
|
||||
|
||||
- Si votre PR corrige un bug, veuillez fournir une description du bug en question.
|
||||
|
||||
- La fusion d'un PR nécessite deux responsables: l'un approuve les modifications après révision, puis l'autre les révise et les fusionne.
|
||||
|
||||
## Pré-requis
|
||||
`Node.js 4+`, `yarn` et `npm 3+` sont requis. Note: nous utilisons yarn pour verrouiller les versions des dépendances, donc vous devriez installer les dépendances en utilisant `yarn` au lieu de `npm install`.
|
||||
```shell
|
||||
git clone git@github.com:ElemeFE/element.git
|
||||
npm run dev
|
||||
|
||||
# open http://localhost:8085
|
||||
```
|
||||
|
||||
> **Remarque** : modifiez le fichier `examples/play/index.vue`, utilisez le composant auquel vous contribuez, puis lancez `npm run dev:play`, allez sur [http://localhost:8085](http://localhost:8085), regardez le résultat rapidement et facilement.
|
||||
|
||||
Pour le build:
|
||||
|
||||
```shell
|
||||
npm run dist
|
||||
```
|
||||
|
||||
## Concernant le développement de composants
|
||||
- Exécutez `make new <nom-du-composant>` pour créer un répertoire pour le nouveau composant. Les tests, le fichier d'entrée et la documentation sont inclus.
|
||||
- Reportez-vous au `Button` pour les composants imbriqués.
|
||||
- Reportez-vous à `Select` pour connaître les composants qui dépendent d'autres composants.
|
||||
|
||||
## Style du code
|
||||
Il suffit de se conformer à la configuration [ESLint](https://github.com/ElemeFE/eslint-config-elemefe) de [ElemeFE](https://github.com/elemefe).
|
||||
2
.github/CONTRIBUTING.zh-CN.md
vendored
@@ -41,8 +41,6 @@ npm run dev
|
||||
# open http://localhost:8085
|
||||
```
|
||||
|
||||
> **提示**:可以运行 `npm run dev:play`,修改 `examples/play/index.vue` 文件,调用你修改后的组件,仍然访问 [http://localhost:8085](http://localhost:8085),查看修改效果,更快更方便。
|
||||
|
||||
打包代码:
|
||||
|
||||
```shell
|
||||
|
||||
5
.github/ISSUE_TEMPLATE/config.yml
vendored
@@ -1,5 +0,0 @@
|
||||
blank_issues_enabled: true
|
||||
contact_links:
|
||||
- name: Create new issue
|
||||
url: https://elementui.github.io/issue-generator
|
||||
about: The issue which is not created via https://elementui.github.io/issue-generator will be closed immediately.
|
||||
2
.github/PULL_REQUEST_TEMPLATE.md
vendored
@@ -1,5 +1,5 @@
|
||||
Please make sure these boxes are checked before submitting your PR, thank you!
|
||||
|
||||
* [ ] Make sure you follow Element's contributing guide ([中文](https://github.com/ElemeFE/element/blob/master/.github/CONTRIBUTING.zh-CN.md) | [English](https://github.com/ElemeFE/element/blob/master/.github/CONTRIBUTING.en-US.md) | [Español](https://github.com/ElemeFE/element/blob/master/.github/CONTRIBUTING.es.md) | [Français](https://github.com/ElemeFE/element/blob/master/.github/CONTRIBUTING.fr-FR.md)).
|
||||
* [ ] Make sure you follow Element's contributing guide ([中文](https://github.com/ElemeFE/element/blob/master/.github/CONTRIBUTING.zh-CN.md) | [English](https://github.com/ElemeFE/element/blob/master/.github/CONTRIBUTING.en-US.md) | [Español](https://github.com/ElemeFE/element/blob/master/.github/CONTRIBUTING.es.md)).
|
||||
* [ ] Make sure you are merging your commits to `dev` branch.
|
||||
* [ ] Add some descriptions and refer relative issues for you PR.
|
||||
|
||||
17
.github/stale.yml
vendored
@@ -1,17 +0,0 @@
|
||||
# Number of days of inactivity before an issue becomes stale
|
||||
daysUntilStale: 365
|
||||
# Number of days of inactivity before a stale issue is closed
|
||||
daysUntilClose: 7
|
||||
# Issues with these labels will never be considered stale
|
||||
# exemptLabels:
|
||||
# - pinned
|
||||
# - security
|
||||
# Label to use when marking an issue as stale
|
||||
staleLabel: stale
|
||||
# Comment to post when marking an issue as stale. Set to `false` to disable
|
||||
markComment: >
|
||||
This issue has been automatically marked as stale because it has not had
|
||||
recent activity. It will be closed if no further activity occurs. Thank you
|
||||
for your contributions.
|
||||
# Comment to post when closing a stale issue. Set to `false` to disable
|
||||
closeComment: false
|
||||
45
.github/workflows/preview-build.yml
vendored
@@ -1,45 +0,0 @@
|
||||
name: Preview Build
|
||||
|
||||
on: pull_request
|
||||
|
||||
jobs:
|
||||
build:
|
||||
name: Build
|
||||
runs-on: ubuntu-latest
|
||||
env:
|
||||
PULL_REQUEST_NUMBER: ${{ github.event.number }}
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v2
|
||||
|
||||
- name: Setup node
|
||||
uses: actions/setup-node@v2
|
||||
with:
|
||||
node-version: '10.15.0'
|
||||
registry-url: https://registry.npmjs.com/
|
||||
|
||||
- name: Build
|
||||
run: npm run bootstrap && npm run deploy:build
|
||||
|
||||
|
||||
# share website dist
|
||||
- name: Upload artifact
|
||||
uses: actions/upload-artifact@v2
|
||||
with:
|
||||
name: docs
|
||||
path: examples/element-ui/
|
||||
retention-days: 1
|
||||
|
||||
# write pr.txt for share
|
||||
- name: Save pr number
|
||||
if: ${{ always() }}
|
||||
run: echo ${PULL_REQUEST_NUMBER} > ./pr.txt
|
||||
|
||||
# share pr number
|
||||
- name: Upload pr number
|
||||
if: ${{ always() }}
|
||||
uses: actions/upload-artifact@v2
|
||||
with:
|
||||
name: pr
|
||||
path: ./pr.txt
|
||||
retention-days: 1
|
||||
83
.github/workflows/preview-deploy.yml
vendored
@@ -1,83 +0,0 @@
|
||||
name: Preview Deploy
|
||||
|
||||
on:
|
||||
workflow_run:
|
||||
workflows: ['Preview Build']
|
||||
types:
|
||||
- completed
|
||||
|
||||
jobs:
|
||||
success:
|
||||
runs-on: ubuntu-latest
|
||||
if: github.event.workflow_run.event == 'pull_request' && github.event.workflow_run.conclusion == 'success'
|
||||
steps:
|
||||
- name: download pr artifact
|
||||
uses: dawidd6/action-download-artifact@v2
|
||||
with:
|
||||
workflow: ${{ github.event.workflow_run.workflow_id }}
|
||||
name: pr
|
||||
|
||||
- name: save PR id
|
||||
id: pr
|
||||
run: echo "::set-output name=id::$(<pr.txt)"
|
||||
|
||||
- name: download docs artifact
|
||||
uses: dawidd6/action-download-artifact@v2
|
||||
with:
|
||||
workflow: ${{ github.event.workflow_run.workflow_id }}
|
||||
workflow_conclusion: success
|
||||
name: docs
|
||||
|
||||
- name: upload surge service
|
||||
id: deploy
|
||||
run: |
|
||||
export DEPLOY_DOMAIN=https://preview-pr-${{ steps.pr.outputs.id }}-element-ui.surge.sh
|
||||
npx surge --project ./ --domain $DEPLOY_DOMAIN --token ${{ secrets.SURGE_TOKEN }}
|
||||
|
||||
- name: update status comment
|
||||
uses: actions-cool/maintain-one-comment@v1.2.1
|
||||
with:
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
body: |
|
||||
🎊 PR Preview has been successfully built and deployed to https://preview-pr-${{ steps.pr.outputs.id }}-element-ui.surge.sh
|
||||
<img width="300" src="https://user-images.githubusercontent.com/507615/90250366-88233900-de6e-11ea-95a5-84f0762ffd39.png">
|
||||
<!-- Sticky Pull Request Comment -->
|
||||
body-include: '<!-- Sticky Pull Request Comment -->'
|
||||
number: ${{ steps.pr.outputs.id }}
|
||||
|
||||
- name: The job failed
|
||||
if: ${{ failure() }}
|
||||
uses: actions-cool/maintain-one-comment@v1.2.1
|
||||
with:
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
body: |
|
||||
😭 Deploy PR Preview failed.
|
||||
<img width="300" src="https://user-images.githubusercontent.com/507615/90250824-4e066700-de6f-11ea-8230-600ecc3d6a6b.png">
|
||||
<!-- Sticky Pull Request Comment -->
|
||||
body-include: '<!-- Sticky Pull Request Comment -->'
|
||||
number: ${{ steps.pr.outputs.id }}
|
||||
|
||||
failed:
|
||||
runs-on: ubuntu-latest
|
||||
if: github.event.workflow_run.event == 'pull_request' && github.event.workflow_run.conclusion == 'failure'
|
||||
steps:
|
||||
- name: download pr artifact
|
||||
uses: dawidd6/action-download-artifact@v2
|
||||
with:
|
||||
workflow: ${{ github.event.workflow_run.workflow_id }}
|
||||
name: pr
|
||||
|
||||
- name: save PR id
|
||||
id: pr
|
||||
run: echo "::set-output name=id::$(<pr.txt)"
|
||||
|
||||
- name: The job failed
|
||||
uses: actions-cool/maintain-one-comment@v1.2.1
|
||||
with:
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
body: |
|
||||
😭 Deploy PR Preview failed.
|
||||
<img width="300" src="https://user-images.githubusercontent.com/507615/90250824-4e066700-de6f-11ea-8230-600ecc3d6a6b.png">
|
||||
<!-- Sticky Pull Request Comment -->
|
||||
body-include: '<!-- Sticky Pull Request Comment -->'
|
||||
number: ${{ steps.pr.outputs.id }}
|
||||
6
.gitignore
vendored
@@ -1,12 +1,8 @@
|
||||
node_modules
|
||||
.DS_Store
|
||||
npm-debug.log
|
||||
yarn-debug.log
|
||||
yarn-error.log
|
||||
lerna-debug.log
|
||||
npm-debug.log.*
|
||||
yarn-debug.log.*
|
||||
yarn-error.log.*
|
||||
lerna-debug.log.*
|
||||
lib
|
||||
.idea
|
||||
@@ -15,11 +11,9 @@ examples/element-ui
|
||||
examples/pages/en-US
|
||||
examples/pages/zh-CN
|
||||
examples/pages/es
|
||||
examples/pages/fr-FR
|
||||
fe.element/element-ui
|
||||
.npmrc
|
||||
coverage
|
||||
waiter.config.js
|
||||
build/bin/algolia-key.js
|
||||
.envrc
|
||||
.history/
|
||||
@@ -1,9 +1,10 @@
|
||||
sudo: false
|
||||
language: node_js
|
||||
node_js: 10
|
||||
addons:
|
||||
chrome: stable
|
||||
node_js: lts/*
|
||||
before_install:
|
||||
- export CHROME_BIN=chromium-browser
|
||||
- export DISPLAY=:99.0
|
||||
- sh -e /etc/init.d/xvfb start
|
||||
- export TRAVIS_COMMIT_MSG="[deploy] $(git log --format='%h - %B' --no-merges -n 1)"
|
||||
- export TRAVIS_COMMIT_USER="$(git log --no-merges -n 1 --format=%an)"
|
||||
- export TRAVIS_COMMIT_EMAIL="$(git log --no-merges -n 1 --format=%ae)"
|
||||
|
||||
1434
CHANGELOG.en-US.md
1567
CHANGELOG.es.md
2085
CHANGELOG.fr-FR.md
1424
CHANGELOG.zh-CN.md
123
README.md
@@ -36,23 +36,45 @@
|
||||
</a>
|
||||
</p>
|
||||
|
||||
<p align="center">
|
||||
<b>Special thanks to the generous sponsorship by:</b>
|
||||
</p>
|
||||
<table>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td align="center" valign="middle">
|
||||
<a href="https://tipe.io/?ref=element" target="_blank">
|
||||
<img width="150px" src="https://user-images.githubusercontent.com/1016365/34124854-48fafa06-e3e9-11e7-8c04-251055feebee.png">
|
||||
</a>
|
||||
</td>
|
||||
<td align="center" valign="middle">
|
||||
<a href="https://www.duotai.cn/?utm_source=element" target="_blank">
|
||||
<img width="140px" src="https://user-images.githubusercontent.com/10095631/39403151-c42dbcee-4ba5-11e8-9c09-8e5283da4144.png">
|
||||
</a>
|
||||
</td>
|
||||
<td align="center" valign="middle">
|
||||
<a href="https://www.duohui.cn/?utm_source=element&utm_medium=web&utm_campaign=element-index" target="_blank">
|
||||
<img width="150px" src="https://user-images.githubusercontent.com/10095631/35603534-bb24470c-0678-11e8-8bcc-17ceaef8cbef.png">
|
||||
</a>
|
||||
</td>
|
||||
<td align="center" valign="middle">
|
||||
<a href="https://bitsrc.io/" target="_blank">
|
||||
<img width="150px" src="https://user-images.githubusercontent.com/10095631/41342907-e44e7196-6f2f-11e8-92f2-47702dc8f059.png">
|
||||
</a>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
> A Vue.js 2.0 UI Toolkit for Web.
|
||||
|
||||
Element will stay with Vue 2.x
|
||||
|
||||
For Vue 3.0, we recommend using [Element Plus](https://github.com/element-plus/element-plus)(Element Plus is a community develop project)
|
||||
|
||||
For MiniProgram development, we recommend using [MorJS](https://github.com/eleme/morjs)
|
||||
|
||||
## Links
|
||||
- Homepage and documentation
|
||||
- [International users](http://element.eleme.io/#/en-US)
|
||||
- [Chinese users](http://element.eleme.io/#/zh-CN)
|
||||
- [Chinese users](http://element-cn.eleme.io/#/zh-CN)
|
||||
- [Spanish users](http://element.eleme.io/#/es)
|
||||
- [French users](http://element.eleme.io/#/fr-FR)
|
||||
- [awesome-element](https://github.com/ElementUI/awesome-element)
|
||||
- [FAQ](./FAQ.md)
|
||||
- [Vue.js 3.0 migration](https://github.com/element-plus/element-plus)
|
||||
- [Customize theme](http://element.eleme.io/#/en-US/component/custom-theme)
|
||||
- [Preview and generate theme online](https://elementui.github.io/theme-chalk-preview)
|
||||
- [Element for React](https://github.com/elemefe/element-react)
|
||||
@@ -97,7 +119,7 @@ Modern browsers and Internet Explorer 10+.
|
||||
## Development
|
||||
Skip this part if you just want to use Element.
|
||||
|
||||
For those who are interested in contributing to Element, please refer to our contributing guide ([中文](https://github.com/ElemeFE/element/blob/master/.github/CONTRIBUTING.zh-CN.md) | [English](https://github.com/ElemeFE/element/blob/master/.github/CONTRIBUTING.en-US.md) | [Español](https://github.com/ElemeFE/element/blob/master/.github/CONTRIBUTING.es.md) | [Français](https://github.com/ElemeFE/element/blob/master/.github/CONTRIBUTING.fr-FR.md)) to see how to run this project.
|
||||
For those who are interested in contributing to Element, please refer to our contributing guide ([中文](https://github.com/ElemeFE/element/blob/master/.github/CONTRIBUTING.zh-CN.md) | [English](https://github.com/ElemeFE/element/blob/master/.github/CONTRIBUTING.en-US.md) | [Español](https://github.com/ElemeFE/element/blob/master/.github/CONTRIBUTING.es.md)) to see how to run this project.
|
||||
|
||||
## Changelog
|
||||
Detailed changes for each release are documented in the [release notes](https://github.com/ElemeFE/element/releases).
|
||||
@@ -106,7 +128,7 @@ Detailed changes for each release are documented in the [release notes](https://
|
||||
We have collected some [frequently asked questions](https://github.com/ElemeFE/element/blob/master/FAQ.md). Before reporting an issue, please search if the FAQ has the answer to your problem.
|
||||
|
||||
## Contribution
|
||||
Please make sure to read the contributing guide ([中文](https://github.com/ElemeFE/element/blob/master/.github/CONTRIBUTING.zh-CN.md) | [English](https://github.com/ElemeFE/element/blob/master/.github/CONTRIBUTING.en-US.md) | [Español](https://github.com/ElemeFE/element/blob/master/.github/CONTRIBUTING.es.md) | [Français](https://github.com/ElemeFE/element/blob/master/.github/CONTRIBUTING.fr-FR.md)) before making a pull request.
|
||||
Please make sure to read the contributing guide ([中文](https://github.com/ElemeFE/element/blob/master/.github/CONTRIBUTING.zh-CN.md) | [English](https://github.com/ElemeFE/element/blob/master/.github/CONTRIBUTING.en-US.md) | [Español](https://github.com/ElemeFE/element/blob/master/.github/CONTRIBUTING.es.md)) before making a pull request.
|
||||
|
||||
## Special Thanks
|
||||
English documentation is brought to you by SwiftGG Translation Team:
|
||||
@@ -133,15 +155,82 @@ Spanish documentation is made possible by these community developers:
|
||||
- [sigfriedCub1990](https://github.com/sigfriedCub1990)
|
||||
- [thechosenjuan](https://github.com/thechosenjuan)
|
||||
|
||||
French documentation is made possible by these community developers:
|
||||
- [smalesys](https://github.com/smalesys)
|
||||
- [blombard](https://github.com/blombard)
|
||||
## Donation
|
||||
If you find Element useful, you can buy us a cup of coffee
|
||||
|
||||
## Join Discussion Group
|
||||
<img width="650" src="https://user-images.githubusercontent.com/10095631/42198577-587063dc-7ebb-11e8-892b-91e08f99ce1e.jpg" alt="donation">
|
||||
|
||||
Scan the QR code using [Dingtalk App](https://www.dingtalk.com/) to join in discussion group :
|
||||
## Backers
|
||||
|
||||
Support us with a monthly donation and help us continue our activities. [[Become a backer](https://opencollective.com/element#backer)]
|
||||
|
||||
<a href="https://opencollective.com/element/backer/0/website" target="_blank"><img src="https://opencollective.com/element/backer/0/avatar.svg"></a>
|
||||
<a href="https://opencollective.com/element/backer/1/website" target="_blank"><img src="https://opencollective.com/element/backer/1/avatar.svg"></a>
|
||||
<a href="https://opencollective.com/element/backer/2/website" target="_blank"><img src="https://opencollective.com/element/backer/2/avatar.svg"></a>
|
||||
<a href="https://opencollective.com/element/backer/3/website" target="_blank"><img src="https://opencollective.com/element/backer/3/avatar.svg"></a>
|
||||
<a href="https://opencollective.com/element/backer/4/website" target="_blank"><img src="https://opencollective.com/element/backer/4/avatar.svg"></a>
|
||||
<a href="https://opencollective.com/element/backer/5/website" target="_blank"><img src="https://opencollective.com/element/backer/5/avatar.svg"></a>
|
||||
<a href="https://opencollective.com/element/backer/6/website" target="_blank"><img src="https://opencollective.com/element/backer/6/avatar.svg"></a>
|
||||
<a href="https://opencollective.com/element/backer/7/website" target="_blank"><img src="https://opencollective.com/element/backer/7/avatar.svg"></a>
|
||||
<a href="https://opencollective.com/element/backer/8/website" target="_blank"><img src="https://opencollective.com/element/backer/8/avatar.svg"></a>
|
||||
<a href="https://opencollective.com/element/backer/9/website" target="_blank"><img src="https://opencollective.com/element/backer/9/avatar.svg"></a>
|
||||
<a href="https://opencollective.com/element/backer/10/website" target="_blank"><img src="https://opencollective.com/element/backer/10/avatar.svg"></a>
|
||||
<a href="https://opencollective.com/element/backer/11/website" target="_blank"><img src="https://opencollective.com/element/backer/11/avatar.svg"></a>
|
||||
<a href="https://opencollective.com/element/backer/12/website" target="_blank"><img src="https://opencollective.com/element/backer/12/avatar.svg"></a>
|
||||
<a href="https://opencollective.com/element/backer/13/website" target="_blank"><img src="https://opencollective.com/element/backer/13/avatar.svg"></a>
|
||||
<a href="https://opencollective.com/element/backer/14/website" target="_blank"><img src="https://opencollective.com/element/backer/14/avatar.svg"></a>
|
||||
<a href="https://opencollective.com/element/backer/15/website" target="_blank"><img src="https://opencollective.com/element/backer/15/avatar.svg"></a>
|
||||
<a href="https://opencollective.com/element/backer/16/website" target="_blank"><img src="https://opencollective.com/element/backer/16/avatar.svg"></a>
|
||||
<a href="https://opencollective.com/element/backer/17/website" target="_blank"><img src="https://opencollective.com/element/backer/17/avatar.svg"></a>
|
||||
<a href="https://opencollective.com/element/backer/18/website" target="_blank"><img src="https://opencollective.com/element/backer/18/avatar.svg"></a>
|
||||
<a href="https://opencollective.com/element/backer/19/website" target="_blank"><img src="https://opencollective.com/element/backer/19/avatar.svg"></a>
|
||||
<a href="https://opencollective.com/element/backer/20/website" target="_blank"><img src="https://opencollective.com/element/backer/20/avatar.svg"></a>
|
||||
<a href="https://opencollective.com/element/backer/21/website" target="_blank"><img src="https://opencollective.com/element/backer/21/avatar.svg"></a>
|
||||
<a href="https://opencollective.com/element/backer/22/website" target="_blank"><img src="https://opencollective.com/element/backer/22/avatar.svg"></a>
|
||||
<a href="https://opencollective.com/element/backer/23/website" target="_blank"><img src="https://opencollective.com/element/backer/23/avatar.svg"></a>
|
||||
<a href="https://opencollective.com/element/backer/24/website" target="_blank"><img src="https://opencollective.com/element/backer/24/avatar.svg"></a>
|
||||
<a href="https://opencollective.com/element/backer/25/website" target="_blank"><img src="https://opencollective.com/element/backer/25/avatar.svg"></a>
|
||||
<a href="https://opencollective.com/element/backer/26/website" target="_blank"><img src="https://opencollective.com/element/backer/26/avatar.svg"></a>
|
||||
<a href="https://opencollective.com/element/backer/27/website" target="_blank"><img src="https://opencollective.com/element/backer/27/avatar.svg"></a>
|
||||
<a href="https://opencollective.com/element/backer/28/website" target="_blank"><img src="https://opencollective.com/element/backer/28/avatar.svg"></a>
|
||||
<a href="https://opencollective.com/element/backer/29/website" target="_blank"><img src="https://opencollective.com/element/backer/29/avatar.svg"></a>
|
||||
|
||||
|
||||
## Sponsors
|
||||
|
||||
Become a sponsor and get your logo on our README on Github with a link to your site. [[Become a sponsor](https://opencollective.com/element#sponsor)]
|
||||
|
||||
<a href="https://opencollective.com/element/sponsor/0/website" target="_blank"><img src="https://opencollective.com/element/sponsor/0/avatar.svg"></a>
|
||||
<a href="https://opencollective.com/element/sponsor/1/website" target="_blank"><img src="https://opencollective.com/element/sponsor/1/avatar.svg"></a>
|
||||
<a href="https://opencollective.com/element/sponsor/2/website" target="_blank"><img src="https://opencollective.com/element/sponsor/2/avatar.svg"></a>
|
||||
<a href="https://opencollective.com/element/sponsor/3/website" target="_blank"><img src="https://opencollective.com/element/sponsor/3/avatar.svg"></a>
|
||||
<a href="https://opencollective.com/element/sponsor/4/website" target="_blank"><img src="https://opencollective.com/element/sponsor/4/avatar.svg"></a>
|
||||
<a href="https://opencollective.com/element/sponsor/5/website" target="_blank"><img src="https://opencollective.com/element/sponsor/5/avatar.svg"></a>
|
||||
<a href="https://opencollective.com/element/sponsor/6/website" target="_blank"><img src="https://opencollective.com/element/sponsor/6/avatar.svg"></a>
|
||||
<a href="https://opencollective.com/element/sponsor/7/website" target="_blank"><img src="https://opencollective.com/element/sponsor/7/avatar.svg"></a>
|
||||
<a href="https://opencollective.com/element/sponsor/8/website" target="_blank"><img src="https://opencollective.com/element/sponsor/8/avatar.svg"></a>
|
||||
<a href="https://opencollective.com/element/sponsor/9/website" target="_blank"><img src="https://opencollective.com/element/sponsor/9/avatar.svg"></a>
|
||||
<a href="https://opencollective.com/element/sponsor/10/website" target="_blank"><img src="https://opencollective.com/element/sponsor/10/avatar.svg"></a>
|
||||
<a href="https://opencollective.com/element/sponsor/11/website" target="_blank"><img src="https://opencollective.com/element/sponsor/11/avatar.svg"></a>
|
||||
<a href="https://opencollective.com/element/sponsor/12/website" target="_blank"><img src="https://opencollective.com/element/sponsor/12/avatar.svg"></a>
|
||||
<a href="https://opencollective.com/element/sponsor/13/website" target="_blank"><img src="https://opencollective.com/element/sponsor/13/avatar.svg"></a>
|
||||
<a href="https://opencollective.com/element/sponsor/14/website" target="_blank"><img src="https://opencollective.com/element/sponsor/14/avatar.svg"></a>
|
||||
<a href="https://opencollective.com/element/sponsor/15/website" target="_blank"><img src="https://opencollective.com/element/sponsor/15/avatar.svg"></a>
|
||||
<a href="https://opencollective.com/element/sponsor/16/website" target="_blank"><img src="https://opencollective.com/element/sponsor/16/avatar.svg"></a>
|
||||
<a href="https://opencollective.com/element/sponsor/17/website" target="_blank"><img src="https://opencollective.com/element/sponsor/17/avatar.svg"></a>
|
||||
<a href="https://opencollective.com/element/sponsor/18/website" target="_blank"><img src="https://opencollective.com/element/sponsor/18/avatar.svg"></a>
|
||||
<a href="https://opencollective.com/element/sponsor/19/website" target="_blank"><img src="https://opencollective.com/element/sponsor/19/avatar.svg"></a>
|
||||
<a href="https://opencollective.com/element/sponsor/20/website" target="_blank"><img src="https://opencollective.com/element/sponsor/20/avatar.svg"></a>
|
||||
<a href="https://opencollective.com/element/sponsor/21/website" target="_blank"><img src="https://opencollective.com/element/sponsor/21/avatar.svg"></a>
|
||||
<a href="https://opencollective.com/element/sponsor/22/website" target="_blank"><img src="https://opencollective.com/element/sponsor/22/avatar.svg"></a>
|
||||
<a href="https://opencollective.com/element/sponsor/23/website" target="_blank"><img src="https://opencollective.com/element/sponsor/23/avatar.svg"></a>
|
||||
<a href="https://opencollective.com/element/sponsor/24/website" target="_blank"><img src="https://opencollective.com/element/sponsor/24/avatar.svg"></a>
|
||||
<a href="https://opencollective.com/element/sponsor/25/website" target="_blank"><img src="https://opencollective.com/element/sponsor/25/avatar.svg"></a>
|
||||
<a href="https://opencollective.com/element/sponsor/26/website" target="_blank"><img src="https://opencollective.com/element/sponsor/26/avatar.svg"></a>
|
||||
<a href="https://opencollective.com/element/sponsor/27/website" target="_blank"><img src="https://opencollective.com/element/sponsor/27/avatar.svg"></a>
|
||||
<a href="https://opencollective.com/element/sponsor/28/website" target="_blank"><img src="https://opencollective.com/element/sponsor/28/avatar.svg"></a>
|
||||
<a href="https://opencollective.com/element/sponsor/29/website" target="_blank"><img src="https://opencollective.com/element/sponsor/29/avatar.svg"></a>
|
||||
|
||||
<img alt="Join Discusion Group" src="https://user-images.githubusercontent.com/17680888/93177882-0ae92d80-f766-11ea-870d-3fa2d7f06454.png" width="300">
|
||||
|
||||
|
||||
## LICENSE
|
||||
|
||||
@@ -27,7 +27,6 @@ const install = function(Vue, opts = {}) {
|
||||
Vue.component(component.name, component);
|
||||
});
|
||||
|
||||
Vue.use(InfiniteScroll);
|
||||
Vue.use(Loading.directive);
|
||||
|
||||
Vue.prototype.$ELEMENT = {
|
||||
@@ -77,7 +76,7 @@ ComponentNames.forEach(name => {
|
||||
package: name
|
||||
}));
|
||||
|
||||
if (['Loading', 'MessageBox', 'Notification', 'Message', 'InfiniteScroll'].indexOf(componentName) === -1) {
|
||||
if (['Loading', 'MessageBox', 'Notification', 'Message'].indexOf(componentName) === -1) {
|
||||
installTemplate.push(render(INSTALL_COMPONENT_TEMPLATE, {
|
||||
name: componentName,
|
||||
component: name
|
||||
|
||||
@@ -10,11 +10,10 @@ const client = algoliasearch('4C63BTGP6S', key);
|
||||
const langs = {
|
||||
'zh-CN': 'element-zh',
|
||||
'en-US': 'element-en',
|
||||
'es': 'element-es',
|
||||
'fr-FR': 'element-fr'
|
||||
'es': 'element-es'
|
||||
};
|
||||
|
||||
['zh-CN', 'en-US', 'es', 'fr-FR'].forEach(lang => {
|
||||
['zh-CN', 'en-US', 'es'].forEach(lang => {
|
||||
const indexName = langs[lang];
|
||||
const index = client.initIndex(indexName);
|
||||
index.clearIndex(err => {
|
||||
|
||||
@@ -17,6 +17,4 @@ nodes.forEach((node) => {
|
||||
}
|
||||
});
|
||||
|
||||
classList.reverse(); // 希望按 css 文件顺序倒序排列
|
||||
|
||||
fs.writeFile(path.resolve(__dirname, '../../examples/icon.json'), JSON.stringify(classList), () => {});
|
||||
|
||||
@@ -11,7 +11,6 @@ if (!process.argv[2]) {
|
||||
}
|
||||
|
||||
const path = require('path');
|
||||
const fs = require('fs');
|
||||
const fileSave = require('file-save');
|
||||
const uppercamelcase = require('uppercamelcase');
|
||||
const componentname = process.argv[2];
|
||||
@@ -54,10 +53,6 @@ export default {
|
||||
filename: path.join('../../examples/docs/es', `${componentname}.md`),
|
||||
content: `## ${ComponentName}`
|
||||
},
|
||||
{
|
||||
filename: path.join('../../examples/docs/fr-FR', `${componentname}.md`),
|
||||
content: `## ${ComponentName}`
|
||||
},
|
||||
{
|
||||
filename: path.join('../../test/unit/specs', `${componentname}.spec.js`),
|
||||
content: `import { createTest, destroyVM } from '../util';
|
||||
@@ -105,29 +100,6 @@ fileSave(path.join(__dirname, '../../components.json'))
|
||||
.write(JSON.stringify(componentsFile, null, ' '), 'utf8')
|
||||
.end('\n');
|
||||
|
||||
// 添加到 index.scss
|
||||
const sassPath = path.join(__dirname, '../../packages/theme-chalk/src/index.scss');
|
||||
const sassImportText = `${fs.readFileSync(sassPath)}@import "./${componentname}.scss";`;
|
||||
fileSave(sassPath)
|
||||
.write(sassImportText, 'utf8')
|
||||
.end('\n');
|
||||
|
||||
// 添加到 element-ui.d.ts
|
||||
const elementTsPath = path.join(__dirname, '../../types/element-ui.d.ts');
|
||||
|
||||
let elementTsText = `${fs.readFileSync(elementTsPath)}
|
||||
/** ${ComponentName} Component */
|
||||
export class ${ComponentName} extends El${ComponentName} {}`;
|
||||
|
||||
const index = elementTsText.indexOf('export') - 1;
|
||||
const importString = `import { El${ComponentName} } from './${componentname}'`;
|
||||
|
||||
elementTsText = elementTsText.slice(0, index) + importString + '\n' + elementTsText.slice(index);
|
||||
|
||||
fileSave(elementTsPath)
|
||||
.write(elementTsText, 'utf8')
|
||||
.end('\n');
|
||||
|
||||
// 创建 package
|
||||
Files.forEach(file => {
|
||||
fileSave(path.join(PackagePath, file.filename))
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
var fs = require('fs');
|
||||
var path = require('path');
|
||||
var version = process.env.VERSION || require('../../package.json').version;
|
||||
var content = { '1.4.13': '1.4', '2.0.11': '2.0', '2.1.0': '2.1', '2.2.2': '2.2', '2.3.9': '2.3', '2.4.11': '2.4', '2.5.4': '2.5', '2.6.3': '2.6', '2.7.2': '2.7', '2.8.2': '2.8', '2.9.2': '2.9', '2.10.1': '2.10', '2.11.1': '2.11', '2.12.0': '2.12', '2.13.2': '2.13', '2.14.1': '2.14' };
|
||||
if (!content[version]) content[version] = '2.15';
|
||||
var content = { '1.4.13': '1.4', '2.0.11': '2.0', '2.1.0': '2.1', '2.2.2': '2.2', '2.3.9': '2.3' };
|
||||
if (!content[version]) content[version] = '2.4';
|
||||
fs.writeFileSync(path.resolve(__dirname, '../../examples/versions.json'), JSON.stringify(content));
|
||||
|
||||
@@ -2,6 +2,7 @@ var path = require('path');
|
||||
var fs = require('fs');
|
||||
var nodeExternals = require('webpack-node-externals');
|
||||
var Components = require('../components.json');
|
||||
var saladConfig = require('./salad.config.json');
|
||||
|
||||
var utilsList = fs.readdirSync(path.resolve(__dirname, '../src/utils'));
|
||||
var mixinsList = fs.readdirSync(path.resolve(__dirname, '../src/mixins'));
|
||||
@@ -46,4 +47,13 @@ exports.vue = {
|
||||
amd: 'vue'
|
||||
};
|
||||
|
||||
exports.jsexclude = /node_modules|utils\/popper\.js|utils\/date\.js|utils\/lodash\.js/;
|
||||
exports.jsexclude = /node_modules|utils\/popper\.js|utils\/date.\js/;
|
||||
|
||||
exports.postcss = function(webapck) {
|
||||
saladConfig.features.partialImport = {
|
||||
addDependencyTo: webapck
|
||||
};
|
||||
return [
|
||||
require('postcss-salad')(saladConfig)
|
||||
];
|
||||
};
|
||||
|
||||
@@ -40,7 +40,7 @@ if [ "$TRAVIS_TAG" ]; then
|
||||
# build sub folder
|
||||
echo $TRAVIS_TAG
|
||||
|
||||
SUB_FOLDER='2.15'
|
||||
SUB_FOLDER='2.4'
|
||||
mkdir $SUB_FOLDER
|
||||
rm -rf *.js *.css *.map static
|
||||
rm -rf $SUB_FOLDER/**
|
||||
|
||||
@@ -1,13 +1,12 @@
|
||||
#! /bin/sh
|
||||
set -ex
|
||||
mkdir temp_web
|
||||
npm run deploy:build
|
||||
cd temp_web
|
||||
git clone --depth 1 -b gh-pages --single-branch https://github.com/ElemeFE/element.git && cd element
|
||||
|
||||
# build sub folder
|
||||
SUB_FOLDER='2.15'
|
||||
mkdir -p $SUB_FOLDER
|
||||
SUB_FOLDER='2.4'
|
||||
mkdir $SUB_FOLDER
|
||||
rm -rf *.js *.css *.map static
|
||||
rm -rf $SUB_FOLDER/**
|
||||
cp -rf ../../examples/element-ui/** .
|
||||
@@ -15,5 +14,5 @@ cp -rf ../../examples/element-ui/** $SUB_FOLDER/
|
||||
cd ../..
|
||||
|
||||
# deploy domestic site
|
||||
faas deploy daily -P element
|
||||
rm -rf temp_web
|
||||
faas deploy alpha
|
||||
rm -rf temp_web
|
||||
@@ -1,26 +0,0 @@
|
||||
const Config = require('markdown-it-chain');
|
||||
const anchorPlugin = require('markdown-it-anchor');
|
||||
const slugify = require('transliteration').slugify;
|
||||
const containers = require('./containers');
|
||||
const overWriteFenceRule = require('./fence');
|
||||
|
||||
const config = new Config();
|
||||
|
||||
config
|
||||
.options.html(true).end()
|
||||
|
||||
.plugin('anchor').use(anchorPlugin, [
|
||||
{
|
||||
level: 2,
|
||||
slugify: slugify,
|
||||
permalink: true,
|
||||
permalinkBefore: true
|
||||
}
|
||||
]).end()
|
||||
|
||||
.plugin('containers').use(containers).end();
|
||||
|
||||
const md = config.toMd();
|
||||
overWriteFenceRule(md);
|
||||
|
||||
module.exports = md;
|
||||
@@ -1,24 +0,0 @@
|
||||
const mdContainer = require('markdown-it-container');
|
||||
|
||||
module.exports = md => {
|
||||
md.use(mdContainer, 'demo', {
|
||||
validate(params) {
|
||||
return params.trim().match(/^demo\s*(.*)$/);
|
||||
},
|
||||
render(tokens, idx) {
|
||||
const m = tokens[idx].info.trim().match(/^demo\s*(.*)$/);
|
||||
if (tokens[idx].nesting === 1) {
|
||||
const description = m && m.length > 1 ? m[1] : '';
|
||||
const content = tokens[idx + 1].type === 'fence' ? tokens[idx + 1].content : '';
|
||||
return `<demo-block>
|
||||
${description ? `<div>${md.render(description)}</div>` : ''}
|
||||
<!--element-demo: ${content}:element-demo-->
|
||||
`;
|
||||
}
|
||||
return '</demo-block>';
|
||||
}
|
||||
});
|
||||
|
||||
md.use(mdContainer, 'tip');
|
||||
md.use(mdContainer, 'warning');
|
||||
};
|
||||
@@ -1,14 +0,0 @@
|
||||
// 覆盖默认的 fence 渲染策略
|
||||
module.exports = md => {
|
||||
const defaultRender = md.renderer.rules.fence;
|
||||
md.renderer.rules.fence = (tokens, idx, options, env, self) => {
|
||||
const token = tokens[idx];
|
||||
// 判断该 fence 是否在 :::demo 内
|
||||
const prevToken = tokens[idx - 1];
|
||||
const isInDemoContainer = prevToken && prevToken.nesting === 1 && prevToken.info.trim().match(/^demo\s*(.*)$/);
|
||||
if (token.info === 'html' && isInDemoContainer) {
|
||||
return `<template slot="highlight"><pre v-pre><code class="html">${md.utils.escapeHtml(token.content)}</code></pre></template>`;
|
||||
}
|
||||
return defaultRender(tokens, idx, options, env, self);
|
||||
};
|
||||
};
|
||||
@@ -1,67 +0,0 @@
|
||||
const {
|
||||
stripScript,
|
||||
stripTemplate,
|
||||
genInlineComponentText
|
||||
} = require('./util');
|
||||
const md = require('./config');
|
||||
|
||||
module.exports = function(source) {
|
||||
const content = md.render(source);
|
||||
|
||||
const startTag = '<!--element-demo:';
|
||||
const startTagLen = startTag.length;
|
||||
const endTag = ':element-demo-->';
|
||||
const endTagLen = endTag.length;
|
||||
|
||||
let componenetsString = '';
|
||||
let id = 0; // demo 的 id
|
||||
let output = []; // 输出的内容
|
||||
let start = 0; // 字符串开始位置
|
||||
|
||||
let commentStart = content.indexOf(startTag);
|
||||
let commentEnd = content.indexOf(endTag, commentStart + startTagLen);
|
||||
while (commentStart !== -1 && commentEnd !== -1) {
|
||||
output.push(content.slice(start, commentStart));
|
||||
|
||||
const commentContent = content.slice(commentStart + startTagLen, commentEnd);
|
||||
const html = stripTemplate(commentContent);
|
||||
const script = stripScript(commentContent);
|
||||
let demoComponentContent = genInlineComponentText(html, script);
|
||||
const demoComponentName = `element-demo${id}`;
|
||||
output.push(`<template slot="source"><${demoComponentName} /></template>`);
|
||||
componenetsString += `${JSON.stringify(demoComponentName)}: ${demoComponentContent},`;
|
||||
|
||||
// 重新计算下一次的位置
|
||||
id++;
|
||||
start = commentEnd + endTagLen;
|
||||
commentStart = content.indexOf(startTag, start);
|
||||
commentEnd = content.indexOf(endTag, commentStart + startTagLen);
|
||||
}
|
||||
|
||||
// 仅允许在 demo 不存在时,才可以在 Markdown 中写 script 标签
|
||||
// todo: 优化这段逻辑
|
||||
let pageScript = '';
|
||||
if (componenetsString) {
|
||||
pageScript = `<script>
|
||||
export default {
|
||||
name: 'component-doc',
|
||||
components: {
|
||||
${componenetsString}
|
||||
}
|
||||
}
|
||||
</script>`;
|
||||
} else if (content.indexOf('<script>') === 0) { // 硬编码,有待改善
|
||||
start = content.indexOf('</script>') + '</script>'.length;
|
||||
pageScript = content.slice(0, start);
|
||||
}
|
||||
|
||||
output.push(content.slice(start));
|
||||
return `
|
||||
<template>
|
||||
<section class="content element-doc">
|
||||
${output.join('')}
|
||||
</section>
|
||||
</template>
|
||||
${pageScript}
|
||||
`;
|
||||
};
|
||||
@@ -1,79 +0,0 @@
|
||||
const { compileTemplate } = require('@vue/component-compiler-utils');
|
||||
const compiler = require('vue-template-compiler');
|
||||
|
||||
function stripScript(content) {
|
||||
const result = content.match(/<(script)>([\s\S]+)<\/\1>/);
|
||||
return result && result[2] ? result[2].trim() : '';
|
||||
}
|
||||
|
||||
function stripStyle(content) {
|
||||
const result = content.match(/<(style)\s*>([\s\S]+)<\/\1>/);
|
||||
return result && result[2] ? result[2].trim() : '';
|
||||
}
|
||||
|
||||
// 编写例子时不一定有 template。所以采取的方案是剔除其他的内容
|
||||
function stripTemplate(content) {
|
||||
content = content.trim();
|
||||
if (!content) {
|
||||
return content;
|
||||
}
|
||||
return content.replace(/<(script|style)[\s\S]+<\/\1>/g, '').trim();
|
||||
}
|
||||
|
||||
function pad(source) {
|
||||
return source
|
||||
.split(/\r?\n/)
|
||||
.map(line => ` ${line}`)
|
||||
.join('\n');
|
||||
}
|
||||
|
||||
function genInlineComponentText(template, script) {
|
||||
// https://github.com/vuejs/vue-loader/blob/423b8341ab368c2117931e909e2da9af74503635/lib/loaders/templateLoader.js#L46
|
||||
const finalOptions = {
|
||||
source: `<div>${template}</div>`,
|
||||
filename: 'inline-component', // TODO:这里有待调整
|
||||
compiler
|
||||
};
|
||||
const compiled = compileTemplate(finalOptions);
|
||||
// tips
|
||||
if (compiled.tips && compiled.tips.length) {
|
||||
compiled.tips.forEach(tip => {
|
||||
console.warn(tip);
|
||||
});
|
||||
}
|
||||
// errors
|
||||
if (compiled.errors && compiled.errors.length) {
|
||||
console.error(
|
||||
`\n Error compiling template:\n${pad(compiled.source)}\n` +
|
||||
compiled.errors.map(e => ` - ${e}`).join('\n') +
|
||||
'\n'
|
||||
);
|
||||
}
|
||||
let demoComponentContent = `
|
||||
${compiled.code}
|
||||
`;
|
||||
// todo: 这里采用了硬编码有待改进
|
||||
script = script.trim();
|
||||
if (script) {
|
||||
script = script.replace(/export\s+default/, 'const democomponentExport =');
|
||||
} else {
|
||||
script = 'const democomponentExport = {}';
|
||||
}
|
||||
demoComponentContent = `(function() {
|
||||
${demoComponentContent}
|
||||
${script}
|
||||
return {
|
||||
render,
|
||||
staticRenderFns,
|
||||
...democomponentExport
|
||||
}
|
||||
})()`;
|
||||
return demoComponentContent;
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
stripScript,
|
||||
stripStyle,
|
||||
stripTemplate,
|
||||
genInlineComponentText
|
||||
};
|
||||
@@ -1,10 +1,10 @@
|
||||
#!/usr/bin/env sh
|
||||
set -e
|
||||
|
||||
git checkout master
|
||||
git merge dev
|
||||
|
||||
VERSION=`npx select-version-cli`
|
||||
#!/usr/bin/env sh
|
||||
set -e
|
||||
echo "Enter release version: "
|
||||
read VERSION
|
||||
|
||||
read -p "Releasing $VERSION - are you sure? (y/n)" -n 1 -r
|
||||
echo # (optional) move to a new line
|
||||
@@ -15,9 +15,6 @@ then
|
||||
# build
|
||||
VERSION=$VERSION npm run dist
|
||||
|
||||
# ssr test
|
||||
node test/ssr/require.test.js
|
||||
|
||||
# publish theme
|
||||
echo "Releasing theme-chalk $VERSION ..."
|
||||
cd packages/theme-chalk
|
||||
|
||||
16
build/salad.config.json
Normal file
@@ -0,0 +1,16 @@
|
||||
{
|
||||
"browsers": ["ie > 8", "last 2 versions"],
|
||||
"features": {
|
||||
"bem": {
|
||||
"shortcuts": {
|
||||
"component": "b",
|
||||
"modifier": "m",
|
||||
"descendent": "e"
|
||||
},
|
||||
"separators": {
|
||||
"descendent": "__",
|
||||
"modifier": "--"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
34
build/strip-tags.js
Normal file
@@ -0,0 +1,34 @@
|
||||
/*!
|
||||
* strip-tags <https://github.com/jonschlinkert/strip-tags>
|
||||
*
|
||||
* Copyright (c) 2015 Jon Schlinkert, contributors.
|
||||
* Licensed under the MIT license.
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
var cheerio = require('cheerio');
|
||||
|
||||
exports.strip = function(str, tags) {
|
||||
var $ = cheerio.load(str, {decodeEntities: false});
|
||||
|
||||
if (!tags || tags.length === 0) {
|
||||
return str;
|
||||
}
|
||||
|
||||
tags = !Array.isArray(tags) ? [tags] : tags;
|
||||
var len = tags.length;
|
||||
|
||||
while (len--) {
|
||||
$(tags[len]).remove();
|
||||
}
|
||||
|
||||
return $.html();
|
||||
};
|
||||
|
||||
exports.fetch = function(str, tag) {
|
||||
var $ = cheerio.load(str, {decodeEntities: false});
|
||||
if (!tag) return str;
|
||||
|
||||
return $(tag).html();
|
||||
};
|
||||
@@ -14,8 +14,6 @@ module.exports = {
|
||||
publicPath: '/dist/',
|
||||
filename: 'element-ui.common.js',
|
||||
chunkFilename: '[id].js',
|
||||
libraryExport: 'default',
|
||||
library: 'ELEMENT',
|
||||
libraryTarget: 'commonjs2'
|
||||
},
|
||||
resolve: {
|
||||
@@ -52,7 +50,11 @@ module.exports = {
|
||||
},
|
||||
{
|
||||
test: /\.css$/,
|
||||
loaders: ['style-loader', 'css-loader']
|
||||
loaders: ['style-loader', 'css-loader', 'postcss-loader']
|
||||
},
|
||||
{
|
||||
test: /\.scss$/,
|
||||
loaders: ['style-loader', 'css-loader', 'sass-loader']
|
||||
},
|
||||
{
|
||||
test: /\.(svg|otf|ttf|woff2?|eot|gif|png|jpe?g)(\?\S*)?$/,
|
||||
|
||||
@@ -47,7 +47,11 @@ const webpackConfig = {
|
||||
},
|
||||
{
|
||||
test: /\.css$/,
|
||||
loaders: ['style-loader', 'css-loader']
|
||||
loaders: ['style-loader', 'css-loader', 'postcss-loader']
|
||||
},
|
||||
{
|
||||
test: /\.scss$/,
|
||||
loaders: ['style-loader', 'css-loader', 'sass-loader']
|
||||
},
|
||||
{
|
||||
test: /\.(svg|otf|ttf|woff2?|eot|gif|png|jpe?g)(\?\S*)?$/,
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
const path = require('path');
|
||||
const ProgressBarPlugin = require('progress-bar-webpack-plugin');
|
||||
const VueLoaderPlugin = require('vue-loader/lib/plugin');
|
||||
const TerserPlugin = require('terser-webpack-plugin');
|
||||
|
||||
const config = require('./config');
|
||||
|
||||
@@ -16,10 +15,8 @@ module.exports = {
|
||||
filename: 'index.js',
|
||||
chunkFilename: '[id].js',
|
||||
libraryTarget: 'umd',
|
||||
libraryExport: 'default',
|
||||
library: 'ELEMENT',
|
||||
umdNamedDefine: true,
|
||||
globalObject: 'typeof self !== \'undefined\' ? self : this'
|
||||
umdNamedDefine: true
|
||||
},
|
||||
resolve: {
|
||||
extensions: ['.js', '.vue', '.json'],
|
||||
@@ -28,17 +25,6 @@ module.exports = {
|
||||
externals: {
|
||||
vue: config.vue
|
||||
},
|
||||
optimization: {
|
||||
minimizer: [
|
||||
new TerserPlugin({
|
||||
terserOptions: {
|
||||
output: {
|
||||
comments: false
|
||||
}
|
||||
}
|
||||
})
|
||||
]
|
||||
},
|
||||
performance: {
|
||||
hints: false
|
||||
},
|
||||
@@ -61,6 +47,22 @@ module.exports = {
|
||||
preserveWhitespace: false
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
test: /\.css$/,
|
||||
loaders: ['style-loader', 'css-loader', 'postcss-loader']
|
||||
},
|
||||
{
|
||||
test: /\.scss$/,
|
||||
loaders: ['style-loader', 'css-loader', 'sass-loader']
|
||||
},
|
||||
{
|
||||
test: /\.(svg|otf|ttf|woff2?|eot|gif|png|jpe?g)(\?\S*)?$/,
|
||||
loader: 'url-loader',
|
||||
query: {
|
||||
limit: 10000,
|
||||
name: path.posix.join('static', '[name].[hash:7].[ext]')
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
|
||||
@@ -5,19 +5,35 @@ const CopyWebpackPlugin = require('copy-webpack-plugin');
|
||||
const HtmlWebpackPlugin = require('html-webpack-plugin');
|
||||
const ProgressBarPlugin = require('progress-bar-webpack-plugin');
|
||||
const VueLoaderPlugin = require('vue-loader/lib/plugin');
|
||||
const OptimizeCSSAssetsPlugin = require('optimize-css-assets-webpack-plugin');
|
||||
const UglifyJsPlugin = require('uglifyjs-webpack-plugin');
|
||||
const launchEditorMiddleware = require('launch-editor-middleware');
|
||||
const md = require('markdown-it')();
|
||||
const slugify = require('transliteration').slugify;
|
||||
|
||||
const striptags = require('./strip-tags');
|
||||
const config = require('./config');
|
||||
|
||||
const isProd = process.env.NODE_ENV === 'production';
|
||||
const isPlay = !!process.env.PLAY_ENV;
|
||||
|
||||
function convert(str) {
|
||||
str = str.replace(/(&#x)(\w{4});/gi, function($0) {
|
||||
return String.fromCharCode(parseInt(encodeURIComponent($0).replace(/(%26%23x)(\w{4})(%3B)/g, '$2'), 16));
|
||||
});
|
||||
return str;
|
||||
}
|
||||
|
||||
function wrap(render) {
|
||||
return function() {
|
||||
return render.apply(this, arguments)
|
||||
.replace('<code v-pre class="', '<code class="hljs ')
|
||||
.replace('<code>', '<code class="hljs">');
|
||||
};
|
||||
}
|
||||
|
||||
const webpackConfig = {
|
||||
mode: process.env.NODE_ENV,
|
||||
entry: isProd ? {
|
||||
docs: './examples/entry.js'
|
||||
docs: './examples/entry.js',
|
||||
'element-ui': './src/index.js'
|
||||
} : (isPlay ? './examples/play.js' : './examples/entry.js'),
|
||||
output: {
|
||||
path: path.resolve(process.cwd(), './examples/element-ui/'),
|
||||
@@ -34,16 +50,7 @@ const webpackConfig = {
|
||||
host: '0.0.0.0',
|
||||
port: 8085,
|
||||
publicPath: '/',
|
||||
hot: true,
|
||||
before: (app) => {
|
||||
/*
|
||||
* 编辑器类型 :此处的指令表示的时各个各个编辑器在cmd或terminal中的命令
|
||||
* webstorm
|
||||
* code // vscode
|
||||
* idea
|
||||
*/
|
||||
app.use('/__open-in-editor', launchEditorMiddleware('code'));
|
||||
}
|
||||
noInfo: true
|
||||
},
|
||||
performance: {
|
||||
hints: false
|
||||
@@ -75,8 +82,16 @@ const webpackConfig = {
|
||||
}
|
||||
},
|
||||
{
|
||||
test: /\.(scss|css)$/,
|
||||
use: [
|
||||
test: /\.css$/,
|
||||
loaders: [
|
||||
isProd ? MiniCssExtractPlugin.loader : 'style-loader',
|
||||
'css-loader',
|
||||
'postcss-loader'
|
||||
]
|
||||
},
|
||||
{
|
||||
test: /\.scss$/,
|
||||
loaders: [
|
||||
isProd ? MiniCssExtractPlugin.loader : 'style-loader',
|
||||
'css-loader',
|
||||
'sass-loader'
|
||||
@@ -84,24 +99,67 @@ const webpackConfig = {
|
||||
},
|
||||
{
|
||||
test: /\.md$/,
|
||||
use: [
|
||||
loaders: [
|
||||
{
|
||||
loader: 'vue-loader',
|
||||
options: {
|
||||
compilerOptions: {
|
||||
preserveWhitespace: false
|
||||
}
|
||||
}
|
||||
loader: 'vue-loader'
|
||||
},
|
||||
{
|
||||
loader: path.resolve(__dirname, './md-loader/index.js')
|
||||
loader: 'vue-markdown-loader/lib/markdown-compiler',
|
||||
options: {
|
||||
preventExtract: true,
|
||||
raw: true,
|
||||
preprocess: function(MarkdownIt, source) {
|
||||
MarkdownIt.renderer.rules.table_open = function() {
|
||||
return '<table class="table">';
|
||||
};
|
||||
MarkdownIt.renderer.rules.fence = wrap(MarkdownIt.renderer.rules.fence);
|
||||
return source;
|
||||
},
|
||||
use: [
|
||||
[require('markdown-it-anchor'), {
|
||||
level: 2,
|
||||
slugify: slugify,
|
||||
permalink: true,
|
||||
permalinkBefore: true
|
||||
}],
|
||||
[require('markdown-it-container'), 'demo', {
|
||||
validate: function(params) {
|
||||
return params.trim().match(/^demo\s*(.*)$/);
|
||||
},
|
||||
|
||||
render: function(tokens, idx) {
|
||||
var m = tokens[idx].info.trim().match(/^demo\s*(.*)$/);
|
||||
if (tokens[idx].nesting === 1) {
|
||||
var description = (m && m.length > 1) ? m[1] : '';
|
||||
var content = tokens[idx + 1].content;
|
||||
var html = convert(striptags.strip(content, ['script', 'style'])).replace(/(<[^>]*)=""(?=.*>)/g, '$1');
|
||||
var script = striptags.fetch(content, 'script');
|
||||
var style = striptags.fetch(content, 'style');
|
||||
var jsfiddle = { html: html, script: script, style: style };
|
||||
var descriptionHTML = description
|
||||
? md.render(description)
|
||||
: '';
|
||||
|
||||
jsfiddle = md.utils.escapeHtml(JSON.stringify(jsfiddle));
|
||||
|
||||
return `<demo-block class="demo-box" :jsfiddle="${jsfiddle}">
|
||||
<div class="source" slot="source">${html}</div>
|
||||
${descriptionHTML}
|
||||
<div class="highlight" slot="highlight">`;
|
||||
}
|
||||
return '</div></demo-block>\n';
|
||||
}
|
||||
}],
|
||||
[require('markdown-it-container'), 'tip'],
|
||||
[require('markdown-it-container'), 'warning']
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
test: /\.(svg|otf|ttf|woff2?|eot|gif|png|jpe?g)(\?\S*)?$/,
|
||||
loader: 'url-loader',
|
||||
// todo: 这种写法有待调整
|
||||
query: {
|
||||
limit: 10000,
|
||||
name: path.posix.join('static', '[name].[hash:7].[ext]')
|
||||
@@ -110,7 +168,6 @@ const webpackConfig = {
|
||||
]
|
||||
},
|
||||
plugins: [
|
||||
new webpack.HotModuleReplacementPlugin(),
|
||||
new HtmlWebpackPlugin({
|
||||
template: './examples/index.tpl',
|
||||
filename: './index.html',
|
||||
@@ -121,9 +178,6 @@ const webpackConfig = {
|
||||
]),
|
||||
new ProgressBarPlugin(),
|
||||
new VueLoaderPlugin(),
|
||||
new webpack.DefinePlugin({
|
||||
'process.env.FAAS_ENV': JSON.stringify(process.env.FAAS_ENV)
|
||||
}),
|
||||
new webpack.LoaderOptionsPlugin({
|
||||
vue: {
|
||||
compilerOptions: {
|
||||
@@ -131,43 +185,15 @@ const webpackConfig = {
|
||||
}
|
||||
}
|
||||
})
|
||||
],
|
||||
optimization: {
|
||||
minimizer: []
|
||||
},
|
||||
devtool: '#eval-source-map'
|
||||
]
|
||||
};
|
||||
|
||||
if (isProd) {
|
||||
webpackConfig.externals = {
|
||||
vue: 'Vue',
|
||||
'vue-router': 'VueRouter',
|
||||
'highlight.js': 'hljs'
|
||||
};
|
||||
webpackConfig.plugins.push(
|
||||
new MiniCssExtractPlugin({
|
||||
filename: '[name].[contenthash:7].css'
|
||||
})
|
||||
);
|
||||
webpackConfig.optimization.minimizer.push(
|
||||
new UglifyJsPlugin({
|
||||
cache: true,
|
||||
parallel: true,
|
||||
sourceMap: false
|
||||
}),
|
||||
new OptimizeCSSAssetsPlugin({})
|
||||
);
|
||||
// https://webpack.js.org/configuration/optimization/#optimizationsplitchunks
|
||||
webpackConfig.optimization.splitChunks = {
|
||||
cacheGroups: {
|
||||
vendor: {
|
||||
test: /\/src\//,
|
||||
name: 'element-ui',
|
||||
chunks: 'all'
|
||||
}
|
||||
}
|
||||
};
|
||||
webpackConfig.devtool = false;
|
||||
}
|
||||
|
||||
module.exports = webpackConfig;
|
||||
|
||||
@@ -1,33 +0,0 @@
|
||||
const path = require('path');
|
||||
const CopyWebpackPlugin = require('copy-webpack-plugin');
|
||||
const demoConfig = require('./webpack.demo');
|
||||
const webpack = require('webpack');
|
||||
const ProgressBarPlugin = require('progress-bar-webpack-plugin');
|
||||
const VueLoaderPlugin = require('vue-loader/lib/plugin');
|
||||
|
||||
demoConfig.entry = {
|
||||
background: path.join(process.cwd(), './examples/extension/src/background'),
|
||||
entry: path.join(process.cwd(), './examples/extension/src/entry')
|
||||
};
|
||||
demoConfig.output = {
|
||||
path: path.join(process.cwd(), './examples/extension/dist'),
|
||||
filename: '[name].js'
|
||||
};
|
||||
demoConfig.plugins = [
|
||||
new CopyWebpackPlugin([
|
||||
{ from: 'examples/extension/src/manifest.json' },
|
||||
{ from: 'examples/extension/src/icon.png' }
|
||||
]),
|
||||
new VueLoaderPlugin(),
|
||||
new ProgressBarPlugin(),
|
||||
new webpack.LoaderOptionsPlugin({
|
||||
vue: {
|
||||
compilerOptions: {
|
||||
preserveWhitespace: false
|
||||
}
|
||||
}
|
||||
}),
|
||||
new webpack.HotModuleReplacementPlugin()
|
||||
];
|
||||
demoConfig.module.rules.find(a => a.loader === 'url-loader').query = {};
|
||||
module.exports = demoConfig;
|
||||
@@ -22,6 +22,7 @@ const webpackConfig = {
|
||||
}),
|
||||
modules: ['node_modules']
|
||||
},
|
||||
devtool: '#inline-source-map',
|
||||
module: {
|
||||
rules: [
|
||||
{
|
||||
@@ -41,7 +42,7 @@ const webpackConfig = {
|
||||
},
|
||||
{
|
||||
test: /\.css$/,
|
||||
loaders: ['style-loader', 'css-loader']
|
||||
loaders: ['style-loader', 'css-loader', 'postcss-loader']
|
||||
},
|
||||
{
|
||||
test: /\.(svg|otf|ttf|woff2?|eot|gif|png|jpe?g)(\?\S*)?$/,
|
||||
|
||||
@@ -69,23 +69,5 @@
|
||||
"main": "./packages/main/index.js",
|
||||
"footer": "./packages/footer/index.js",
|
||||
"timeline": "./packages/timeline/index.js",
|
||||
"timeline-item": "./packages/timeline-item/index.js",
|
||||
"link": "./packages/link/index.js",
|
||||
"divider": "./packages/divider/index.js",
|
||||
"image": "./packages/image/index.js",
|
||||
"calendar": "./packages/calendar/index.js",
|
||||
"backtop": "./packages/backtop/index.js",
|
||||
"infinite-scroll": "./packages/infinite-scroll/index.js",
|
||||
"page-header": "./packages/page-header/index.js",
|
||||
"cascader-panel": "./packages/cascader-panel/index.js",
|
||||
"avatar": "./packages/avatar/index.js",
|
||||
"drawer": "./packages/drawer/index.js",
|
||||
"statistic": "./packages/statistic/index.js",
|
||||
"popconfirm": "./packages/popconfirm/index.js",
|
||||
"skeleton": "./packages/skeleton/index.js",
|
||||
"skeleton-item": "./packages/skeleton-item/index.js",
|
||||
"empty": "./packages/empty/index.js",
|
||||
"descriptions": "./packages/descriptions/index.js",
|
||||
"descriptions-item": "./packages/descriptions-item/index.js",
|
||||
"result": "./packages/result/index.js"
|
||||
"timeline-item": "./packages/timeline-item/index.js"
|
||||
}
|
||||
|
||||
@@ -13,7 +13,6 @@
|
||||
import zhLocale from 'main/locale/lang/zh-CN';
|
||||
import enLocale from 'main/locale/lang/en';
|
||||
import esLocale from 'main/locale/lang/es';
|
||||
import frLocale from 'main/locale/lang/fr';
|
||||
|
||||
const lang = location.hash.replace('#', '').split('/')[1] || 'zh-CN';
|
||||
const localize = lang => {
|
||||
@@ -24,9 +23,6 @@
|
||||
case 'es':
|
||||
use(esLocale);
|
||||
break;
|
||||
case 'fr-FR':
|
||||
use(frLocale);
|
||||
break;
|
||||
default:
|
||||
use(enLocale);
|
||||
}
|
||||
@@ -60,13 +56,14 @@
|
||||
|
||||
const href = location.href;
|
||||
const preferGithub = localStorage.getItem('PREFER_GITHUB');
|
||||
const cnHref = href.indexOf('eleme.cn') > -1 || href.indexOf('element-cn') > -1 || href.indexOf('element.faas') > -1;
|
||||
if (cnHref || preferGithub) return;
|
||||
if (href.indexOf('element-cn') > -1 || href.indexOf('element.faas') > -1 || preferGithub) return;
|
||||
setTimeout(() => {
|
||||
if (this.lang !== 'zh-CN') return;
|
||||
this.$confirm('建议大陆用户访问部署在国内的站点,是否跳转?', '提示')
|
||||
.then(() => {
|
||||
location.replace('https://element.eleme.cn');
|
||||
location.href = location.href
|
||||
.replace('https:', 'http:')
|
||||
.replace('element.', 'element-cn.');
|
||||
})
|
||||
.catch(() => {
|
||||
localStorage.setItem('PREFER_GITHUB', 'true');
|
||||
@@ -83,3 +80,9 @@
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style>
|
||||
@import 'highlight.js/styles/color-brewer.css';
|
||||
@import 'assets/styles/common.css';
|
||||
@import 'assets/styles/fonts/style.css';
|
||||
</style>
|
||||
|
||||
24
examples/assets/images/duohui.svg
Normal file
@@ -0,0 +1,24 @@
|
||||
<svg width="98" height="150" viewBox="0 0 98 150" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||
<title>duohui-element</title>
|
||||
<desc>Created using Figma</desc>
|
||||
<g id="Canvas" transform="translate(-2216 140)">
|
||||
<clipPath id="clip-0" clip-rule="evenodd">
|
||||
<path d="M 2216 -140L 2314 -140L 2314 10L 2216 10L 2216 -140Z" fill="#FFFFFF"/>
|
||||
</clipPath>
|
||||
<g id="duohui-element" clip-path="url(#clip-0)">
|
||||
<path d="M 2216 -140L 2314 -140L 2314 10L 2216 10L 2216 -140Z" fill="#FFFFFF"/>
|
||||
<g id="Duohui Icon 2">
|
||||
<g id="Vector">
|
||||
<use xlink:href="#path0_fill" transform="matrix(1.26636 0 0 1.21929 2230 -75.7038)" fill="#3A88FD"/>
|
||||
</g>
|
||||
<g id="Vector">
|
||||
<use xlink:href="#path1_fill" transform="matrix(1.41534 0 0 1.21834 2226 -112)" fill="#35AFFB"/>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
<defs>
|
||||
<path id="path0_fill" fill-rule="evenodd" d="M 25.7722 1.00635C 26.2 0.374983 26.8949 -2.6613e-07 27.6349 -2.6613e-07C 28.3755 -2.6613e-07 29.0699 0.374983 29.4983 1.00635C 34.409 8.24964 47.798 27.9964 54.5986 38.0262C 55.3878 39.1901 55.4896 40.7162 54.8623 41.983C 54.235 43.2498 52.9833 44.0452 51.6178 44.0452C 39.6694 44.0452 15.601 44.0452 3.6521 44.0452C 2.28712 44.0452 1.03545 43.2498 0.408173 41.983C -0.219106 40.7162 -0.117353 39.1901 0.671804 38.0262C 7.47242 27.9964 20.8609 8.24964 25.7722 1.00635Z"/>
|
||||
<path id="path1_fill" fill-rule="evenodd" d="M 24.9939 1.44703C 25.6137 0.533117 26.5572 -3.01614e-07 27.5551 -3.01614e-07C 28.5535 -3.01614e-07 29.497 0.533117 30.1168 1.44703C 35.4674 9.33854 47.8725 27.6342 54.4043 37.2681C 55.1825 38.4157 55.3299 39.982 54.7847 41.2999C 54.2389 42.6185 53.096 43.4556 51.8426 43.4556C 39.9023 43.4556 15.2084 43.4556 3.26811 43.4556C 2.01471 43.4556 0.871739 42.6185 0.325978 41.2999C -0.219783 39.982 -0.0717813 38.4157 0.70639 37.2681C 7.23818 27.6342 19.6433 9.33854 24.9939 1.44703Z"/>
|
||||
</defs>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.8 KiB |
16
examples/assets/images/duotai.svg
Normal file
@@ -0,0 +1,16 @@
|
||||
<svg width="63" height="59" viewBox="0 0 63 59" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||
<g id="Canvas" fill="none">
|
||||
<g id="duotai-icon">
|
||||
<g id="Rectangle">
|
||||
<rect width="41.1402" height="42.1429" transform="translate(21.5987 16.8571)" fill="#FF7262"/>
|
||||
</g>
|
||||
<g id="Vector 2">
|
||||
<path d="M 0 25.2857L 21.5986 0L 43.1972 25.2857L 0 25.2857Z" transform="translate(0 33.7142)" fill="#0ACF83"/>
|
||||
</g>
|
||||
<g id="Ellipse">
|
||||
<ellipse cx="16.4561" cy="16.8572" rx="16.4561" ry="16.8572" transform="translate(5.14249 0)" fill="#1ABCFE"/>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
||||
|
After Width: | Height: | Size: 595 B |
|
Before Width: | Height: | Size: 5.4 KiB |
|
Before Width: | Height: | Size: 4.2 KiB |
|
Before Width: | Height: | Size: 4.6 KiB |
|
Before Width: | Height: | Size: 4.7 KiB |
@@ -1,19 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg width="13px" height="12px" viewBox="0 0 13 12" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||
<!-- Generator: Sketch 54.1 (76490) - https://sketchapp.com -->
|
||||
<title>icon-redo</title>
|
||||
<desc>Created with Sketch.</desc>
|
||||
<g id="theme" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
|
||||
<g id="element-theme-editor" transform="translate(-1118.000000, -167.000000)" fill="#606266" fill-rule="nonzero">
|
||||
<g id="custom" transform="translate(1060.000000, 146.000000)">
|
||||
<g id="Group-2" transform="translate(30.000000, 15.000000)">
|
||||
<g id="Group" transform="translate(0.000000, 4.000000)">
|
||||
<g id="icon-clockwise" transform="translate(26.000000, 0.000000)">
|
||||
<path d="M12.2585,3.59833136 L12.2585,2.3085 L13.2585,2.3085 L13.2585,5.6365 L9.9295,5.6365 L9.9295,4.6365 L11.8833737,4.6365 C10.9510824,3.62012881 9.6272717,3.0179 8.2,3.0179 C5.43814237,3.0179 3.2,5.25604237 3.2,8.0179 C3.2,10.7797576 5.43814237,13.0179 8.2,13.0179 C10.9618576,13.0179 13.2,10.7797576 13.2,8.0179 L14.2,8.0179 C14.2,11.3320424 11.5141424,14.0179 8.2,14.0179 C4.88585763,14.0179 2.2,11.3320424 2.2,8.0179 C2.2,4.70375763 4.88585763,2.0179 8.2,2.0179 C9.73531163,2.0179 11.1716793,2.59926473 12.2585,3.59833136 Z" id="icon-redo"></path>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 1.5 KiB |
@@ -1,19 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg width="13px" height="12px" viewBox="0 0 13 12" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||
<!-- Generator: Sketch 54.1 (76490) - https://sketchapp.com -->
|
||||
<title>icon-undo</title>
|
||||
<desc>Created with Sketch.</desc>
|
||||
<g id="theme" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
|
||||
<g id="element-theme-editor" transform="translate(-1092.000000, -167.000000)" fill="#606266" fill-rule="nonzero">
|
||||
<g id="custom" transform="translate(1060.000000, 146.000000)">
|
||||
<g id="Group-2" transform="translate(30.000000, 15.000000)">
|
||||
<g id="Group" transform="translate(0.000000, 4.000000)">
|
||||
<g id="icon-clockwise">
|
||||
<path d="M12.2585,3.59833136 L12.2585,2.3085 L13.2585,2.3085 L13.2585,5.6365 L9.9295,5.6365 L9.9295,4.6365 L11.8833737,4.6365 C10.9510824,3.62012881 9.6272717,3.0179 8.2,3.0179 C5.43814237,3.0179 3.2,5.25604237 3.2,8.0179 C3.2,10.7797576 5.43814237,13.0179 8.2,13.0179 C10.9618576,13.0179 13.2,10.7797576 13.2,8.0179 L14.2,8.0179 C14.2,11.3320424 11.5141424,14.0179 8.2,14.0179 C4.88585763,14.0179 2.2,11.3320424 2.2,8.0179 C2.2,4.70375763 4.88585763,2.0179 8.2,2.0179 C9.73531163,2.0179 11.1716793,2.59926473 12.2585,3.59833136 Z" id="icon-undo" transform="translate(8.200000, 8.017900) scale(-1, 1) translate(-8.200000, -8.017900) "></path>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 1.6 KiB |
@@ -1,19 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg width="26px" height="26px" viewBox="0 0 26 26" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||
<!-- Generator: Sketch 54.1 (76490) - https://sketchapp.com -->
|
||||
<title>icon_upload</title>
|
||||
<desc>Created with Sketch.</desc>
|
||||
<g id="theme" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
|
||||
<g id="element-theme" transform="translate(-207.000000, -662.000000)" fill="#909399">
|
||||
<g id="section" transform="translate(70.000000, 511.000000)">
|
||||
<g id="card" transform="translate(0.000000, 60.000000)">
|
||||
<g id="btn" transform="translate(108.000000, 91.000000)">
|
||||
<g id="icon-upload" transform="translate(29.000000, 0.000000)">
|
||||
<path d="M13,-0.000600000001 L3.015,9.9854 L4.429,11.3984 L12,3.8284 L12,20.4854 L14.001,20.4854 L14.001,3.8284 L21.572,11.3984 L22.986,9.9854 L14.415,1.4144 L13,-0.000600000001 Z M13,2.8284 L13.158,2.9844 L12.843,2.9844 L13,2.8284 Z M24.001,19.9854 L24.001,23.9854 L2,23.9854 L2,19.9854 L0,19.9854 L0,25.9854 L26.001,25.9854 L26.001,19.9854 L24.001,19.9854 Z" id="icon_upload"></path>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 1.3 KiB |
|
Before Width: | Height: | Size: 34 KiB |
|
Before Width: | Height: | Size: 48 KiB |
|
Before Width: | Height: | Size: 50 KiB |
|
Before Width: | Height: | Size: 61 KiB |
|
Before Width: | Height: | Size: 61 KiB |
|
Before Width: | Height: | Size: 56 KiB |
|
Before Width: | Height: | Size: 53 KiB |
|
Before Width: | Height: | Size: 59 KiB |
@@ -1 +0,0 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 320 240"><defs><style>.cls-1{fill:none;}.cls-2{fill:#eff5fd;}.cls-3{fill:#fff;}.cls-4{fill:#26a1ff;}.cls-5{fill:snow;}.cls-6{fill:#fdaca9;}.cls-7{fill:#fd9da0;}.cls-8{fill:#fed5d0;}.cls-9{fill:#ffe8e6;}</style></defs><title>资源 104</title><g id="图层_2" data-name="图层 2"><g id="图层_1-2" data-name="图层 1"><rect class="cls-1" width="320" height="240"/><circle class="cls-2" cx="160" cy="120" r="120"/><path class="cls-3" d="M160,55H105.64A20.64,20.64,0,0,0,85,75.64V200a5,5,0,0,0,5,5h70Z"/><rect class="cls-4" x="95" y="145" width="130" height="40" rx="5"/><path class="cls-5" d="M230,55H160V205h70a5,5,0,0,0,5-5V60A5,5,0,0,0,230,55Z"/><path class="cls-6" d="M220,145H160v40h60a5,5,0,0,0,5-5V150A5,5,0,0,0,220,145Z"/><path class="cls-6" d="M160,99.78a2.5,2.5,0,0,1,0-5c48.71,0,62.17-28.57,62.72-29.79a2.5,2.5,0,1,1,4.56,2C226.69,68.36,212.13,99.78,160,99.78Z"/><path class="cls-2" d="M124.26,171.58V154.4h6.44a7.91,7.91,0,0,1,3.16.52,4,4,0,0,1,1.86,1.6,4.26,4.26,0,0,1,.68,2.27,3.89,3.89,0,0,1-.6,2.08,4.36,4.36,0,0,1-1.8,1.57,4.45,4.45,0,0,1,2.39,1.56,4.15,4.15,0,0,1,.84,2.6,5,5,0,0,1-.51,2.24,4.32,4.32,0,0,1-1.26,1.6,5.18,5.18,0,0,1-1.88.85,11.48,11.48,0,0,1-2.77.29Zm2.27-10h3.72a8.34,8.34,0,0,0,2.16-.2,2.39,2.39,0,0,0,1.31-.86,2.49,2.49,0,0,0,.44-1.5,2.76,2.76,0,0,0-.41-1.5,2,2,0,0,0-1.17-.89,9.84,9.84,0,0,0-2.62-.24h-3.43Zm0,7.93h4.28a10.68,10.68,0,0,0,1.55-.08,3.81,3.81,0,0,0,1.31-.47,2.44,2.44,0,0,0,.86-1,2.92,2.92,0,0,0,.34-1.44,2.84,2.84,0,0,0-.49-1.67,2.56,2.56,0,0,0-1.36-1,8.51,8.51,0,0,0-2.52-.29h-4Z"/><path class="cls-2" d="M148.25,171.58v-1.83a4.55,4.55,0,0,1-3.95,2.11,5.06,5.06,0,0,1-2.06-.42,3.42,3.42,0,0,1-1.42-1.06,4.06,4.06,0,0,1-.65-1.57,11.22,11.22,0,0,1-.13-2v-7.71h2.11V166a11.86,11.86,0,0,0,.13,2.23,2.18,2.18,0,0,0,.84,1.31,2.68,2.68,0,0,0,1.6.47,3.52,3.52,0,0,0,1.78-.48,2.76,2.76,0,0,0,1.18-1.33,6.68,6.68,0,0,0,.34-2.43v-6.67h2.11v12.45Z"/><path class="cls-2" d="M158,169.69l.31,1.86a7.59,7.59,0,0,1-1.6.19,3.64,3.64,0,0,1-1.78-.36,2,2,0,0,1-.89-1,7.55,7.55,0,0,1-.26-2.49v-7.16h-1.54v-1.64h1.54v-3.08l2.1-1.27v4.35H158v1.64h-2.12v7.28a3.83,3.83,0,0,0,.11,1.16.92.92,0,0,0,.37.41,1.38,1.38,0,0,0,.72.15A6,6,0,0,0,158,169.69Z"/><path class="cls-5" d="M167.69,169.69l.3,1.86a7.43,7.43,0,0,1-1.59.19,3.61,3.61,0,0,1-1.78-.36,2,2,0,0,1-.89-1,7.28,7.28,0,0,1-.26-2.49v-7.16h-1.55v-1.64h1.55v-3.08l2.1-1.27v4.35h2.12v1.64h-2.12v7.28a3.51,3.51,0,0,0,.11,1.16.84.84,0,0,0,.36.41,1.43,1.43,0,0,0,.72.15A6.1,6.1,0,0,0,167.69,169.69Z"/><path class="cls-5" d="M169,165.35a6.43,6.43,0,0,1,1.93-5.12,5.79,5.79,0,0,1,3.91-1.38,5.6,5.6,0,0,1,4.2,1.68,6.42,6.42,0,0,1,1.62,4.65,8.25,8.25,0,0,1-.72,3.78,5.13,5.13,0,0,1-2.09,2.14,6.2,6.2,0,0,1-3,.76,5.57,5.57,0,0,1-4.22-1.68A6.65,6.65,0,0,1,169,165.35Zm2.17,0a5.26,5.26,0,0,0,1.05,3.58,3.47,3.47,0,0,0,5.23,0,5.41,5.41,0,0,0,1.05-3.65,5.13,5.13,0,0,0-1.05-3.49,3.48,3.48,0,0,0-5.23,0A5.25,5.25,0,0,0,171.13,165.35Z"/><path class="cls-5" d="M183.1,171.58V159.13H185v1.77a4.46,4.46,0,0,1,4-2.05,5.2,5.2,0,0,1,2.07.41,3.25,3.25,0,0,1,1.41,1.06,4,4,0,0,1,.65,1.55,11.89,11.89,0,0,1,.12,2.06v7.65H191.1V164a5.85,5.85,0,0,0-.24-1.93,2,2,0,0,0-.88-1,2.82,2.82,0,0,0-1.47-.38,3.39,3.39,0,0,0-2.32.85c-.66.57-1,1.66-1,3.25v6.8Z"/><circle class="cls-4" cx="71.9" cy="76.81" r="30"/><path class="cls-3" d="M62.69,68.35h4.89v2.5H59.25V62.53h2.5v3.23a15,15,0,0,1,25.15,11H84.4A12.5,12.5,0,0,0,63.06,68C62.93,68.09,62.81,68.22,62.69,68.35Zm19.36,19.5a15,15,0,0,1-25.15-11h2.5a12.51,12.51,0,0,0,21.34,8.85l.37-.39H76.22v-2.5h8.33v8.32h-2.5Z"/><path class="cls-7" d="M46.94,47.79a2.92,2.92,0,0,1-2.25-1l-7-8.38a2.93,2.93,0,1,1,4.48-3.77L49.17,43a2.92,2.92,0,0,1-.35,4.12A2.88,2.88,0,0,1,46.94,47.79Z"/><path class="cls-8" d="M37.06,59.93h-.25L25.89,59a2.93,2.93,0,0,1,.51-5.83l10.91,1a2.93,2.93,0,0,1-.25,5.84Z"/><path class="cls-8" d="M60.58,40.14l-.25,0A2.93,2.93,0,0,1,57.66,37l.94-10.91a2.93,2.93,0,1,1,5.83.5l-.94,10.91A2.93,2.93,0,0,1,60.58,40.14Z"/><rect class="cls-2" x="99" y="128.31" width="15" height="6.27"/><rect class="cls-2" x="123.56" y="112.59" width="15" height="22"/><rect class="cls-9" x="160" y="106.81" width="7.5" height="27.78"/><rect class="cls-2" x="152.5" y="106.81" width="7.5" height="27.78"/><rect class="cls-9" x="206" y="91.81" width="15" height="42.78"/><rect class="cls-9" x="179.25" y="103.64" width="15" height="30.94"/><path class="cls-4" d="M95,130.81a2.62,2.62,0,0,1-1-.21,2.5,2.5,0,0,1-1.26-3.31C93.31,126,107.88,94.78,160,94.78a2.5,2.5,0,0,1,0,5c-48.91,0-62.59,29.26-62.72,29.56A2.5,2.5,0,0,1,95,130.81Z"/><path class="cls-6" d="M226,63.73a2.5,2.5,0,0,0-3.3,1.26c-.55,1.22-14,29.79-62.72,29.79h0v5h0c52.13,0,66.69-31.42,67.28-32.75A2.5,2.5,0,0,0,226,63.73Z"/></g></g></svg>
|
||||
|
Before Width: | Height: | Size: 4.6 KiB |
|
Before Width: | Height: | Size: 58 KiB |
|
Before Width: | Height: | Size: 55 KiB |
175
examples/assets/images/tipe.svg
Normal file
@@ -0,0 +1,175 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 148.32 226.69">
|
||||
<defs>
|
||||
<style>
|
||||
.cls-1 {
|
||||
isolation: isolate;
|
||||
}
|
||||
|
||||
.cls-2 {
|
||||
fill: url(#radial-gradient);
|
||||
}
|
||||
|
||||
.cls-3 {
|
||||
fill: url(#linear-gradient);
|
||||
}
|
||||
|
||||
.cls-4 {
|
||||
fill: url(#linear-gradient-2);
|
||||
}
|
||||
|
||||
.cls-5 {
|
||||
fill: url(#linear-gradient-3);
|
||||
}
|
||||
|
||||
.cls-6 {
|
||||
fill: url(#linear-gradient-4);
|
||||
}
|
||||
|
||||
.cls-7 {
|
||||
fill: url(#linear-gradient-5);
|
||||
}
|
||||
|
||||
.cls-8 {
|
||||
fill: url(#linear-gradient-6);
|
||||
}
|
||||
|
||||
.cls-9 {
|
||||
opacity: 0.7;
|
||||
}
|
||||
|
||||
.cls-11, .cls-9 {
|
||||
mix-blend-mode: multiply;
|
||||
}
|
||||
|
||||
.cls-10 {
|
||||
fill: url(#linear-gradient-7);
|
||||
}
|
||||
|
||||
.cls-12 {
|
||||
fill: url(#linear-gradient-8);
|
||||
}
|
||||
|
||||
.cls-13 {
|
||||
fill: url(#linear-gradient-9);
|
||||
}
|
||||
|
||||
.cls-14 {
|
||||
fill: #3c2e36;
|
||||
}
|
||||
|
||||
.cls-15 {
|
||||
fill: url(#linear-gradient-10);
|
||||
}
|
||||
|
||||
.cls-16 {
|
||||
fill: url(#radial-gradient-2);
|
||||
}
|
||||
</style>
|
||||
<radialGradient id="radial-gradient" cx="74.93" cy="117.87" r="86.39" gradientTransform="translate(0 22.72) scale(1 1.07)" gradientUnits="userSpaceOnUse">
|
||||
<stop offset="0.32" stop-color="#e4dce1"/>
|
||||
<stop offset="0.48" stop-color="#e1dadf"/>
|
||||
<stop offset="0.59" stop-color="#d9d3da"/>
|
||||
<stop offset="0.68" stop-color="#cac7d2"/>
|
||||
<stop offset="0.76" stop-color="#b5b6c6"/>
|
||||
<stop offset="0.79" stop-color="#aaadc0"/>
|
||||
<stop offset="1" stop-color="#6f6f85"/>
|
||||
</radialGradient>
|
||||
<linearGradient id="linear-gradient" x1="38.85" y1="122.53" x2="108.18" y2="108.38" gradientUnits="userSpaceOnUse">
|
||||
<stop offset="0" stop-color="#e4dce1"/>
|
||||
<stop offset="0.19" stop-color="#d7d0d7"/>
|
||||
<stop offset="0.53" stop-color="#b5b2be"/>
|
||||
<stop offset="0.97" stop-color="#808296"/>
|
||||
</linearGradient>
|
||||
<linearGradient id="linear-gradient-2" x1="32.25" y1="64.7" x2="148.44" y2="64.7" gradientUnits="userSpaceOnUse">
|
||||
<stop offset="0.32" stop-color="#e4dce1"/>
|
||||
<stop offset="0.49" stop-color="#e1dadf"/>
|
||||
<stop offset="0.6" stop-color="#d9d3da"/>
|
||||
<stop offset="0.69" stop-color="#cac7d2"/>
|
||||
<stop offset="0.78" stop-color="#b5b6c6"/>
|
||||
<stop offset="0.81" stop-color="#aaadc0"/>
|
||||
<stop offset="1" stop-color="#6f6f85"/>
|
||||
</linearGradient>
|
||||
<linearGradient id="linear-gradient-3" x1="139.11" y1="68.34" x2="139.11" y2="1.17" gradientUnits="userSpaceOnUse">
|
||||
<stop offset="0.12" stop-color="#888aa0"/>
|
||||
<stop offset="0.54" stop-color="#716f8a"/>
|
||||
<stop offset="0.89" stop-color="#635d7c"/>
|
||||
</linearGradient>
|
||||
<linearGradient id="linear-gradient-4" x1="111.94" y1="16.05" x2="135.36" y2="16.05" gradientUnits="userSpaceOnUse">
|
||||
<stop offset="0" stop-color="#3c314b"/>
|
||||
<stop offset="0.54" stop-color="#534a67"/>
|
||||
<stop offset="0.89" stop-color="#635d7c"/>
|
||||
</linearGradient>
|
||||
<linearGradient id="linear-gradient-5" x1="6752.04" y1="68.34" x2="6752.04" y2="-3.45" gradientTransform="matrix(-1, 0, 0, 1, 6787.68, 0)" gradientUnits="userSpaceOnUse">
|
||||
<stop offset="0.19" stop-color="#e4dce1"/>
|
||||
<stop offset="0.42" stop-color="#c2bac6"/>
|
||||
<stop offset="0.92" stop-color="#6b6582"/>
|
||||
<stop offset="0.97" stop-color="#635d7c"/>
|
||||
</linearGradient>
|
||||
<linearGradient id="linear-gradient-6" x1="39.39" y1="16.05" x2="62.82" y2="16.05" gradientUnits="userSpaceOnUse">
|
||||
<stop offset="0" stop-color="#3c314b"/>
|
||||
<stop offset="0.02" stop-color="#3d324c"/>
|
||||
<stop offset="0.35" stop-color="#524a66"/>
|
||||
<stop offset="0.65" stop-color="#5f5876"/>
|
||||
<stop offset="0.89" stop-color="#635d7c"/>
|
||||
</linearGradient>
|
||||
<linearGradient id="linear-gradient-7" x1="79.66" y1="229.05" x2="79.66" y2="194.82" gradientUnits="userSpaceOnUse">
|
||||
<stop offset="0.03" stop-color="#808296"/>
|
||||
<stop offset="0.31" stop-color="#b7b8c3" stop-opacity="0.78"/>
|
||||
<stop offset="0.79" stop-color="#fff" stop-opacity="0.5"/>
|
||||
</linearGradient>
|
||||
<linearGradient id="linear-gradient-8" x1="87.38" y1="117.84" x2="87.38" y2="41.77" gradientUnits="userSpaceOnUse">
|
||||
<stop offset="0" stop-color="#e3dddf" stop-opacity="0"/>
|
||||
<stop offset="0.04" stop-color="#cbc5cd" stop-opacity="0.12"/>
|
||||
<stop offset="0.15" stop-color="#9d97a9" stop-opacity="0.37"/>
|
||||
<stop offset="0.25" stop-color="#7b758f" stop-opacity="0.54"/>
|
||||
<stop offset="0.35" stop-color="#67617f" stop-opacity="0.65"/>
|
||||
<stop offset="0.45" stop-color="#605a7a" stop-opacity="0.68"/>
|
||||
<stop offset="0.54" stop-color="#575070" stop-opacity="0.75"/>
|
||||
<stop offset="1" stop-color="#382e4a"/>
|
||||
</linearGradient>
|
||||
<linearGradient id="linear-gradient-9" x1="11357.22" y1="78.8" x2="11361.46" y2="58.49" gradientTransform="matrix(-1, 0, 0, 1, 11419.34, 0)" gradientUnits="userSpaceOnUse">
|
||||
<stop offset="0.07" stop-color="#28ffff"/>
|
||||
<stop offset="0.41" stop-color="#51d2ff"/>
|
||||
<stop offset="0.8" stop-color="#7ba3ff"/>
|
||||
<stop offset="1" stop-color="#8b91ff"/>
|
||||
</linearGradient>
|
||||
<linearGradient id="linear-gradient-10" x1="113" y1="78.8" x2="117.24" y2="58.49" gradientTransform="matrix(1, 0, 0, 1, 0, 0)" xlink:href="#linear-gradient-9"/>
|
||||
<radialGradient id="radial-gradient-2" cx="36.09" cy="124.71" r="36.13" gradientUnits="userSpaceOnUse">
|
||||
<stop offset="0.11" stop-color="#635d7c"/>
|
||||
<stop offset="0.35" stop-color="#5f5876"/>
|
||||
<stop offset="0.65" stop-color="#524a66"/>
|
||||
<stop offset="0.98" stop-color="#3d324c"/>
|
||||
<stop offset="1" stop-color="#3c314b"/>
|
||||
</radialGradient>
|
||||
</defs>
|
||||
<title>Asset 3</title>
|
||||
<g class="cls-1">
|
||||
<g id="Layer_2" data-name="Layer 2">
|
||||
<g id="Layer_1-2" data-name="Layer 1">
|
||||
<g>
|
||||
<path class="cls-2" d="M138.13,128.27c-4.7-9.78-11.29-21.28-9.75-33.55a15.83,15.83,0,0,1,3.26-8.26A65.12,65.12,0,0,1,114.75,99a64.1,64.1,0,0,1-6.11,2.76,66.61,66.61,0,0,0-14.35,9.42c-13.43,11.7-26.21,44.39-48.51,50.6h0a23.9,23.9,0,0,1-9.81,2c-9.41-.07-20.4-6.21-26.26-15.43C1,134.68,3.58,115.85,9.49,103.81c-.18.37-.37.74-.55,1.13a102.51,102.51,0,0,0-4.2,10.42v0A86.37,86.37,0,0,0,0,143.69c0,45.84,35.49,83,79.27,83,11.19,0,29-3.38,43.66-13.61a57.75,57.75,0,0,0,22.57-32C151.54,158.58,144.94,142.45,138.13,128.27Z"/>
|
||||
<path class="cls-3" d="M51.46,158.37a27,27,0,0,1-5.67,3.38h0c22.3-6.21,35.07-38.9,48.51-50.6a66.61,66.61,0,0,1,14.35-9.42,58.67,58.67,0,0,1-21.26,4.09c-19.75,0-37.75-10.49-48.31-24,1,1.39,13,15.46,22.29,43.72A30,30,0,0,1,51.46,158.37Z"/>
|
||||
<path class="cls-4" d="M145.33,59.56c-2.08,22.29-28.26,46.26-58,46.26-29.95,0-55.88-24.12-58-46.26-1.45-15.6,7.34-36,58-36S146.78,44,145.33,59.56Z"/>
|
||||
<path class="cls-5" d="M135.36,0h0a51.59,51.59,0,0,0-4.68,32.1A37.21,37.21,0,0,1,134,34.24c10,7.23,12.12,17,11.34,25.32a35.2,35.2,0,0,1-1.6,7.61A73.45,73.45,0,0,0,142.08,12,71.18,71.18,0,0,0,135.36,0Z"/>
|
||||
<path class="cls-6" d="M130.68,32.1A51.59,51.59,0,0,1,135.36,0h0a57.92,57.92,0,0,0-9.41,6.87,59.8,59.8,0,0,0-14,18.75q3.35.64,6.29,1.45A53.09,53.09,0,0,1,130.68,32.1Z"/>
|
||||
<path class="cls-7" d="M39.39,0h0a51.59,51.59,0,0,1,4.68,32.1,37.21,37.21,0,0,0-3.31,2.14c-10,7.23-12.12,17-11.34,25.32A35.2,35.2,0,0,0,31,67.17,73.45,73.45,0,0,1,32.67,12,71.18,71.18,0,0,1,39.39,0Z"/>
|
||||
<path class="cls-8" d="M48.81,6.87A57.92,57.92,0,0,0,39.39,0h0a51.59,51.59,0,0,1,4.68,32.1,53.09,53.09,0,0,1,12.45-5q2.94-.82,6.29-1.45A59.8,59.8,0,0,0,48.81,6.87Z"/>
|
||||
<g class="cls-9">
|
||||
<path class="cls-10" d="M84.24,182.6c-26.08,0-49.56,5.42-66,14.08,14.54,18.33,36.47,30,61,30,11.19,0,29-3.38,43.66-13.61A58.81,58.81,0,0,0,141,192.47C125.56,186.3,105.79,182.6,84.24,182.6Z"/>
|
||||
</g>
|
||||
<g>
|
||||
<g class="cls-11">
|
||||
<path class="cls-12" d="M138.51,52.94c-.56-2.94-2-5.19-5-5.88-7.88-1.85-27,9.84-37.8,15.34-4,2.06-6.16,3.05-8.34,3s-4.31-.94-8.34-3c-10.77-5.5-29.92-17.18-37.8-15.34-3,.7-4.44,2.94-5,5.88-1,5.16.35,18,9.89,27.49,7.14,7.11,16.68,10.46,24.69,12.71l.18.08a4.2,4.2,0,0,0-.09.88c0,3.28,3.83,5.94,8.56,5.94,2.34,0,6.35-.65,7.9-1.71h0c1.55,1.06,5.56,1.71,7.9,1.71,4.73,0,8.56-2.66,8.56-5.94a4.2,4.2,0,0,0-.09-.88l.18-.08c8-2.25,17.56-5.6,24.69-12.71C138.16,70.92,139.49,58.1,138.51,52.94Z"/>
|
||||
</g>
|
||||
<path class="cls-13" d="M75.26,75.35C64.56,86.85,47.81,77.09,45,63.28c-1.83-9.07,3.63-7.73,8.71-5.67C60.14,60.2,68.84,66.27,75.26,75.35Z"/>
|
||||
<path class="cls-14" d="M60.43,68.26a15.16,15.16,0,0,1-2.19,8,15.56,15.56,0,0,1,0-15.92A15.16,15.16,0,0,1,60.43,68.26Z"/>
|
||||
<path d="M87.36,86.64a8.15,8.15,0,0,0-6.27,2.49c8.25,5.17,4.31,5.17,12.55,0A8.15,8.15,0,0,0,87.36,86.64Z"/>
|
||||
<path class="cls-15" d="M99.86,75.35c10.69,11.5,27.45,1.74,30.23-12.07,1.83-9.07-3.63-7.73-8.71-5.67C115,60.2,106.28,66.27,99.86,75.35Z"/>
|
||||
<path class="cls-14" d="M114.69,68.26a15.16,15.16,0,0,0,2.19,8,15.56,15.56,0,0,0,0-15.92A15.16,15.16,0,0,0,114.69,68.26Z"/>
|
||||
</g>
|
||||
<path class="cls-16" d="M9.71,148.35c5.86,9.22,16.85,15.37,26.26,15.43a23.7,23.7,0,0,0,8.21-1.41l0,0c-15,4.18-19.32-25.16-10.92-43.06v0c1.09-3.38,2.35-6.34,3.42-8.83.37-.86,2.53-5.15,2.09-9.8-.84-9-14-17.33-24-5.37A44.52,44.52,0,0,0,9.39,104C3.55,116.06,1.08,134.76,9.71,148.35Z"/>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 9.2 KiB |
|
Before Width: | Height: | Size: 7.7 KiB |
3108
examples/assets/restaurants.json
Normal file
@@ -5,7 +5,6 @@ html, body {
|
||||
font-family: 'Helvetica Neue',Helvetica,'PingFang SC','Hiragino Sans GB','Microsoft YaHei',SimSun,sans-serif;
|
||||
font-weight: 400;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
-webkit-tap-highlight-color: transparent;
|
||||
|
||||
&.is-component {
|
||||
overflow: hidden;
|
||||
@@ -15,7 +14,7 @@ html, body {
|
||||
#app {
|
||||
height: 100%;
|
||||
|
||||
&.is-component {
|
||||
@when component {
|
||||
overflow-y: hidden;
|
||||
|
||||
.main-cnt {
|
||||
|
||||
@@ -1,18 +0,0 @@
|
||||
export const tintColor = (c, tint) => {
|
||||
const color = c.replace('#', '');
|
||||
let red = parseInt(color.slice(0, 2), 16);
|
||||
let green = parseInt(color.slice(2, 4), 16);
|
||||
let blue = parseInt(color.slice(4, 6), 16);
|
||||
|
||||
if (tint === 0) { // when primary color is in its rgb space
|
||||
return [red, green, blue].join(',');
|
||||
} else {
|
||||
red += Math.round(tint * (255 - red));
|
||||
green += Math.round(tint * (255 - green));
|
||||
blue += Math.round(tint * (255 - blue));
|
||||
red = red.toString(16);
|
||||
green = green.toString(16);
|
||||
blue = blue.toString(16);
|
||||
return `#${ red }${ green }${ blue }`;
|
||||
}
|
||||
};
|
||||
@@ -4,16 +4,12 @@
|
||||
:class="[blockClass, { 'hover': hovering }]"
|
||||
@mouseenter="hovering = true"
|
||||
@mouseleave="hovering = false">
|
||||
<div class="source">
|
||||
<slot name="source"></slot>
|
||||
</div>
|
||||
<slot name="source"></slot>
|
||||
<div class="meta" ref="meta">
|
||||
<div class="description" v-if="$slots.default">
|
||||
<slot></slot>
|
||||
</div>
|
||||
<div class="highlight">
|
||||
<slot name="highlight"></slot>
|
||||
</div>
|
||||
<slot name="highlight"></slot>
|
||||
</div>
|
||||
<div
|
||||
class="demo-block-control"
|
||||
@@ -33,7 +29,7 @@
|
||||
size="small"
|
||||
type="text"
|
||||
class="control-button"
|
||||
@click.stop="goCodepen">
|
||||
@click.stop="goJsfiddle">
|
||||
{{ langConfig['button-text'] }}
|
||||
</el-button>
|
||||
</transition>
|
||||
@@ -42,7 +38,7 @@
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style lang="scss">
|
||||
<style>
|
||||
.demo-block {
|
||||
border: solid 1px #ebebeb;
|
||||
border-radius: 3px;
|
||||
@@ -183,17 +179,11 @@
|
||||
<script type="text/babel">
|
||||
import compoLang from '../i18n/component.json';
|
||||
import Element from 'main/index.js';
|
||||
import { stripScript, stripStyle, stripTemplate } from '../util';
|
||||
const { version } = Element;
|
||||
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
codepen: {
|
||||
script: '',
|
||||
html: '',
|
||||
style: ''
|
||||
},
|
||||
hovering: false,
|
||||
isExpanded: false,
|
||||
fixedControl: false,
|
||||
@@ -201,11 +191,17 @@
|
||||
};
|
||||
},
|
||||
|
||||
props: {
|
||||
jsfiddle: Object,
|
||||
default() {
|
||||
return {};
|
||||
}
|
||||
},
|
||||
|
||||
methods: {
|
||||
goCodepen() {
|
||||
// since 2.6.2 use code rather than jsfiddle https://blog.codepen.io/documentation/api/prefill/
|
||||
const { script, html, style } = this.codepen;
|
||||
const resourcesTpl = '<scr' + 'ipt src="//unpkg.com/vue@2/dist/vue.js"></scr' + 'ipt>' +
|
||||
goJsfiddle() {
|
||||
const { script, html, style } = this.jsfiddle;
|
||||
const resourcesTpl = '<scr' + 'ipt src="//unpkg.com/vue/dist/vue.js"></scr' + 'ipt>' +
|
||||
'\n<scr' + `ipt src="//unpkg.com/element-ui@${ version }/lib/index.js"></scr` + 'ipt>';
|
||||
let jsTpl = (script || '').replace(/export default/, 'var Main =').trim();
|
||||
let htmlTpl = `${resourcesTpl}\n<div id="app">\n${html.trim()}\n</div>`;
|
||||
@@ -216,23 +212,25 @@
|
||||
const data = {
|
||||
js: jsTpl,
|
||||
css: cssTpl,
|
||||
html: htmlTpl
|
||||
html: htmlTpl,
|
||||
panel_js: 3,
|
||||
panel_css: 1
|
||||
};
|
||||
const form = document.getElementById('fiddle-form') || document.createElement('form');
|
||||
while (form.firstChild) {
|
||||
form.removeChild(form.firstChild);
|
||||
}
|
||||
form.method = 'POST';
|
||||
form.action = 'https://codepen.io/pen/define/';
|
||||
form.innerHTML = '';
|
||||
const node = document.createElement('textarea');
|
||||
|
||||
form.method = 'post';
|
||||
form.action = 'https://jsfiddle.net/api/post/library/pure/';
|
||||
form.target = '_blank';
|
||||
|
||||
for (let name in data) {
|
||||
node.name = name;
|
||||
node.value = data[name].toString();
|
||||
form.appendChild(node.cloneNode());
|
||||
}
|
||||
form.setAttribute('id', 'fiddle-form');
|
||||
form.style.display = 'none';
|
||||
|
||||
const input = document.createElement('input');
|
||||
input.setAttribute('name', 'data');
|
||||
input.setAttribute('type', 'hidden');
|
||||
input.setAttribute('value', JSON.stringify(data));
|
||||
|
||||
form.appendChild(input);
|
||||
document.body.appendChild(form);
|
||||
|
||||
form.submit();
|
||||
@@ -301,25 +299,6 @@
|
||||
}
|
||||
},
|
||||
|
||||
created() {
|
||||
const highlight = this.$slots.highlight;
|
||||
if (highlight && highlight[0]) {
|
||||
let code = '';
|
||||
let cur = highlight[0];
|
||||
if (cur.tag === 'pre' && (cur.children && cur.children[0])) {
|
||||
cur = cur.children[0];
|
||||
if (cur.tag === 'code') {
|
||||
code = cur.children[0].text;
|
||||
}
|
||||
}
|
||||
if (code) {
|
||||
this.codepen.html = stripTemplate(code);
|
||||
this.codepen.script = stripScript(code);
|
||||
this.codepen.style = stripStyle(code);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
mounted() {
|
||||
this.$nextTick(() => {
|
||||
let highlight = this.$el.getElementsByClassName('highlight')[0];
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style lang="scss">
|
||||
<style>
|
||||
.footer-nav {
|
||||
padding: 40px 0;
|
||||
color: #333;
|
||||
|
||||
@@ -7,10 +7,10 @@
|
||||
<a href="https://github.com/ElemeFE/element/releases" class="footer-main-link" target="_blank">{{ langConfig.changelog }}</a>
|
||||
<a href="https://github.com/ElemeFE/element/blob/dev/FAQ.md" class="footer-main-link" target="_blank">{{ langConfig.faq }}</a>
|
||||
<a href="https://github.com/ElementUI/element-starter" class="footer-main-link" target="_blank">{{ langConfig.starter }}</a>
|
||||
<a :href="'/#/' + lang + '/component/custom-theme'" class="footer-main-link" target="_blank">{{ langConfig.theme }}</a>
|
||||
<a href="https://github.com/ElementUI/element-theme" class="footer-main-link" target="_blank">{{ langConfig.theme }}</a>
|
||||
<a href="https://github.com/ElementUI/theme-chalk-preview" class="footer-main-link" target="_blank">{{ langConfig.preview }}</a>
|
||||
<a href="https://github.com/elemefe/element-react" class="footer-main-link" target="_blank">Element-React</a>
|
||||
<a href="https://github.com/ElemeFE/element-angular" class="footer-main-link" target="_blank">Element-Angular</a>
|
||||
<a href="https://github.com/eleme/morjs" class="footer-main-link" target="_blank">MorJS</a>
|
||||
</div>
|
||||
<div class="footer-main">
|
||||
<h4>{{ langConfig.community }}</h4>
|
||||
@@ -28,17 +28,8 @@
|
||||
width="120"
|
||||
popper-class="footer-popover"
|
||||
trigger="hover">
|
||||
<div class="footer-popover-title">{{ langConfig.elemeTech }}</div>
|
||||
<img src="https://gw.alicdn.com/imgextra/i4/O1CN01dBDgJP1t4R3qikGBP_!!6000000005848-0-tps-344-344.jpg" alt="">
|
||||
</el-popover>
|
||||
<el-popover
|
||||
ref="weixin"
|
||||
placement="top"
|
||||
width="120"
|
||||
popper-class="footer-popover"
|
||||
trigger="hover">
|
||||
<div class="footer-popover-title">{{ langConfig.elemeDesign }}</div>
|
||||
<img src="https://gw.alicdn.com/imgextra/i4/O1CN015ha1O71yg3g1QaKEi_!!6000000006607-0-tps-1280-1280.jpg" alt="">
|
||||
<div class="footer-popover-title">{{ langConfig.eleme }} UED</div>
|
||||
<img src="../assets/images/qrcode.png" alt="">
|
||||
</el-popover>
|
||||
<i class="doc-icon-weixin elementdoc" v-popover:weixin></i>
|
||||
<a href="https://github.com/elemefe" target="_blank">
|
||||
@@ -52,7 +43,7 @@
|
||||
</footer>
|
||||
</template>
|
||||
|
||||
<style lang="scss">
|
||||
<style>
|
||||
.footer {
|
||||
background-color: #F7FBFD;
|
||||
width: 100%;
|
||||
@@ -71,7 +62,7 @@
|
||||
display: inline-block;
|
||||
vertical-align: top;
|
||||
margin-right: 110px;
|
||||
|
||||
|
||||
h4 {
|
||||
font-size: 18px;
|
||||
color: #333;
|
||||
@@ -95,7 +86,7 @@
|
||||
.footer-social {
|
||||
float: right;
|
||||
text-align: right;
|
||||
|
||||
|
||||
.footer-social-title {
|
||||
color: #666;
|
||||
font-size: 18px;
|
||||
@@ -144,7 +135,7 @@
|
||||
}
|
||||
|
||||
img {
|
||||
width: 100px;
|
||||
size: 100px;
|
||||
margin: 10px;
|
||||
}
|
||||
}
|
||||
@@ -153,13 +144,13 @@
|
||||
height: auto;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@media (max-width: 1000px) {
|
||||
.footer-social {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@media (max-width: 768px) {
|
||||
.footer {
|
||||
.footer-main {
|
||||
|
||||
@@ -1,23 +1,8 @@
|
||||
<style lang="scss" scoped>
|
||||
<style scoped>
|
||||
.headerWrapper {
|
||||
height: 80px;
|
||||
}
|
||||
|
||||
#v3-banner {
|
||||
background-color: #409EFF;
|
||||
min-height: 30px;
|
||||
padding: 5px 60px;
|
||||
z-index: 19;
|
||||
box-sizing: border-box;
|
||||
text-align: center;
|
||||
color: #eee;
|
||||
}
|
||||
|
||||
#v3-banner a {
|
||||
color: #FFF;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.header {
|
||||
height: 80px;
|
||||
background-color: #fff;
|
||||
@@ -25,14 +10,13 @@
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
line-height: 80px;
|
||||
line-height: @height;
|
||||
z-index: 100;
|
||||
position: relative;
|
||||
|
||||
.container {
|
||||
height: 100%;
|
||||
box-sizing: border-box;
|
||||
border-bottom: 1px solid #DCDFE6;
|
||||
}
|
||||
|
||||
.nav-lang-spe {
|
||||
@@ -70,15 +54,9 @@
|
||||
height: 100%;
|
||||
line-height: 80px;
|
||||
background: transparent;
|
||||
@utils-clearfix;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
&::before, &::after {
|
||||
display: table;
|
||||
content: "";
|
||||
}
|
||||
&::after {
|
||||
clear: both;
|
||||
}
|
||||
}
|
||||
|
||||
.nav-gap {
|
||||
@@ -112,11 +90,11 @@
|
||||
list-style: none;
|
||||
position: relative;
|
||||
cursor: pointer;
|
||||
|
||||
|
||||
&.nav-algolia-search {
|
||||
cursor: default;
|
||||
}
|
||||
|
||||
|
||||
&.lang-item,
|
||||
&:last-child {
|
||||
cursor: default;
|
||||
@@ -144,24 +122,23 @@
|
||||
|
||||
a {
|
||||
text-decoration: none;
|
||||
color: #1989FA;
|
||||
opacity: 0.5;
|
||||
color: #888;
|
||||
display: block;
|
||||
padding: 0 22px;
|
||||
|
||||
&.active,
|
||||
&:hover {
|
||||
opacity: 1;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
&.active::after {
|
||||
content: '';
|
||||
display: inline-block;
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
left: calc(50% - 15px);
|
||||
width: 30px;
|
||||
height: 2px;
|
||||
bottom: 15px;
|
||||
left: calc(50% - 7px);
|
||||
width: 14px;
|
||||
height: 4px;
|
||||
background: #409EFF;
|
||||
}
|
||||
}
|
||||
@@ -195,7 +172,7 @@
|
||||
transform: translateY(-2px);
|
||||
}
|
||||
|
||||
.is-active {
|
||||
@when active {
|
||||
span, i {
|
||||
color: #409EFF;
|
||||
}
|
||||
@@ -210,7 +187,7 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
.nav-dropdown-list {
|
||||
width: auto;
|
||||
}
|
||||
@@ -230,7 +207,7 @@
|
||||
&:last-child {
|
||||
margin-left: 10px;
|
||||
}
|
||||
|
||||
|
||||
a {
|
||||
padding: 0 5px;
|
||||
}
|
||||
@@ -254,11 +231,11 @@
|
||||
|
||||
&.lang-item {
|
||||
height: 100%;
|
||||
|
||||
|
||||
.nav-lang {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
|
||||
span {
|
||||
padding-bottom: 0;
|
||||
}
|
||||
@@ -282,18 +259,6 @@
|
||||
</style>
|
||||
<template>
|
||||
<div class="headerWrapper">
|
||||
<div id="v3-banner" v-if="isHome">
|
||||
<template v-if="lang === 'zh-CN'">
|
||||
您正在浏览基于 Vue 2.x 的文档;
|
||||
<a href="https://element-plus.org/#/zh-CN">点击查看 Vue 3.x 版本。</a>
|
||||
饿了么开源了自研多端框架 MorJS,
|
||||
<a href="https://github.com/eleme/morjs">欢迎点击查看或试用 👏🏻</a>
|
||||
</template>
|
||||
<template v-else>
|
||||
You’re browsing the documentation of Element UI for Vue 2.x version.
|
||||
<a href="https://element-plus.org">Click here</a> for Vue 3.x version
|
||||
</template>
|
||||
</div>
|
||||
<header class="header" ref="header">
|
||||
<div class="container">
|
||||
<h1><router-link :to="`/${ lang }`">
|
||||
@@ -328,14 +293,6 @@
|
||||
:to="`/${ lang }/component`">{{ langConfig.components }}
|
||||
</router-link>
|
||||
</li>
|
||||
<li
|
||||
class="nav-item nav-item-theme"
|
||||
>
|
||||
<router-link
|
||||
active-class="active"
|
||||
:to="`/${ lang }/theme`">{{ langConfig.theme }}
|
||||
</router-link>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<router-link
|
||||
active-class="active"
|
||||
@@ -396,6 +353,11 @@
|
||||
</el-dropdown-menu>
|
||||
</el-dropdown>
|
||||
</li>
|
||||
|
||||
<!--theme picker-->
|
||||
<li class="nav-item nav-theme-switch" v-show="isComponentPage">
|
||||
<theme-picker></theme-picker>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</header>
|
||||
@@ -406,10 +368,6 @@
|
||||
import AlgoliaSearch from './search.vue';
|
||||
import compoLang from '../i18n/component.json';
|
||||
import Element from 'main/index.js';
|
||||
import themeLoader from './theme/loader';
|
||||
import bus from '../bus';
|
||||
import { ACTION_USER_CONFIG_UPDATE } from './theme/constant.js';
|
||||
|
||||
const { version } = Element;
|
||||
|
||||
export default {
|
||||
@@ -423,14 +381,11 @@
|
||||
langs: {
|
||||
'zh-CN': '中文',
|
||||
'en-US': 'English',
|
||||
'es': 'Español',
|
||||
'fr-FR': 'Français'
|
||||
'es': 'Español'
|
||||
}
|
||||
};
|
||||
},
|
||||
|
||||
mixins: [themeLoader],
|
||||
|
||||
components: {
|
||||
ThemePicker,
|
||||
AlgoliaSearch
|
||||
@@ -448,23 +403,9 @@
|
||||
},
|
||||
isComponentPage() {
|
||||
return /^component/.test(this.$route.name);
|
||||
},
|
||||
isHome() {
|
||||
return /^home/.test(this.$route.name);
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
const testInnerImg = new Image();
|
||||
testInnerImg.onload = () => {
|
||||
this.$isEle = true;
|
||||
ga('send', 'event', 'DocView', 'Ali', 'Inner');
|
||||
};
|
||||
testInnerImg.onerror = (err) => {
|
||||
ga('send', 'event', 'DocView', 'Ali', 'Outer');
|
||||
console.error(err);
|
||||
};
|
||||
testInnerImg.src = `https://private-alipayobjects.alipay.com/alipay-rmsdeploy-image/rmsportal/VmvVUItLdPNqKlNGuRHi.png?t=${Date.now()}`;
|
||||
},
|
||||
|
||||
methods: {
|
||||
switchVersion(version) {
|
||||
if (version === this.version) return;
|
||||
@@ -499,17 +440,6 @@
|
||||
};
|
||||
xhr.open('GET', '/versions.json');
|
||||
xhr.send();
|
||||
let primaryLast = '#409EFF';
|
||||
bus.$on(ACTION_USER_CONFIG_UPDATE, (val) => {
|
||||
let primaryColor = val.global['$--color-primary'];
|
||||
if (!primaryColor) primaryColor = '#409EFF';
|
||||
const base64svg = 'data:image/svg+xml;base64,';
|
||||
const imgSet = document.querySelectorAll('h1 img');
|
||||
imgSet.forEach((img) => {
|
||||
img.src = `${base64svg}${window.btoa(window.atob(img.src.replace(base64svg, '')).replace(primaryLast, primaryColor))}`;
|
||||
});
|
||||
primaryLast = primaryColor;
|
||||
});
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
@@ -6,12 +6,11 @@
|
||||
:fetch-suggestions="querySearch"
|
||||
:placeholder="placeholder"
|
||||
:trigger-on-focus="false"
|
||||
@select="handleSelect"
|
||||
highlight-first-item>
|
||||
@select="handleSelect">
|
||||
<template slot-scope="props">
|
||||
<p class="algolia-search-title" v-if="props.item.title">
|
||||
<span v-html="props.item.highlightedCompo"></span>
|
||||
<span class="algolia-search-separator"></span>
|
||||
<span class="algolia-search-separator">></span>
|
||||
<span v-html="props.item.title"></span>
|
||||
</p>
|
||||
<p
|
||||
@@ -35,10 +34,10 @@
|
||||
</el-autocomplete>
|
||||
</template>
|
||||
|
||||
<style lang="scss">
|
||||
<style>
|
||||
.algolia-search {
|
||||
width: 450px !important;
|
||||
|
||||
|
||||
&.is-empty {
|
||||
.el-autocomplete-suggestion__list {
|
||||
padding-bottom: 0;
|
||||
@@ -52,27 +51,27 @@
|
||||
|
||||
li {
|
||||
border-bottom: solid 1px #ebebeb;
|
||||
|
||||
|
||||
&:last-child {
|
||||
border-bottom: none;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
.algolia-highlight {
|
||||
color: #409EFF;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
|
||||
.algolia-search-title {
|
||||
font-size: 14px;
|
||||
margin: 6px 0;
|
||||
line-height: 1.8;
|
||||
}
|
||||
|
||||
|
||||
.algolia-search-separator {
|
||||
padding: 0 6px;
|
||||
}
|
||||
|
||||
|
||||
.algolia-search-content {
|
||||
font-size: 12px;
|
||||
margin: 6px 0;
|
||||
@@ -81,7 +80,7 @@
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
|
||||
.algolia-search-link {
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
@@ -97,14 +96,14 @@
|
||||
&:hover {
|
||||
background-color: #e4e7ed;
|
||||
}
|
||||
|
||||
|
||||
img {
|
||||
display: inline-block;
|
||||
height: 17px;
|
||||
margin-top: 10px;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
.algolia-search-empty {
|
||||
margin: 5px 0;
|
||||
text-align: center;
|
||||
@@ -137,11 +136,6 @@
|
||||
search: 'Buscar',
|
||||
empty: 'No hay datos que coincidan',
|
||||
index: 'es'
|
||||
},
|
||||
'fr-FR': {
|
||||
search: 'Rechercher',
|
||||
empty: 'Aucun résultat',
|
||||
index: 'fr'
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -219,4 +213,4 @@
|
||||
this.initIndex();
|
||||
}
|
||||
};
|
||||
</script>
|
||||
</script>
|
||||
@@ -1,4 +1,4 @@
|
||||
<style lang="scss">
|
||||
<style>
|
||||
.side-nav {
|
||||
width: 100%;
|
||||
box-sizing: border-box;
|
||||
@@ -122,6 +122,26 @@
|
||||
:class="{ 'is-fade': isFade }"
|
||||
:style="navStyle">
|
||||
<ul>
|
||||
<li class="nav-item sponsors">
|
||||
<a>{{ lang === 'zh-CN' ? '赞助商' : 'Sponsors' }}</a>
|
||||
<ul class="pure-menu-list sub-nav">
|
||||
<li class="nav-item" v-show="lang !== 'zh-CN'">
|
||||
<a href="https://tipe.io/?ref=element" target="_blank">
|
||||
<img src="~examples/assets/images/tipe.svg" alt="tipe.io">
|
||||
</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="sponsor" href="https://www.duotai.net/?utm_source=element" target="_blank">
|
||||
<img src="~examples/assets/images/duotai.svg" alt="duotai">
|
||||
</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="sponsor" href="https://www.duohui.cn/?utm_source=element&utm_medium=web&utm_campaign=element-index" target="_blank">
|
||||
<img src="~examples/assets/images/duohui.svg" alt="duohui">
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
</li>
|
||||
<li
|
||||
class="nav-item"
|
||||
v-for="(item, key) in data"
|
||||
@@ -160,7 +180,7 @@
|
||||
<li
|
||||
class="nav-item"
|
||||
v-for="(navItem, key) in group.list"
|
||||
v-show="!navItem.disabled"
|
||||
v-if="!navItem.disabled"
|
||||
:key="key">
|
||||
<router-link
|
||||
active-class="active"
|
||||
|
||||
@@ -1,153 +0,0 @@
|
||||
<template>
|
||||
<div class="configurator-action">
|
||||
<div class="action-group">
|
||||
<el-tooltip :content="getActionDisplayName('undo')">
|
||||
<img
|
||||
src="../../assets/images/icon-undo.svg"
|
||||
@click="onUndo"
|
||||
:class="{ 'active': userConfigHistory.length > 0 }"
|
||||
/>
|
||||
</el-tooltip>
|
||||
<el-tooltip :content="getActionDisplayName('redo')">
|
||||
<img
|
||||
src="../../assets/images/icon-redo.svg"
|
||||
@click="onRedo"
|
||||
:class="{ 'active': userConfigRedoHistory.length > 0 }"
|
||||
/>
|
||||
</el-tooltip>
|
||||
<div class="button-group">
|
||||
<el-button
|
||||
class="reset"
|
||||
type="primary"
|
||||
round
|
||||
size="mini"
|
||||
:disabled="isOfficial"
|
||||
@click="onReset"
|
||||
>
|
||||
{{getActionDisplayName('reset-theme')}}
|
||||
</el-button>
|
||||
<el-button
|
||||
class="download"
|
||||
type="primary"
|
||||
round
|
||||
size="mini"
|
||||
:disabled="downloadDisabled"
|
||||
@click="onDownload"
|
||||
>
|
||||
{{getActionDisplayName('download-theme')}}
|
||||
</el-button>
|
||||
</div>
|
||||
</div>
|
||||
<el-select v-model="selectedComponent" class="selector">
|
||||
<el-option
|
||||
v-for="item in selectOptions"
|
||||
:key="item.value"
|
||||
:label="item.label"
|
||||
:value="item.value">
|
||||
</el-option>
|
||||
</el-select>
|
||||
<div class="line"></div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style lang="scss">
|
||||
.configurator-action {
|
||||
padding: 15px 18px 0;
|
||||
.action-group {
|
||||
padding: 5px 0;
|
||||
img {
|
||||
cursor: not-allowed;
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
padding: 7px 0;
|
||||
margin-left: 5px;
|
||||
opacity: .5;
|
||||
&.active {
|
||||
opacity: 1;
|
||||
cursor: pointer;
|
||||
}
|
||||
&:last-of-type {
|
||||
margin-left: 10px;
|
||||
}
|
||||
}
|
||||
.button-group {
|
||||
float: right;
|
||||
.el-button {
|
||||
padding: 6px 15px;
|
||||
&.is-disabled {
|
||||
color: #C0C4CC;
|
||||
background-color: #fff;
|
||||
border-color: #EBEEF5;
|
||||
}
|
||||
}
|
||||
.reset {
|
||||
background: #E6F1FC;
|
||||
color: #1989FA;
|
||||
border-color: #A2CFFC;
|
||||
}
|
||||
.download {
|
||||
background: #1989FA;
|
||||
color: #FFF;
|
||||
border-color: #1989FA
|
||||
}
|
||||
}
|
||||
}
|
||||
.selector {
|
||||
width: 100%;
|
||||
input {
|
||||
background: #f5f7fa;
|
||||
border: none;
|
||||
font-size: 18px;
|
||||
padding-left: 0;
|
||||
color: #606266;
|
||||
}
|
||||
}
|
||||
.line {
|
||||
width: 100%;
|
||||
height: 0;
|
||||
border-bottom: 1px solid #DCDFE6;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
<script>
|
||||
import { getActionDisplayName } from './utils/utils';
|
||||
export default {
|
||||
props: {
|
||||
selectOptions: Array,
|
||||
userConfigHistory: Array,
|
||||
userConfigRedoHistory: Array,
|
||||
isOfficial: Boolean,
|
||||
onUndo: Function,
|
||||
onRedo: Function
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
selectedComponent: 'color',
|
||||
downloadDisabled: false
|
||||
};
|
||||
},
|
||||
watch: {
|
||||
selectedComponent: {
|
||||
handler(val) {
|
||||
this.$emit('select', val);
|
||||
}
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
getActionDisplayName(key) {
|
||||
return getActionDisplayName(key);
|
||||
},
|
||||
onReset() {
|
||||
this.$parent.onReset();
|
||||
},
|
||||
onDownload() {
|
||||
this.downloadDisabled = true;
|
||||
this.$parent.onDownload();
|
||||
setTimeout(() => {
|
||||
this.downloadDisabled = false;
|
||||
}, 2500);
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
@@ -1,89 +0,0 @@
|
||||
<template>
|
||||
<section class="config" :key="displayName">
|
||||
<div class="config-label">
|
||||
<el-tooltip :content="displayName" placement="top">
|
||||
<span>{{displayKeyName}}</span>
|
||||
</el-tooltip>
|
||||
</div>
|
||||
<div class="config-content">
|
||||
<theme-input
|
||||
v-if="isGlobal"
|
||||
:val="value"
|
||||
@change="onChange"
|
||||
></theme-input>
|
||||
<el-select
|
||||
size="medium"
|
||||
v-if="!isGlobal"
|
||||
v-model="value"
|
||||
class="select"
|
||||
@change="onSelectChange"
|
||||
>
|
||||
<el-option
|
||||
v-for="item in options"
|
||||
:key="item.value"
|
||||
:label="item.label"
|
||||
:value="item.value">
|
||||
</el-option>
|
||||
</el-select>
|
||||
</div>
|
||||
</section>
|
||||
</template>
|
||||
|
||||
<style>
|
||||
.select {
|
||||
width: 100%;
|
||||
}
|
||||
</style>
|
||||
|
||||
<script>
|
||||
import Mixin from './mixin';
|
||||
import Input from './input';
|
||||
import { getStyleDisplayName } from '../utils/utils.js';
|
||||
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
options: [],
|
||||
value: ''
|
||||
};
|
||||
},
|
||||
components: {
|
||||
themeInput: Input
|
||||
},
|
||||
mixins: [Mixin],
|
||||
computed: {
|
||||
isGlobalInputValue() {
|
||||
return this.config.value.startsWith('$');
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
onSelectChange(e) {
|
||||
this.onChange(e);
|
||||
},
|
||||
initSelectOption() {
|
||||
this.options = [];
|
||||
const golbalV = this.golbalValue.border;
|
||||
if (golbalV) {
|
||||
Object.keys(golbalV).forEach((font) => {
|
||||
if (font.includes('border-radius')) {
|
||||
const size = golbalV[font];
|
||||
this.options.push({
|
||||
value: size.key,
|
||||
label: getStyleDisplayName(size)
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
'mergedValue': {
|
||||
immediate: true,
|
||||
handler(value) {
|
||||
this.initSelectOption();
|
||||
this.value = this.mergedValue;
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
@@ -1,158 +0,0 @@
|
||||
<template>
|
||||
<section class="config" :key="displayName">
|
||||
<div class="config-label">
|
||||
<el-tooltip :content="displayName" placement="top">
|
||||
<span>{{displayKeyName}}</span>
|
||||
</el-tooltip>
|
||||
<el-button
|
||||
class="plus-button"
|
||||
size="mini"
|
||||
round
|
||||
icon="el-icon-plus"
|
||||
@click.stop="onAddShadow"
|
||||
>
|
||||
</el-button>
|
||||
</div>
|
||||
<div class="config-content" v-for="(each, key) in valueArr" :key="key">
|
||||
<div class="content-10">
|
||||
<color-picker
|
||||
size="mini"
|
||||
class="colorPicker"
|
||||
v-model="each.color"
|
||||
@change="val => onInputChange(val, key, 'color')"
|
||||
show-alpha
|
||||
></color-picker>
|
||||
<span class="content-tip">Color</span>
|
||||
</div>
|
||||
<div class="content-20">
|
||||
<theme-input
|
||||
size="mini"
|
||||
:val="each.offsetX"
|
||||
@change="val => onInputChange(Number(val), key, 'offsetX')"
|
||||
>
|
||||
</theme-input>
|
||||
<span class="content-tip">X-px</span>
|
||||
</div>
|
||||
<div class="content-20">
|
||||
<theme-input
|
||||
size="mini"
|
||||
:val="each.offsetY"
|
||||
@change="val => onInputChange(Number(val), key, 'offsetY')"
|
||||
>
|
||||
</theme-input>
|
||||
<span class="content-tip">Y-px</span>
|
||||
</div>
|
||||
<div class="content-20">
|
||||
<theme-input
|
||||
size="mini"
|
||||
:val="each.spreadRadius"
|
||||
@change="val => onInputChange(Number(val), key, 'spreadRadius')"
|
||||
>
|
||||
</theme-input>
|
||||
<span class="content-tip">Spread</span>
|
||||
</div>
|
||||
<div class="content-20">
|
||||
<theme-input
|
||||
size="mini"
|
||||
:val="each.blurRadius"
|
||||
@change="val => onInputChange(Number(val), key, 'blurRadius')"
|
||||
>
|
||||
</theme-input>
|
||||
<span class="content-tip">Blur</span>
|
||||
</div>
|
||||
<div class="content-10">
|
||||
<el-button
|
||||
size="mini"
|
||||
round
|
||||
icon="el-icon-minus"
|
||||
@click.stop="val => onMinusShadow(key)"
|
||||
></el-button>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
.plus-button {
|
||||
position: absolute;
|
||||
left: 90%;
|
||||
margin-top: 4px;
|
||||
}
|
||||
.colorPicker {
|
||||
margin-left: 0;
|
||||
}
|
||||
.content-20 .el-input__suffix-inner span{
|
||||
line-height: 28px;
|
||||
}
|
||||
.content-20 {
|
||||
padding: 0 3px;
|
||||
}
|
||||
.content-10 {
|
||||
vertical-align: top;
|
||||
}
|
||||
.content-tip {
|
||||
color: #909399;
|
||||
font-size: 12px;
|
||||
}
|
||||
.config-content {
|
||||
padding: 5px 0;
|
||||
}
|
||||
/* Element buton style override */
|
||||
.el-button--mini.is-round {
|
||||
padding: 3px 3px;
|
||||
}
|
||||
</style>
|
||||
<script>
|
||||
import Mixin from './mixin';
|
||||
import Input from './input';
|
||||
import { parse as parseShaodw, stringify as stringifyShaodw } from '../utils/boxShadow.js';
|
||||
import ColorPicker from './color-picker';
|
||||
|
||||
export default {
|
||||
components: {
|
||||
ColorPicker,
|
||||
themeInput: Input
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
valueArr: []
|
||||
};
|
||||
},
|
||||
mixins: [Mixin],
|
||||
methods: {
|
||||
onAddShadow() {
|
||||
this.valueArr.push({
|
||||
offsetX: 0,
|
||||
offsetY: 0,
|
||||
spreadRadius: 0,
|
||||
blurRadius: 0,
|
||||
color: 'rgba(0,0,0,0)',
|
||||
inset: false
|
||||
});
|
||||
},
|
||||
onMinusShadow(index) {
|
||||
this.valueArr.splice(index, 1);
|
||||
this.onShadowChange();
|
||||
},
|
||||
onInputChange(e, index, key) {
|
||||
const arr = this.valueArr[index];
|
||||
arr[key] = e;
|
||||
this.valueArr.splice(index, 1, arr);
|
||||
this.onShadowChange();
|
||||
},
|
||||
onShadowChange() {
|
||||
this.onChange(
|
||||
stringifyShaodw(this.valueArr)
|
||||
);
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
'mergedValue': {
|
||||
immediate: true,
|
||||
handler(value) {
|
||||
this.valueArr = parseShaodw(value);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
@@ -1,8 +0,0 @@
|
||||
import ColorPicker from './src/main';
|
||||
|
||||
/* istanbul ignore next */
|
||||
ColorPicker.install = function(Vue) {
|
||||
Vue.component(ColorPicker.name, ColorPicker);
|
||||
};
|
||||
|
||||
export default ColorPicker;
|
||||
@@ -1,316 +0,0 @@
|
||||
const hsv2hsl = function(hue, sat, val) {
|
||||
return [
|
||||
hue,
|
||||
(sat * val / ((hue = (2 - sat) * val) < 1 ? hue : 2 - hue)) || 0,
|
||||
hue / 2
|
||||
];
|
||||
};
|
||||
|
||||
// Need to handle 1.0 as 100%, since once it is a number, there is no difference between it and 1
|
||||
// <http://stackoverflow.com/questions/7422072/javascript-how-to-detect-number-as-a-decimal-including-1-0>
|
||||
const isOnePointZero = function(n) {
|
||||
return typeof n === 'string' && n.indexOf('.') !== -1 && parseFloat(n) === 1;
|
||||
};
|
||||
|
||||
const isPercentage = function(n) {
|
||||
return typeof n === 'string' && n.indexOf('%') !== -1;
|
||||
};
|
||||
|
||||
// Take input from [0, n] and return it as [0, 1]
|
||||
const bound01 = function(value, max) {
|
||||
if (isOnePointZero(value)) value = '100%';
|
||||
|
||||
const processPercent = isPercentage(value);
|
||||
value = Math.min(max, Math.max(0, parseFloat(value)));
|
||||
|
||||
// Automatically convert percentage into number
|
||||
if (processPercent) {
|
||||
value = parseInt(value * max, 10) / 100;
|
||||
}
|
||||
|
||||
// Handle floating point rounding errors
|
||||
if ((Math.abs(value - max) < 0.000001)) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Convert into [0, 1] range if it isn't already
|
||||
return (value % max) / parseFloat(max);
|
||||
};
|
||||
|
||||
const INT_HEX_MAP = { 10: 'A', 11: 'B', 12: 'C', 13: 'D', 14: 'E', 15: 'F' };
|
||||
|
||||
const toHex = function({ r, g, b }) {
|
||||
const hexOne = function(value) {
|
||||
value = Math.min(Math.round(value), 255);
|
||||
const high = Math.floor(value / 16);
|
||||
const low = value % 16;
|
||||
return '' + (INT_HEX_MAP[high] || high) + (INT_HEX_MAP[low] || low);
|
||||
};
|
||||
|
||||
if (isNaN(r) || isNaN(g) || isNaN(b)) return '';
|
||||
|
||||
return '#' + hexOne(r) + hexOne(g) + hexOne(b);
|
||||
};
|
||||
|
||||
const HEX_INT_MAP = { A: 10, B: 11, C: 12, D: 13, E: 14, F: 15 };
|
||||
|
||||
const parseHexChannel = function(hex) {
|
||||
if (hex.length === 2) {
|
||||
return (HEX_INT_MAP[hex[0].toUpperCase()] || +hex[0]) * 16 + (HEX_INT_MAP[hex[1].toUpperCase()] || +hex[1]);
|
||||
}
|
||||
|
||||
return HEX_INT_MAP[hex[1].toUpperCase()] || +hex[1];
|
||||
};
|
||||
|
||||
const hsl2hsv = function(hue, sat, light) {
|
||||
sat = sat / 100;
|
||||
light = light / 100;
|
||||
let smin = sat;
|
||||
const lmin = Math.max(light, 0.01);
|
||||
let sv;
|
||||
let v;
|
||||
|
||||
light *= 2;
|
||||
sat *= (light <= 1) ? light : 2 - light;
|
||||
smin *= lmin <= 1 ? lmin : 2 - lmin;
|
||||
v = (light + sat) / 2;
|
||||
sv = light === 0 ? (2 * smin) / (lmin + smin) : (2 * sat) / (light + sat);
|
||||
|
||||
return {
|
||||
h: hue,
|
||||
s: sv * 100,
|
||||
v: v * 100
|
||||
};
|
||||
};
|
||||
|
||||
// `rgbToHsv`
|
||||
// Converts an RGB color value to HSV
|
||||
// *Assumes:* r, g, and b are contained in the set [0, 255] or [0, 1]
|
||||
// *Returns:* { h, s, v } in [0,1]
|
||||
const rgb2hsv = function(r, g, b) {
|
||||
r = bound01(r, 255);
|
||||
g = bound01(g, 255);
|
||||
b = bound01(b, 255);
|
||||
|
||||
const max = Math.max(r, g, b);
|
||||
const min = Math.min(r, g, b);
|
||||
let h, s;
|
||||
let v = max;
|
||||
|
||||
const d = max - min;
|
||||
s = max === 0 ? 0 : d / max;
|
||||
|
||||
if (max === min) {
|
||||
h = 0; // achromatic
|
||||
} else {
|
||||
switch (max) {
|
||||
case r:
|
||||
h = (g - b) / d + (g < b ? 6 : 0);
|
||||
break;
|
||||
case g:
|
||||
h = (b - r) / d + 2;
|
||||
break;
|
||||
case b:
|
||||
h = (r - g) / d + 4;
|
||||
break;
|
||||
}
|
||||
h /= 6;
|
||||
}
|
||||
|
||||
return { h: h * 360, s: s * 100, v: v * 100 };
|
||||
};
|
||||
|
||||
// `hsvToRgb`
|
||||
// Converts an HSV color value to RGB.
|
||||
// *Assumes:* h is contained in [0, 1] or [0, 360] and s and v are contained in [0, 1] or [0, 100]
|
||||
// *Returns:* { r, g, b } in the set [0, 255]
|
||||
const hsv2rgb = function(h, s, v) {
|
||||
h = bound01(h, 360) * 6;
|
||||
s = bound01(s, 100);
|
||||
v = bound01(v, 100);
|
||||
|
||||
const i = Math.floor(h);
|
||||
const f = h - i;
|
||||
const p = v * (1 - s);
|
||||
const q = v * (1 - f * s);
|
||||
const t = v * (1 - (1 - f) * s);
|
||||
const mod = i % 6;
|
||||
const r = [v, q, p, p, t, v][mod];
|
||||
const g = [t, v, v, q, p, p][mod];
|
||||
const b = [p, p, t, v, v, q][mod];
|
||||
|
||||
return {
|
||||
r: Math.round(r * 255),
|
||||
g: Math.round(g * 255),
|
||||
b: Math.round(b * 255)
|
||||
};
|
||||
};
|
||||
|
||||
export default class Color {
|
||||
constructor(options) {
|
||||
this._hue = 0;
|
||||
this._saturation = 100;
|
||||
this._value = 100;
|
||||
this._alpha = 100;
|
||||
|
||||
this.enableAlpha = false;
|
||||
this.format = 'hex';
|
||||
this.value = '';
|
||||
|
||||
options = options || {};
|
||||
|
||||
for (let option in options) {
|
||||
if (options.hasOwnProperty(option)) {
|
||||
this[option] = options[option];
|
||||
}
|
||||
}
|
||||
|
||||
this.doOnChange();
|
||||
}
|
||||
|
||||
set(prop, value) {
|
||||
if (arguments.length === 1 && typeof prop === 'object') {
|
||||
for (let p in prop) {
|
||||
if (prop.hasOwnProperty(p)) {
|
||||
this.set(p, prop[p]);
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
this['_' + prop] = value;
|
||||
this.doOnChange();
|
||||
}
|
||||
|
||||
get(prop) {
|
||||
return this['_' + prop];
|
||||
}
|
||||
|
||||
toRgb() {
|
||||
return hsv2rgb(this._hue, this._saturation, this._value);
|
||||
}
|
||||
|
||||
fromString(value) {
|
||||
if (!value) {
|
||||
this._hue = 0;
|
||||
this._saturation = 100;
|
||||
this._value = 100;
|
||||
|
||||
this.doOnChange();
|
||||
return;
|
||||
}
|
||||
|
||||
const fromHSV = (h, s, v) => {
|
||||
this._hue = Math.max(0, Math.min(360, h));
|
||||
this._saturation = Math.max(0, Math.min(100, s));
|
||||
this._value = Math.max(0, Math.min(100, v));
|
||||
|
||||
this.doOnChange();
|
||||
};
|
||||
|
||||
if (value.indexOf('hsl') !== -1) {
|
||||
const parts = value.replace(/hsla|hsl|\(|\)/gm, '')
|
||||
.split(/\s|,/g).filter((val) => val !== '').map((val, index) => index > 2 ? parseFloat(val) : parseInt(val, 10));
|
||||
|
||||
if (parts.length === 4) {
|
||||
this._alpha = Math.floor(parseFloat(parts[3]) * 100);
|
||||
} else if (parts.length === 3) {
|
||||
this._alpha = 100;
|
||||
}
|
||||
if (parts.length >= 3) {
|
||||
const { h, s, v } = hsl2hsv(parts[0], parts[1], parts[2]);
|
||||
fromHSV(h, s, v);
|
||||
}
|
||||
} else if (value.indexOf('hsv') !== -1) {
|
||||
const parts = value.replace(/hsva|hsv|\(|\)/gm, '')
|
||||
.split(/\s|,/g).filter((val) => val !== '').map((val, index) => index > 2 ? parseFloat(val) : parseInt(val, 10));
|
||||
|
||||
if (parts.length === 4) {
|
||||
this._alpha = Math.floor(parseFloat(parts[3]) * 100);
|
||||
} else if (parts.length === 3) {
|
||||
this._alpha = 100;
|
||||
}
|
||||
if (parts.length >= 3) {
|
||||
fromHSV(parts[0], parts[1], parts[2]);
|
||||
}
|
||||
} else if (value.indexOf('rgb') !== -1) {
|
||||
const parts = value.replace(/rgba|rgb|\(|\)/gm, '')
|
||||
.split(/\s|,/g).filter((val) => val !== '').map((val, index) => index > 2 ? parseFloat(val) : parseInt(val, 10));
|
||||
|
||||
if (parts.length === 4) {
|
||||
this._alpha = Math.floor(parseFloat(parts[3]) * 100);
|
||||
} else if (parts.length === 3) {
|
||||
this._alpha = 100;
|
||||
}
|
||||
if (parts.length >= 3) {
|
||||
const { h, s, v } = rgb2hsv(parts[0], parts[1], parts[2]);
|
||||
fromHSV(h, s, v);
|
||||
}
|
||||
} else if (value.indexOf('#') !== -1) {
|
||||
const hex = value.replace('#', '').trim();
|
||||
let r, g, b;
|
||||
|
||||
if (hex.length === 3) {
|
||||
r = parseHexChannel(hex[0] + hex[0]);
|
||||
g = parseHexChannel(hex[1] + hex[1]);
|
||||
b = parseHexChannel(hex[2] + hex[2]);
|
||||
} else if (hex.length === 6 || hex.length === 8) {
|
||||
r = parseHexChannel(hex.substring(0, 2));
|
||||
g = parseHexChannel(hex.substring(2, 4));
|
||||
b = parseHexChannel(hex.substring(4, 6));
|
||||
}
|
||||
|
||||
if (hex.length === 8) {
|
||||
this._alpha = Math.floor(parseHexChannel(hex.substring(6)) / 255 * 100);
|
||||
} else if (hex.length === 3 || hex.length === 6) {
|
||||
this._alpha = 100;
|
||||
}
|
||||
|
||||
const { h, s, v } = rgb2hsv(r, g, b);
|
||||
fromHSV(h, s, v);
|
||||
}
|
||||
}
|
||||
|
||||
compare(color) {
|
||||
return Math.abs(color._hue - this._hue) < 2 &&
|
||||
Math.abs(color._saturation - this._saturation) < 1 &&
|
||||
Math.abs(color._value - this._value) < 1 &&
|
||||
Math.abs(color._alpha - this._alpha) < 1;
|
||||
}
|
||||
|
||||
doOnChange() {
|
||||
const { _hue, _saturation, _value, _alpha, format } = this;
|
||||
|
||||
if (this.enableAlpha) {
|
||||
switch (format) {
|
||||
case 'hsl':
|
||||
const hsl = hsv2hsl(_hue, _saturation / 100, _value / 100);
|
||||
this.value = `hsla(${ _hue }, ${ Math.round(hsl[1] * 100) }%, ${ Math.round(hsl[2] * 100) }%, ${ _alpha / 100})`;
|
||||
break;
|
||||
case 'hsv':
|
||||
this.value = `hsva(${ _hue }, ${ Math.round(_saturation) }%, ${ Math.round(_value) }%, ${ _alpha / 100})`;
|
||||
break;
|
||||
default:
|
||||
const { r, g, b } = hsv2rgb(_hue, _saturation, _value);
|
||||
this.value = `rgba(${r}, ${g}, ${b}, ${ _alpha / 100 })`;
|
||||
}
|
||||
} else {
|
||||
switch (format) {
|
||||
case 'hsl':
|
||||
const hsl = hsv2hsl(_hue, _saturation / 100, _value / 100);
|
||||
this.value = `hsl(${ _hue }, ${ Math.round(hsl[1] * 100) }%, ${ Math.round(hsl[2] * 100) }%)`;
|
||||
break;
|
||||
case 'hsv':
|
||||
this.value = `hsv(${ _hue }, ${ Math.round(_saturation) }%, ${ Math.round(_value) }%)`;
|
||||
break;
|
||||
case 'rgb':
|
||||
const { r, g, b } = hsv2rgb(_hue, _saturation, _value);
|
||||
this.value = `rgb(${r}, ${g}, ${b})`;
|
||||
break;
|
||||
default:
|
||||
this.value = toHex(hsv2rgb(_hue, _saturation, _value));
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -1,132 +0,0 @@
|
||||
<template>
|
||||
<div class="el-color-alpha-slider" :class="{ 'is-vertical': vertical }">
|
||||
<div class="el-color-alpha-slider__bar"
|
||||
@click="handleClick"
|
||||
ref="bar"
|
||||
:style="{
|
||||
background: background
|
||||
}">
|
||||
</div>
|
||||
<div class="el-color-alpha-slider__thumb"
|
||||
ref="thumb"
|
||||
:style="{
|
||||
left: thumbLeft + 'px',
|
||||
top: thumbTop + 'px'
|
||||
}">
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import draggable from '../draggable';
|
||||
|
||||
export default {
|
||||
name: 'el-color-alpha-slider',
|
||||
|
||||
props: {
|
||||
color: {
|
||||
required: true
|
||||
},
|
||||
vertical: Boolean
|
||||
},
|
||||
|
||||
watch: {
|
||||
'color._alpha'() {
|
||||
this.update();
|
||||
},
|
||||
|
||||
'color.value'() {
|
||||
this.update();
|
||||
}
|
||||
},
|
||||
|
||||
methods: {
|
||||
handleClick(event) {
|
||||
const thumb = this.$refs.thumb;
|
||||
const target = event.target;
|
||||
|
||||
if (target !== thumb) {
|
||||
this.handleDrag(event);
|
||||
}
|
||||
},
|
||||
|
||||
handleDrag(event) {
|
||||
const rect = this.$el.getBoundingClientRect();
|
||||
const { thumb } = this.$refs;
|
||||
|
||||
if (!this.vertical) {
|
||||
let left = event.clientX - rect.left;
|
||||
left = Math.max(thumb.offsetWidth / 2, left);
|
||||
left = Math.min(left, rect.width - thumb.offsetWidth / 2);
|
||||
|
||||
this.color.set('alpha', Math.round((left - thumb.offsetWidth / 2) / (rect.width - thumb.offsetWidth) * 100));
|
||||
} else {
|
||||
let top = event.clientY - rect.top;
|
||||
top = Math.max(thumb.offsetHeight / 2, top);
|
||||
top = Math.min(top, rect.height - thumb.offsetHeight / 2);
|
||||
|
||||
this.color.set('alpha', Math.round((top - thumb.offsetHeight / 2) / (rect.height - thumb.offsetHeight) * 100));
|
||||
}
|
||||
},
|
||||
|
||||
getThumbLeft() {
|
||||
if (this.vertical) return 0;
|
||||
const el = this.$el;
|
||||
const alpha = this.color._alpha;
|
||||
|
||||
if (!el) return 0;
|
||||
const thumb = this.$refs.thumb;
|
||||
return Math.round(alpha * (el.offsetWidth - thumb.offsetWidth / 2) / 100);
|
||||
},
|
||||
|
||||
getThumbTop() {
|
||||
if (!this.vertical) return 0;
|
||||
const el = this.$el;
|
||||
const alpha = this.color._alpha;
|
||||
|
||||
if (!el) return 0;
|
||||
const thumb = this.$refs.thumb;
|
||||
return Math.round(alpha * (el.offsetHeight - thumb.offsetHeight / 2) / 100);
|
||||
},
|
||||
|
||||
getBackground() {
|
||||
if (this.color && this.color.value) {
|
||||
const { r, g, b } = this.color.toRgb();
|
||||
return `linear-gradient(to right, rgba(${r}, ${g}, ${b}, 0) 0%, rgba(${r}, ${g}, ${b}, 1) 100%)`;
|
||||
}
|
||||
return null;
|
||||
},
|
||||
|
||||
update() {
|
||||
this.thumbLeft = this.getThumbLeft();
|
||||
this.thumbTop = this.getThumbTop();
|
||||
this.background = this.getBackground();
|
||||
}
|
||||
},
|
||||
|
||||
data() {
|
||||
return {
|
||||
thumbLeft: 0,
|
||||
thumbTop: 0,
|
||||
background: null
|
||||
};
|
||||
},
|
||||
|
||||
mounted() {
|
||||
const { bar, thumb } = this.$refs;
|
||||
|
||||
const dragConfig = {
|
||||
drag: (event) => {
|
||||
this.handleDrag(event);
|
||||
},
|
||||
end: (event) => {
|
||||
this.handleDrag(event);
|
||||
}
|
||||
};
|
||||
|
||||
draggable(bar, dragConfig);
|
||||
draggable(thumb, dragConfig);
|
||||
this.update();
|
||||
}
|
||||
};
|
||||
</script>
|
||||
@@ -1,111 +0,0 @@
|
||||
<template>
|
||||
<div class="el-color-predefine color-list-container">
|
||||
<div class="el-color-predefine__colors color-list">
|
||||
<div class="color-list-item"
|
||||
:class="{selected: item.selected, 'is-alpha': item._alpha < 100}"
|
||||
v-for="(item, index) in rgbaColors"
|
||||
:key="colors[index].variable"
|
||||
@click="handleSelect(index)">
|
||||
<span class="color-list-item-ball" :style="{'background-color': item.value}">
|
||||
</span>
|
||||
<div class="color-list-item-label">
|
||||
{{item.info.label}}
|
||||
<div class="color-list-item-value">
|
||||
{{item.info.value}}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<style>
|
||||
.color-list-container {
|
||||
border-top: 1px solid #EBEEF5;
|
||||
margin-top: 15px;
|
||||
padding-top: 10px;
|
||||
width: 100%;
|
||||
}
|
||||
.color-list {
|
||||
max-height: 138px;
|
||||
overflow: auto;
|
||||
}
|
||||
.color-list-item {
|
||||
height: 24px;
|
||||
width: 100%;
|
||||
cursor: pointer;
|
||||
margin: 2px 0;
|
||||
position: relative;
|
||||
}
|
||||
.color-list-item:hover {
|
||||
background: #efefef;
|
||||
}
|
||||
.color-list-item-ball {
|
||||
height: 20px;
|
||||
width: 20px;
|
||||
margin-top: 2px;
|
||||
margin-left: 5px;
|
||||
border-radius: 100%;
|
||||
display: block;
|
||||
position: absolute;
|
||||
}
|
||||
.color-list-item-label {
|
||||
margin-left: 35px;
|
||||
font-size: 13px;
|
||||
line-height: 24px;
|
||||
display: inline-block;
|
||||
width: 85%;
|
||||
overflow: hidden;
|
||||
}
|
||||
.color-list-item-value {
|
||||
float: right;
|
||||
}
|
||||
</style>
|
||||
|
||||
<script>
|
||||
import Color from '../color';
|
||||
|
||||
export default {
|
||||
props: {
|
||||
colors: { type: Array, required: true },
|
||||
color: { required: true }
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
rgbaColors: this.parseColors(this.colors, this.color)
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
handleSelect(index) {
|
||||
this.color.fromString(this.colors[index].value);
|
||||
this.$emit('select', this.colors[index]);
|
||||
},
|
||||
parseColors(colors, color) {
|
||||
return colors.map(value => {
|
||||
const c = new Color();
|
||||
c.enableAlpha = true;
|
||||
c.format = 'rgba';
|
||||
c.fromString(value.value);
|
||||
c.info = value;
|
||||
c.selected = c.value === color.value;
|
||||
return c;
|
||||
});
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
'$parent.currentColor'(val) {
|
||||
const color = new Color();
|
||||
color.fromString(val);
|
||||
|
||||
this.rgbaColors.forEach(item => {
|
||||
item.selected = color.compare(item);
|
||||
});
|
||||
},
|
||||
colors(newVal) {
|
||||
this.rgbaColors = this.parseColors(newVal, this.color);
|
||||
},
|
||||
color(newVal) {
|
||||
this.rgbaColors = this.parseColors(this.colors, newVal);
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
@@ -1,123 +0,0 @@
|
||||
<template>
|
||||
<div class="el-color-hue-slider" :class="{ 'is-vertical': vertical }">
|
||||
<div class="el-color-hue-slider__bar" @click="handleClick" ref="bar"></div>
|
||||
<div class="el-color-hue-slider__thumb"
|
||||
:style="{
|
||||
left: thumbLeft + 'px',
|
||||
top: thumbTop + 'px'
|
||||
}"
|
||||
ref="thumb">
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import draggable from '../draggable';
|
||||
|
||||
export default {
|
||||
name: 'el-color-hue-slider',
|
||||
|
||||
props: {
|
||||
color: {
|
||||
required: true
|
||||
},
|
||||
|
||||
vertical: Boolean
|
||||
},
|
||||
|
||||
data() {
|
||||
return {
|
||||
thumbLeft: 0,
|
||||
thumbTop: 0
|
||||
};
|
||||
},
|
||||
|
||||
computed: {
|
||||
hueValue() {
|
||||
const hue = this.color.get('hue');
|
||||
return hue;
|
||||
}
|
||||
},
|
||||
|
||||
watch: {
|
||||
hueValue() {
|
||||
this.update();
|
||||
}
|
||||
},
|
||||
|
||||
methods: {
|
||||
handleClick(event) {
|
||||
const thumb = this.$refs.thumb;
|
||||
const target = event.target;
|
||||
|
||||
if (target !== thumb) {
|
||||
this.handleDrag(event);
|
||||
}
|
||||
},
|
||||
|
||||
handleDrag(event) {
|
||||
const rect = this.$el.getBoundingClientRect();
|
||||
const { thumb } = this.$refs;
|
||||
let hue;
|
||||
|
||||
if (!this.vertical) {
|
||||
let left = event.clientX - rect.left;
|
||||
left = Math.min(left, rect.width - thumb.offsetWidth / 2);
|
||||
left = Math.max(thumb.offsetWidth / 2, left);
|
||||
|
||||
hue = Math.round((left - thumb.offsetWidth / 2) / (rect.width - thumb.offsetWidth) * 360);
|
||||
} else {
|
||||
let top = event.clientY - rect.top;
|
||||
top = Math.min(top, rect.height - thumb.offsetHeight / 2);
|
||||
top = Math.max(thumb.offsetHeight / 2, top);
|
||||
|
||||
hue = Math.round((top - thumb.offsetHeight / 2) / (rect.height - thumb.offsetHeight) * 360);
|
||||
}
|
||||
|
||||
this.color.set('hue', hue);
|
||||
},
|
||||
|
||||
getThumbLeft() {
|
||||
if (this.vertical) return 0;
|
||||
const el = this.$el;
|
||||
const hue = this.color.get('hue');
|
||||
|
||||
if (!el) return 0;
|
||||
const thumb = this.$refs.thumb;
|
||||
return Math.round(hue * (el.offsetWidth - thumb.offsetWidth / 2) / 360);
|
||||
},
|
||||
|
||||
getThumbTop() {
|
||||
if (!this.vertical) return 0;
|
||||
const el = this.$el;
|
||||
const hue = this.color.get('hue');
|
||||
|
||||
if (!el) return 0;
|
||||
const thumb = this.$refs.thumb;
|
||||
return Math.round(hue * (el.offsetHeight - thumb.offsetHeight / 2) / 360);
|
||||
},
|
||||
|
||||
update() {
|
||||
this.thumbLeft = this.getThumbLeft();
|
||||
this.thumbTop = this.getThumbTop();
|
||||
}
|
||||
},
|
||||
|
||||
mounted() {
|
||||
const { bar, thumb } = this.$refs;
|
||||
|
||||
const dragConfig = {
|
||||
drag: (event) => {
|
||||
this.handleDrag(event);
|
||||
},
|
||||
end: (event) => {
|
||||
this.handleDrag(event);
|
||||
}
|
||||
};
|
||||
|
||||
draggable(bar, dragConfig);
|
||||
draggable(thumb, dragConfig);
|
||||
this.update();
|
||||
}
|
||||
};
|
||||
</script>
|
||||
@@ -1,135 +0,0 @@
|
||||
<template>
|
||||
<transition name="el-zoom-in-top" @after-leave="doDestroy">
|
||||
<div
|
||||
class="el-color-dropdown"
|
||||
v-show="showPopper">
|
||||
<div class="el-color-dropdown__main-wrapper">
|
||||
<hue-slider ref="hue" :color="color" vertical style="float: right;"></hue-slider>
|
||||
<sv-panel ref="sl" :color="color"></sv-panel>
|
||||
</div>
|
||||
<alpha-slider v-if="showAlpha" ref="alpha" :color="color"></alpha-slider>
|
||||
<predefine v-if="predefine" :color="color" :colors="predefine"></predefine>
|
||||
<div class="el-color-dropdown__btns">
|
||||
<span class="el-color-dropdown__value">
|
||||
<el-input
|
||||
v-model="customInput"
|
||||
@keyup.native.enter="handleConfirm"
|
||||
@blur="handleConfirm"
|
||||
:validate-event="false"
|
||||
size="mini">
|
||||
</el-input>
|
||||
</span>
|
||||
<!-- <el-button
|
||||
size="mini"
|
||||
type="text"
|
||||
class="el-color-dropdown__link-btn"
|
||||
@click="$emit('clear')">
|
||||
{{ t('el.colorpicker.clear') }}
|
||||
</el-button> -->
|
||||
<el-button
|
||||
plain
|
||||
size="mini"
|
||||
type="primary"
|
||||
class="el-color-dropdown__btn"
|
||||
@click="confirmValue">
|
||||
{{ t('el.colorpicker.confirm') }}
|
||||
</el-button>
|
||||
</div>
|
||||
<color-list
|
||||
v-if="colorList && colorList.length > 0"
|
||||
:color="color"
|
||||
:colors="colorList"
|
||||
@select=onColorListSelect
|
||||
></color-list>
|
||||
</div>
|
||||
</transition>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import SvPanel from './sv-panel';
|
||||
import HueSlider from './hue-slider';
|
||||
import AlphaSlider from './alpha-slider';
|
||||
import Predefine from './predefine';
|
||||
import ColorList from './color-list';
|
||||
import Popper from 'element-ui/src/utils/vue-popper';
|
||||
import Locale from 'element-ui/src/mixins/locale';
|
||||
import ElInput from 'element-ui/packages/input';
|
||||
import ElButton from 'element-ui/packages/button';
|
||||
|
||||
export default {
|
||||
name: 'el-color-picker-dropdown',
|
||||
|
||||
mixins: [Popper, Locale],
|
||||
|
||||
components: {
|
||||
SvPanel,
|
||||
HueSlider,
|
||||
AlphaSlider,
|
||||
ElInput,
|
||||
ElButton,
|
||||
Predefine,
|
||||
ColorList
|
||||
},
|
||||
|
||||
props: {
|
||||
color: {
|
||||
required: true
|
||||
},
|
||||
showAlpha: Boolean,
|
||||
predefine: Array,
|
||||
colorList: Array
|
||||
},
|
||||
|
||||
data() {
|
||||
return {
|
||||
customInput: ''
|
||||
};
|
||||
},
|
||||
|
||||
computed: {
|
||||
currentColor() {
|
||||
const parent = this.$parent;
|
||||
return !parent.value && !parent.showPanelColor ? '' : parent.color.value;
|
||||
}
|
||||
},
|
||||
|
||||
methods: {
|
||||
confirmValue() {
|
||||
this.$emit('pick');
|
||||
},
|
||||
|
||||
onColorListSelect(e) {
|
||||
this.$emit('pick', e);
|
||||
},
|
||||
|
||||
handleConfirm() {
|
||||
this.color.fromString(this.customInput);
|
||||
}
|
||||
},
|
||||
|
||||
mounted() {
|
||||
this.$parent.popperElm = this.popperElm = this.$el;
|
||||
this.referenceElm = this.$parent.$el;
|
||||
},
|
||||
|
||||
watch: {
|
||||
showPopper(val) {
|
||||
if (val === true) {
|
||||
this.$nextTick(() => {
|
||||
const { sl, hue, alpha } = this.$refs;
|
||||
sl && sl.update();
|
||||
hue && hue.update();
|
||||
alpha && alpha.update();
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
currentColor: {
|
||||
immediate: true,
|
||||
handler(val) {
|
||||
this.customInput = val;
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
@@ -1,61 +0,0 @@
|
||||
<template>
|
||||
<div class="el-color-predefine">
|
||||
<div class="el-color-predefine__colors">
|
||||
<div class="el-color-predefine__color-selector"
|
||||
:class="{selected: item.selected, 'is-alpha': item._alpha < 100}"
|
||||
v-for="(item, index) in rgbaColors"
|
||||
:key="colors[index]"
|
||||
@click="handleSelect(index)">
|
||||
<div :style="{'background-color': item.value}">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import Color from '../color';
|
||||
|
||||
export default {
|
||||
props: {
|
||||
colors: { type: Array, required: true },
|
||||
color: { required: true }
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
rgbaColors: this.parseColors(this.colors, this.color)
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
handleSelect(index) {
|
||||
this.color.fromString(this.colors[index]);
|
||||
},
|
||||
parseColors(colors, color) {
|
||||
return colors.map(value => {
|
||||
const c = new Color();
|
||||
c.enableAlpha = true;
|
||||
c.format = 'rgba';
|
||||
c.fromString(value);
|
||||
c.selected = c.value === color.value;
|
||||
return c;
|
||||
});
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
'$parent.currentColor'(val) {
|
||||
const color = new Color();
|
||||
color.fromString(val);
|
||||
|
||||
this.rgbaColors.forEach(item => {
|
||||
item.selected = color.compare(item);
|
||||
});
|
||||
},
|
||||
colors(newVal) {
|
||||
this.rgbaColors = this.parseColors(newVal, this.color);
|
||||
},
|
||||
color(newVal) {
|
||||
this.rgbaColors = this.parseColors(this.colors, newVal);
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
@@ -1,100 +0,0 @@
|
||||
<template>
|
||||
<div class="el-color-svpanel"
|
||||
:style="{
|
||||
backgroundColor: background
|
||||
}">
|
||||
<div class="el-color-svpanel__white"></div>
|
||||
<div class="el-color-svpanel__black"></div>
|
||||
<div class="el-color-svpanel__cursor"
|
||||
:style="{
|
||||
top: cursorTop + 'px',
|
||||
left: cursorLeft + 'px'
|
||||
}">
|
||||
<div></div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import draggable from '../draggable';
|
||||
|
||||
export default {
|
||||
name: 'el-sl-panel',
|
||||
|
||||
props: {
|
||||
color: {
|
||||
required: true
|
||||
}
|
||||
},
|
||||
|
||||
computed: {
|
||||
colorValue() {
|
||||
const hue = this.color.get('hue');
|
||||
const value = this.color.get('value');
|
||||
return { hue, value };
|
||||
}
|
||||
},
|
||||
|
||||
watch: {
|
||||
colorValue() {
|
||||
this.update();
|
||||
}
|
||||
},
|
||||
|
||||
methods: {
|
||||
update() {
|
||||
const saturation = this.color.get('saturation');
|
||||
const value = this.color.get('value');
|
||||
|
||||
const el = this.$el;
|
||||
let { clientWidth: width, clientHeight: height } = el;
|
||||
|
||||
this.cursorLeft = saturation * width / 100;
|
||||
this.cursorTop = (100 - value) * height / 100;
|
||||
|
||||
this.background = 'hsl(' + this.color.get('hue') + ', 100%, 50%)';
|
||||
},
|
||||
|
||||
handleDrag(event) {
|
||||
const el = this.$el;
|
||||
const rect = el.getBoundingClientRect();
|
||||
|
||||
let left = event.clientX - rect.left;
|
||||
let top = event.clientY - rect.top;
|
||||
left = Math.max(0, left);
|
||||
left = Math.min(left, rect.width);
|
||||
|
||||
top = Math.max(0, top);
|
||||
top = Math.min(top, rect.height);
|
||||
|
||||
this.cursorLeft = left;
|
||||
this.cursorTop = top;
|
||||
this.color.set({
|
||||
saturation: left / rect.width * 100,
|
||||
value: 100 - top / rect.height * 100
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
mounted() {
|
||||
draggable(this.$el, {
|
||||
drag: (event) => {
|
||||
this.handleDrag(event);
|
||||
},
|
||||
end: (event) => {
|
||||
this.handleDrag(event);
|
||||
}
|
||||
});
|
||||
|
||||
this.update();
|
||||
},
|
||||
|
||||
data() {
|
||||
return {
|
||||
cursorTop: 0,
|
||||
cursorLeft: 0,
|
||||
background: 'hsl(0, 100%, 50%)'
|
||||
};
|
||||
}
|
||||
};
|
||||
</script>
|
||||
@@ -1,36 +0,0 @@
|
||||
import Vue from 'vue';
|
||||
let isDragging = false;
|
||||
|
||||
export default function(element, options) {
|
||||
if (Vue.prototype.$isServer) return;
|
||||
const moveFn = function(event) {
|
||||
if (options.drag) {
|
||||
options.drag(event);
|
||||
}
|
||||
};
|
||||
const upFn = function(event) {
|
||||
document.removeEventListener('mousemove', moveFn);
|
||||
document.removeEventListener('mouseup', upFn);
|
||||
document.onselectstart = null;
|
||||
document.ondragstart = null;
|
||||
|
||||
isDragging = false;
|
||||
|
||||
if (options.end) {
|
||||
options.end(event);
|
||||
}
|
||||
};
|
||||
element.addEventListener('mousedown', function(event) {
|
||||
if (isDragging) return;
|
||||
document.onselectstart = function() { return false; };
|
||||
document.ondragstart = function() { return false; };
|
||||
|
||||
document.addEventListener('mousemove', moveFn);
|
||||
document.addEventListener('mouseup', upFn);
|
||||
isDragging = true;
|
||||
|
||||
if (options.start) {
|
||||
options.start(event);
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -1,190 +0,0 @@
|
||||
<template>
|
||||
<div
|
||||
:class="[
|
||||
'el-color-picker',
|
||||
colorDisabled ? 'is-disabled' : '',
|
||||
colorSize ? `el-color-picker--${ colorSize }` : ''
|
||||
]"
|
||||
v-clickoutside="hide">
|
||||
<div class="el-color-picker__mask" v-if="colorDisabled"></div>
|
||||
<div class="el-color-picker__trigger" @click="handleTrigger">
|
||||
<span class="el-color-picker__color" :class="{ 'is-alpha': showAlpha }">
|
||||
<span class="el-color-picker__color-inner"
|
||||
:style="{
|
||||
backgroundColor: displayedColor
|
||||
}"></span>
|
||||
<span class="el-color-picker__empty el-icon-close" v-if="!value && !showPanelColor"></span>
|
||||
</span>
|
||||
<span class="el-color-picker__icon el-icon-arrow-down" v-show="value || showPanelColor"></span>
|
||||
</div>
|
||||
<picker-dropdown
|
||||
ref="dropdown"
|
||||
:class="['el-color-picker__panel', popperClass || '']"
|
||||
v-model="showPicker"
|
||||
@pick="confirmValue"
|
||||
@clear="clearValue"
|
||||
:color="color"
|
||||
:show-alpha="showAlpha"
|
||||
:predefine="predefine"
|
||||
:colorList="colorList">
|
||||
</picker-dropdown>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import Color from './color';
|
||||
import PickerDropdown from './components/picker-dropdown.vue';
|
||||
import Clickoutside from 'element-ui/src/utils/clickoutside';
|
||||
import Emitter from 'element-ui/src/mixins/emitter';
|
||||
|
||||
export default {
|
||||
name: 'ElColorPicker',
|
||||
|
||||
mixins: [Emitter],
|
||||
|
||||
props: {
|
||||
value: String,
|
||||
showAlpha: Boolean,
|
||||
colorFormat: String,
|
||||
disabled: Boolean,
|
||||
size: String,
|
||||
popperClass: String,
|
||||
predefine: Array,
|
||||
colorList: Array
|
||||
},
|
||||
|
||||
inject: {
|
||||
elForm: {
|
||||
default: ''
|
||||
},
|
||||
elFormItem: {
|
||||
default: ''
|
||||
}
|
||||
},
|
||||
|
||||
directives: { Clickoutside },
|
||||
|
||||
computed: {
|
||||
displayedColor() {
|
||||
if (!this.value && !this.showPanelColor) {
|
||||
return 'transparent';
|
||||
}
|
||||
|
||||
return this.displayedRgb(this.color, this.showAlpha);
|
||||
},
|
||||
|
||||
_elFormItemSize() {
|
||||
return (this.elFormItem || {}).elFormItemSize;
|
||||
},
|
||||
|
||||
colorSize() {
|
||||
return this.size || this._elFormItemSize || (this.$ELEMENT || {}).size;
|
||||
},
|
||||
|
||||
colorDisabled() {
|
||||
return this.disabled || (this.elForm || {}).disabled;
|
||||
}
|
||||
},
|
||||
|
||||
watch: {
|
||||
value(val) {
|
||||
if (!val) {
|
||||
this.showPanelColor = false;
|
||||
} else if (val && val !== this.color.value) {
|
||||
this.color.fromString(val);
|
||||
}
|
||||
},
|
||||
color: {
|
||||
deep: true,
|
||||
handler() {
|
||||
this.showPanelColor = true;
|
||||
}
|
||||
},
|
||||
displayedColor(val) {
|
||||
if (!this.showPicker) return;
|
||||
const currentValueColor = new Color({
|
||||
enableAlpha: this.showAlpha,
|
||||
format: this.colorFormat
|
||||
});
|
||||
currentValueColor.fromString(this.value);
|
||||
|
||||
const currentValueColorRgb = this.displayedRgb(currentValueColor, this.showAlpha);
|
||||
if (val !== currentValueColorRgb) {
|
||||
this.$emit('active-change', val);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
methods: {
|
||||
handleTrigger() {
|
||||
if (this.colorDisabled) return;
|
||||
this.showPicker = !this.showPicker;
|
||||
},
|
||||
confirmValue(selection) {
|
||||
const value = selection || this.color.value;
|
||||
this.$emit('input', value);
|
||||
this.$emit('change', value);
|
||||
this.dispatch('ElFormItem', 'el.form.change', value);
|
||||
this.showPicker = false;
|
||||
},
|
||||
clearValue() {
|
||||
this.$emit('input', null);
|
||||
this.$emit('change', null);
|
||||
if (this.value !== null) {
|
||||
this.dispatch('ElFormItem', 'el.form.change', null);
|
||||
}
|
||||
this.showPanelColor = false;
|
||||
this.showPicker = false;
|
||||
this.resetColor();
|
||||
},
|
||||
hide() {
|
||||
this.showPicker = false;
|
||||
this.resetColor();
|
||||
},
|
||||
resetColor() {
|
||||
this.$nextTick(_ => {
|
||||
if (this.value) {
|
||||
this.color.fromString(this.value);
|
||||
} else {
|
||||
this.showPanelColor = false;
|
||||
}
|
||||
});
|
||||
},
|
||||
displayedRgb(color, showAlpha) {
|
||||
if (!(color instanceof Color)) {
|
||||
throw Error('color should be instance of Color Class');
|
||||
}
|
||||
|
||||
const { r, g, b } = color.toRgb();
|
||||
return showAlpha
|
||||
? `rgba(${ r }, ${ g }, ${ b }, ${ color.get('alpha') / 100 })`
|
||||
: `rgb(${ r }, ${ g }, ${ b })`;
|
||||
}
|
||||
},
|
||||
|
||||
mounted() {
|
||||
const value = this.value;
|
||||
if (value) {
|
||||
this.color.fromString(value);
|
||||
}
|
||||
this.popperElm = this.$refs.dropdown.$el;
|
||||
},
|
||||
|
||||
data() {
|
||||
const color = new Color({
|
||||
enableAlpha: this.showAlpha,
|
||||
format: this.colorFormat
|
||||
});
|
||||
|
||||
return {
|
||||
color,
|
||||
showPicker: false,
|
||||
showPanelColor: false
|
||||
};
|
||||
},
|
||||
|
||||
components: {
|
||||
PickerDropdown
|
||||
}
|
||||
};
|
||||
</script>
|
||||
@@ -1,93 +0,0 @@
|
||||
<template>
|
||||
<section class="config" :key="displayName">
|
||||
<div class="config-label">
|
||||
<el-tooltip :content="displayName" placement="top">
|
||||
<span>{{displayKeyName}}</span>
|
||||
</el-tooltip>
|
||||
</div>
|
||||
<div class="config-content">
|
||||
<div class="content-80">
|
||||
<el-input
|
||||
size="medium"
|
||||
:value=displayValue
|
||||
readonly
|
||||
slot="reference"
|
||||
@click.native="onInputClick"
|
||||
></el-input>
|
||||
</div>
|
||||
<div class="content-20">
|
||||
<color-picker
|
||||
size="medium"
|
||||
ref="colorPicker"
|
||||
class="colorPicker"
|
||||
v-model="pickerColor"
|
||||
@change=onPickerChange
|
||||
:colorList="golbalColorList"
|
||||
></color-picker>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
</template>
|
||||
|
||||
<style>
|
||||
input {
|
||||
cursor: pointer;
|
||||
}
|
||||
.colorPicker {
|
||||
margin-left: 10px;
|
||||
vertical-align: bottom;
|
||||
}
|
||||
</style>
|
||||
|
||||
<script>
|
||||
import Mixin from './mixin';
|
||||
import { getStyleDisplayValue, getStyleDisplayName } from '../utils/utils.js';
|
||||
import ColorPicker from './color-picker';
|
||||
|
||||
export default {
|
||||
components: {
|
||||
ColorPicker
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
pickerColor: ''
|
||||
};
|
||||
},
|
||||
mixins: [Mixin],
|
||||
watch: {
|
||||
displayValue: {
|
||||
immediate: true,
|
||||
handler(value) {
|
||||
if (value.startsWith('#')) {
|
||||
this.pickerColor = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
golbalColor() {
|
||||
return this.golbalValue.color;
|
||||
},
|
||||
displayValue() {
|
||||
return getStyleDisplayValue(this.mergedValue, this.golbalColor);
|
||||
},
|
||||
golbalColorList() {
|
||||
return this.isGlobal ? [] : Object.keys(this.golbalColor).map((c) => (
|
||||
{
|
||||
label: getStyleDisplayName(this.golbalColor[c]),
|
||||
value: this.golbalColor[c].value,
|
||||
variable: c
|
||||
}
|
||||
));
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
onInputClick() {
|
||||
this.$refs.colorPicker && this.$refs.colorPicker.handleTrigger();
|
||||
},
|
||||
onPickerChange(e) {
|
||||
this.onChange(e.variable || e);
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
@@ -1,104 +0,0 @@
|
||||
<template>
|
||||
<section class="config" :key="displayName">
|
||||
<div class="config-label">
|
||||
<el-tooltip :content="displayName" placement="top">
|
||||
<span>{{displayKeyName}}</span>
|
||||
</el-tooltip>
|
||||
</div>
|
||||
<div class="config-content">
|
||||
<el-select
|
||||
v-model="value"
|
||||
class="select"
|
||||
size="medium"
|
||||
@change="onSelectChange"
|
||||
>
|
||||
<el-option
|
||||
v-for="item in options"
|
||||
:key="item.value"
|
||||
:label="item.label"
|
||||
:value="item.value">
|
||||
</el-option>
|
||||
</el-select>
|
||||
</div>
|
||||
</section>
|
||||
</template>
|
||||
|
||||
<style>
|
||||
.select {
|
||||
width: 100%;
|
||||
}
|
||||
</style>
|
||||
|
||||
<script>
|
||||
const defaultFontLineHeight = [
|
||||
'1',
|
||||
'1.3',
|
||||
'1.5',
|
||||
'1.7',
|
||||
'12px',
|
||||
'16px',
|
||||
'20px',
|
||||
'24px',
|
||||
'28px'
|
||||
];
|
||||
import Mixin from './mixin';
|
||||
import { getStyleDisplayName } from '../utils/utils.js';
|
||||
|
||||
export default {
|
||||
props: {
|
||||
componentName: {
|
||||
type: String
|
||||
},
|
||||
golbalValue: {
|
||||
type: Object
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
options: [],
|
||||
value: ''
|
||||
};
|
||||
},
|
||||
mixins: [Mixin],
|
||||
computed: {
|
||||
isGlobalInputValue() {
|
||||
return this.config.value.startsWith('$');
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
onSelectChange(e) {
|
||||
this.onChange(e);
|
||||
},
|
||||
initSelectOption() {
|
||||
this.options = [];
|
||||
defaultFontLineHeight.forEach((size) => {
|
||||
this.options.push({
|
||||
value: size,
|
||||
label: size
|
||||
});
|
||||
});
|
||||
const golbalTypography = this.golbalValue.typography;
|
||||
if (this.isGlobalInputValue && golbalTypography) {
|
||||
Object.keys(golbalTypography).forEach((font) => {
|
||||
if (font.includes('font-line-height')) {
|
||||
const size = golbalTypography[font];
|
||||
this.options.push({
|
||||
value: size.key,
|
||||
label: getStyleDisplayName(size)
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
'mergedValue': {
|
||||
immediate: true,
|
||||
handler(value) {
|
||||
this.initSelectOption();
|
||||
this.value = this.mergedValue;
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
@@ -1,105 +0,0 @@
|
||||
<template>
|
||||
<section class="config" :key="displayName">
|
||||
<div class="config-label">
|
||||
<el-tooltip :content="displayName" placement="top">
|
||||
<span>{{displayKeyName}}</span>
|
||||
</el-tooltip>
|
||||
</div>
|
||||
<div class="config-content">
|
||||
<el-select
|
||||
v-model="value"
|
||||
class="select"
|
||||
size="medium"
|
||||
@change="onSelectChange"
|
||||
>
|
||||
<el-option
|
||||
v-for="item in options"
|
||||
:key="item.value"
|
||||
:label="item.label"
|
||||
:value="item.value">
|
||||
</el-option>
|
||||
</el-select>
|
||||
</div>
|
||||
</section>
|
||||
</template>
|
||||
|
||||
<style>
|
||||
.select {
|
||||
width: 100%;
|
||||
}
|
||||
</style>
|
||||
|
||||
<script>
|
||||
const defaultFontSize = [
|
||||
'12px',
|
||||
'13px',
|
||||
'14px',
|
||||
'16px',
|
||||
'18px',
|
||||
'20px',
|
||||
'22px',
|
||||
'28px',
|
||||
'36px',
|
||||
'48px'
|
||||
];
|
||||
import Mixin from './mixin';
|
||||
import { getStyleDisplayName } from '../utils/utils.js';
|
||||
|
||||
export default {
|
||||
props: {
|
||||
componentName: {
|
||||
type: String
|
||||
},
|
||||
golbalValue: {
|
||||
type: Object
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
options: [],
|
||||
value: ''
|
||||
};
|
||||
},
|
||||
mixins: [Mixin],
|
||||
computed: {
|
||||
isGlobalInputValue() {
|
||||
return this.config.value.startsWith('$');
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
onSelectChange(e) {
|
||||
this.onChange(e);
|
||||
},
|
||||
initSelectOption() {
|
||||
this.options = [];
|
||||
defaultFontSize.forEach((size) => {
|
||||
this.options.push({
|
||||
value: size,
|
||||
label: size
|
||||
});
|
||||
});
|
||||
const golbalTypography = this.golbalValue.typography;
|
||||
if (this.isGlobalInputValue && golbalTypography) {
|
||||
Object.keys(golbalTypography).forEach((font) => {
|
||||
if (font.includes('font-size')) {
|
||||
const size = golbalTypography[font];
|
||||
this.options.push({
|
||||
value: size.key,
|
||||
label: getStyleDisplayName(size)
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
'mergedValue': {
|
||||
immediate: true,
|
||||
handler(value) {
|
||||
this.initSelectOption();
|
||||
this.value = this.mergedValue;
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
@@ -1,109 +0,0 @@
|
||||
<template>
|
||||
<section class="config" :key="displayName">
|
||||
<div class="config-label">
|
||||
<el-tooltip :content="displayName" placement="top">
|
||||
<span>{{displayKeyName}}</span>
|
||||
</el-tooltip>
|
||||
</div>
|
||||
<div class="config-content">
|
||||
<el-select
|
||||
v-model="value"
|
||||
class="select"
|
||||
size="medium"
|
||||
@change="onSelectChange"
|
||||
>
|
||||
<el-option
|
||||
v-for="item in options"
|
||||
:key="item.value"
|
||||
:label="item.label"
|
||||
:value="item.value">
|
||||
</el-option>
|
||||
</el-select>
|
||||
</div>
|
||||
</section>
|
||||
</template>
|
||||
|
||||
<style>
|
||||
.select {
|
||||
width: 100%;
|
||||
}
|
||||
</style>
|
||||
|
||||
<script>
|
||||
const defaultFontWeight = [
|
||||
'normal',
|
||||
'bold',
|
||||
'bolder',
|
||||
'lighter',
|
||||
'100',
|
||||
'200',
|
||||
'300',
|
||||
'400',
|
||||
'500',
|
||||
'600',
|
||||
'700',
|
||||
'800',
|
||||
'900',
|
||||
'inherit'
|
||||
];
|
||||
import Mixin from './mixin';
|
||||
import { getStyleDisplayName } from '../utils/utils.js';
|
||||
|
||||
export default {
|
||||
props: {
|
||||
componentName: {
|
||||
type: String
|
||||
},
|
||||
golbalValue: {
|
||||
type: Object
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
options: [],
|
||||
value: ''
|
||||
};
|
||||
},
|
||||
mixins: [Mixin],
|
||||
computed: {
|
||||
isGlobalInputValue() {
|
||||
return this.config.value.startsWith('$');
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
onSelectChange(e) {
|
||||
this.onChange(e);
|
||||
},
|
||||
initSelectOption() {
|
||||
this.options = [];
|
||||
defaultFontWeight.forEach((weight) => {
|
||||
this.options.push({
|
||||
value: weight,
|
||||
label: weight
|
||||
});
|
||||
});
|
||||
const golbalTypography = this.golbalValue.typography;
|
||||
if (this.isGlobalInputValue && golbalTypography) {
|
||||
Object.keys(golbalTypography).forEach((font) => {
|
||||
if (font.includes('font-weight')) {
|
||||
const weight = golbalTypography[font];
|
||||
this.options.push({
|
||||
value: weight.key,
|
||||
label: getStyleDisplayName(weight)
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
'mergedValue': {
|
||||
immediate: true,
|
||||
handler(value) {
|
||||
this.initSelectOption();
|
||||
this.value = this.mergedValue;
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
@@ -1,45 +0,0 @@
|
||||
<template>
|
||||
<el-input
|
||||
@keyup.enter.native="onUpdate"
|
||||
v-model="value"
|
||||
@blur="onUpdate"
|
||||
v-bind="$attrs"
|
||||
>
|
||||
<template slot="suffix">
|
||||
<slot name="suffix"></slot>
|
||||
</template>
|
||||
</el-input>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
|
||||
export default {
|
||||
props: ['val', 'onChange'],
|
||||
data() {
|
||||
return {
|
||||
value: '',
|
||||
oldValue: ''
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
onUpdate(e) {
|
||||
const { value } = e.target;
|
||||
if (value !== this.oldValue) {
|
||||
this.oldValue = value;
|
||||
this.$emit('change', value);
|
||||
}
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
val: {
|
||||
immediate: true,
|
||||
handler(value) {
|
||||
this.value = value;
|
||||
if (!this.oldValue) {
|
||||
this.oldValue = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
@@ -1,81 +0,0 @@
|
||||
<style>
|
||||
.config {
|
||||
padding: 5px 0;
|
||||
}
|
||||
.config-label {
|
||||
color: #606266;;
|
||||
font-size: 14px;
|
||||
padding-bottom: 8px;
|
||||
position: relative;
|
||||
}
|
||||
.config-content {
|
||||
|
||||
}
|
||||
.content-80 {
|
||||
box-sizing: border-box;
|
||||
display: inline-block;
|
||||
width: 80%;
|
||||
}
|
||||
.content-20 {
|
||||
box-sizing: border-box;
|
||||
display: inline-block;
|
||||
width: 20%;
|
||||
vertical-align: bottom;
|
||||
}
|
||||
.content-10 {
|
||||
box-sizing: border-box;
|
||||
display: inline-block;
|
||||
width: 10%;
|
||||
vertical-align: bottom;
|
||||
}
|
||||
.content-15 {
|
||||
box-sizing: border-box;
|
||||
display: inline-block;
|
||||
width: 15%;
|
||||
vertical-align: bottom;
|
||||
}
|
||||
</style>
|
||||
<script>
|
||||
import { getStyleDisplayName } from '../utils/utils.js';
|
||||
export default {
|
||||
props: {
|
||||
config: {
|
||||
type: Object
|
||||
},
|
||||
userConfig: {
|
||||
type: Object
|
||||
},
|
||||
golbalValue: {
|
||||
type: Object
|
||||
},
|
||||
componentName: {
|
||||
type: String
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
mergedValue() {
|
||||
return this.userConfig[this.config.key] || this.config.value;
|
||||
},
|
||||
displayName() {
|
||||
return getStyleDisplayName(this.config, this.componentName);
|
||||
},
|
||||
displayKeyName() {
|
||||
if (this.config.name) {
|
||||
return this.config.key.replace('$--', '');
|
||||
}
|
||||
return this.config.key.replace(`$--${this.componentName}-`, '');
|
||||
},
|
||||
isGlobal() {
|
||||
return !this.config.value.startsWith('$');
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
onChange(value) {
|
||||
this.$emit('onChange', {
|
||||
key: this.config.key,
|
||||
value
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
@@ -1,41 +0,0 @@
|
||||
<template>
|
||||
<section class="config" :key="displayName">
|
||||
<div class="config-label">
|
||||
<el-tooltip :content="displayName" placement="top">
|
||||
<span>{{displayKeyName}}</span>
|
||||
</el-tooltip>
|
||||
</div>
|
||||
<div class="config-content">
|
||||
<theme-input
|
||||
:val="value"
|
||||
size="medium"
|
||||
@change="onChange"
|
||||
></theme-input>
|
||||
</div>
|
||||
</section>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import Input from './input';
|
||||
import Mixin from './mixin';
|
||||
|
||||
export default {
|
||||
components: {
|
||||
themeInput: Input
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
value: ''
|
||||
};
|
||||
},
|
||||
mixins: [Mixin],
|
||||
watch: {
|
||||
'mergedValue': {
|
||||
immediate: true,
|
||||
handler(value) {
|
||||
this.value = this.mergedValue;
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
@@ -1,195 +0,0 @@
|
||||
<template>
|
||||
<div class="main-configurator" ref='configurator'>
|
||||
<action-panel
|
||||
:selectOptions="selectOptions"
|
||||
:userConfigHistory="userConfigHistory"
|
||||
:userConfigRedoHistory="userConfigRedoHistory"
|
||||
:onUndo="undo"
|
||||
:onRedo="redo"
|
||||
:isOfficial="isOfficial"
|
||||
@select="onSelectChange"
|
||||
></action-panel>
|
||||
<main-panel
|
||||
v-if="defaultConfig"
|
||||
:currentConfig="currentConfig"
|
||||
:defaultConfig="defaultConfig"
|
||||
:userConfig="userConfig"
|
||||
:globalValue="globalValue"
|
||||
@onChange="userConfigChange"
|
||||
></main-panel>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style lang="scss">
|
||||
.main-configurator {
|
||||
height: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
</style>
|
||||
|
||||
<script>
|
||||
import bus from '../../bus.js';
|
||||
import { getVars } from '../theme/loader/api.js';
|
||||
import mainPanel from './main';
|
||||
import actionPanel from './action';
|
||||
import {
|
||||
filterConfigType,
|
||||
filterGlobalValue,
|
||||
getActionDisplayName
|
||||
} from './utils/utils.js';
|
||||
import Shortcut from './shortcut';
|
||||
import {
|
||||
ACTION_APPLY_THEME,
|
||||
ACTION_DOWNLOAD_THEME,
|
||||
ACTION_COMPONECT_SELECT
|
||||
} from '../theme/constant.js';
|
||||
|
||||
export default {
|
||||
props: {
|
||||
themeConfig: Object,
|
||||
previewConfig: Object,
|
||||
isOfficial: Boolean,
|
||||
onUserConfigUpdate: Function
|
||||
},
|
||||
components: {
|
||||
mainPanel,
|
||||
actionPanel
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
init: false,
|
||||
defaultConfig: null,
|
||||
currentConfig: null,
|
||||
userConfig: {
|
||||
global: {},
|
||||
local: {}
|
||||
},
|
||||
userConfigHistory: [],
|
||||
userConfigRedoHistory: [],
|
||||
hasLocalConfig: false,
|
||||
selectOptions: [],
|
||||
selectedComponent: 'color'
|
||||
};
|
||||
},
|
||||
mixins: [Shortcut],
|
||||
computed: {
|
||||
globalValue() {
|
||||
return filterGlobalValue(this.defaultConfig, this.userConfig);
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
ga('send', 'event', 'ThemeConfigurator', 'Init');
|
||||
this.showConfigurator();
|
||||
this.enableShortcut();
|
||||
},
|
||||
beforeDestroy() {
|
||||
this.disableShortcut();
|
||||
},
|
||||
methods: {
|
||||
getActionDisplayName(key) {
|
||||
return getActionDisplayName(key);
|
||||
},
|
||||
showConfigurator() {
|
||||
if (this.init) return;
|
||||
this.$nextTick(() => {
|
||||
const loading = this.$loading({
|
||||
target: this.$refs.configurator
|
||||
});
|
||||
let defaultConfig;
|
||||
getVars()
|
||||
.then(res => {
|
||||
defaultConfig = res;
|
||||
})
|
||||
.catch(err => {
|
||||
this.onError && this.onError(err);
|
||||
})
|
||||
.then(() => {
|
||||
setTimeout(() => {
|
||||
if (defaultConfig) {
|
||||
this.defaultConfig = defaultConfig;
|
||||
this.setSelectOption();
|
||||
this.filterCurrentConfig();
|
||||
this.init = true;
|
||||
}
|
||||
loading.close();
|
||||
}, 300); // action after transition
|
||||
});
|
||||
});
|
||||
},
|
||||
setSelectOption() {
|
||||
this.selectOptions = this.defaultConfig.map((config) => ({
|
||||
label: config.name.charAt(0).toUpperCase() + config.name.slice(1),
|
||||
value: config.name
|
||||
})).sort((a, b) => {
|
||||
const A = a.label;
|
||||
const B = b.label;
|
||||
if (A < B) return -1;
|
||||
if (A > B) return 1;
|
||||
return 0;
|
||||
});
|
||||
},
|
||||
filterCurrentConfig() {
|
||||
this.currentConfig = this.defaultConfig.find(config => {
|
||||
return (
|
||||
config.name === this.selectedComponent
|
||||
);
|
||||
});
|
||||
},
|
||||
userConfigChange(e) {
|
||||
this.userConfigHistory.push(JSON.stringify(this.userConfig));
|
||||
this.userConfigRedoHistory = [];
|
||||
this.$set(
|
||||
this.userConfig[filterConfigType(this.currentConfig.name)],
|
||||
e.key,
|
||||
e.value
|
||||
);
|
||||
this.onAction();
|
||||
},
|
||||
onReset() {
|
||||
this.userConfigRedoHistory = [];
|
||||
this.userConfigHistory = [];
|
||||
this.userConfig = {
|
||||
global: {},
|
||||
local: {}
|
||||
};
|
||||
this.onAction();
|
||||
},
|
||||
onDownload() {
|
||||
bus.$emit(ACTION_DOWNLOAD_THEME, this.userConfig, this.previewConfig.name);
|
||||
},
|
||||
onAction() {
|
||||
this.onUserConfigUpdate(this.userConfig);
|
||||
bus.$emit(ACTION_APPLY_THEME, this.userConfig);
|
||||
},
|
||||
undo() {
|
||||
if (this.userConfigHistory.length > 0) {
|
||||
this.userConfigRedoHistory.push(JSON.stringify(this.userConfig));
|
||||
this.userConfig = JSON.parse(this.userConfigHistory.pop());
|
||||
this.onAction();
|
||||
}
|
||||
},
|
||||
redo() {
|
||||
if (this.userConfigRedoHistory.length > 0) {
|
||||
this.userConfigHistory.push(JSON.stringify(this.userConfig));
|
||||
this.userConfig = JSON.parse(this.userConfigRedoHistory.shift());
|
||||
this.onAction();
|
||||
}
|
||||
},
|
||||
onSelectChange(val) {
|
||||
bus.$emit(ACTION_COMPONECT_SELECT, val);
|
||||
this.selectedComponent = val;
|
||||
this.filterCurrentConfig();
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
themeConfig: {
|
||||
handler(val, oldVal) {
|
||||
if (!oldVal.globnal) {
|
||||
this.userConfig = val;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
@@ -1,130 +0,0 @@
|
||||
<template>
|
||||
<div class="editor-main" ref="mainPanel">
|
||||
<!-- <span>{{configName}}</span> -->
|
||||
<div v-for="(config, key) in configByOrder" :key="key">
|
||||
<span
|
||||
v-if="showCategory(config.category, key + 1)"
|
||||
class="category-name"
|
||||
>
|
||||
{{config.category}}
|
||||
</span>
|
||||
<component
|
||||
:is="editorComponent(config.type)"
|
||||
:componentName=configName
|
||||
:config=config
|
||||
:userConfig=userConfigByType
|
||||
:golbalValue=globalValue
|
||||
@onChange=onChange
|
||||
>
|
||||
</component>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style>
|
||||
.editor-main {
|
||||
padding: 0 18px 15px;
|
||||
overflow-y: auto;
|
||||
}
|
||||
.category-name {
|
||||
color: #C0C4CC;
|
||||
font-size: 18px;
|
||||
display: block;
|
||||
margin: 13px 0 3px 0;
|
||||
}
|
||||
</style>
|
||||
|
||||
<script>
|
||||
import ColorEditor from './editor/color';
|
||||
import fontWeightEditor from './editor/fontWeight';
|
||||
import fontSizeEditor from './editor/fontSize';
|
||||
import fontLineHeightEditor from './editor/fontLineHeight';
|
||||
import borderRadiusEditor from './editor/borderRadius';
|
||||
import boxShadowEditor from './editor/boxShadow';
|
||||
import simpleTextEditor from './editor/simpleText';
|
||||
import { filterConfigType } from './utils/utils.js';
|
||||
|
||||
export default {
|
||||
components: {
|
||||
ColorEditor,
|
||||
fontSizeEditor,
|
||||
fontLineHeightEditor,
|
||||
simpleTextEditor,
|
||||
borderRadiusEditor,
|
||||
boxShadowEditor,
|
||||
fontWeightEditor
|
||||
},
|
||||
props: {
|
||||
defaultConfig: {
|
||||
type: Array
|
||||
},
|
||||
currentConfig: {
|
||||
type: Object
|
||||
},
|
||||
userConfig: {
|
||||
type: Object
|
||||
},
|
||||
globalValue: {
|
||||
type: Object
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
configName() {
|
||||
return this.currentConfig.name;
|
||||
},
|
||||
userConfigByType() {
|
||||
return this.userConfig[filterConfigType(this.configName)];
|
||||
},
|
||||
configByOrder() {
|
||||
return this.currentConfig.config.sort((a, b) => (a.order - b.order));
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
editorComponent(type) {
|
||||
switch (type) {
|
||||
case 'color':
|
||||
return ColorEditor;
|
||||
case 'fontWeight':
|
||||
return fontWeightEditor;
|
||||
case 'fontSize':
|
||||
return fontSizeEditor;
|
||||
case 'fontLineHeight':
|
||||
return fontLineHeightEditor;
|
||||
case 'borderRadius':
|
||||
return borderRadiusEditor;
|
||||
case 'boxShadow':
|
||||
return boxShadowEditor;
|
||||
default:
|
||||
return simpleTextEditor;
|
||||
}
|
||||
},
|
||||
onChange(e) {
|
||||
this.$emit('onChange', e);
|
||||
},
|
||||
showCategory(name, key) {
|
||||
if (!name) {
|
||||
return false;
|
||||
}
|
||||
if (!this.categoryDisplay[name] || this.categoryDisplay[name] === key) {
|
||||
this.categoryDisplay[name] = key;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
categoryDisplay: {}
|
||||
};
|
||||
},
|
||||
watch: {
|
||||
currentConfig: {
|
||||
handler() {
|
||||
this.$nextTick(() => {
|
||||
this.$refs.mainPanel.scrollTo(0, 0);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
@@ -1,27 +0,0 @@
|
||||
|
||||
<script>
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
downloading: false
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
shortcut(e) {
|
||||
if (e.keyCode === 90 && (e.ctrlKey || e.metaKey)) {
|
||||
if (e.shiftKey) {
|
||||
this.redo();
|
||||
} else {
|
||||
this.undo();
|
||||
}
|
||||
}
|
||||
},
|
||||
enableShortcut() {
|
||||
document.addEventListener('keydown', this.shortcut);
|
||||
},
|
||||
disableShortcut() {
|
||||
document.removeEventListener('keydown', this.shortcut);
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
@@ -1,59 +0,0 @@
|
||||
const VALUES_REG = /,(?![^\(]*\))/;
|
||||
const PARTS_REG = /\s(?![^(]*\))/;
|
||||
const LENGTH_REG = /^[0-9]+[a-zA-Z%]+?$/;
|
||||
|
||||
const parseValue = str => {
|
||||
const parts = str.split(PARTS_REG);
|
||||
const inset = parts.includes('inset');
|
||||
const last = parts.slice(-1)[0];
|
||||
const color = !isLength(last) ? last : undefined;
|
||||
|
||||
const nums = parts
|
||||
.filter(n => n !== 'inset')
|
||||
.filter(n => n !== color)
|
||||
.map(toNum);
|
||||
const [ offsetX, offsetY, blurRadius, spreadRadius ] = nums;
|
||||
|
||||
return {
|
||||
inset,
|
||||
offsetX,
|
||||
offsetY,
|
||||
blurRadius,
|
||||
spreadRadius,
|
||||
color
|
||||
};
|
||||
};
|
||||
|
||||
const stringifyValue = obj => {
|
||||
const {
|
||||
inset,
|
||||
offsetX = 0,
|
||||
offsetY = 0,
|
||||
blurRadius = 0,
|
||||
spreadRadius,
|
||||
color
|
||||
} = obj || {};
|
||||
|
||||
return [
|
||||
(inset ? 'inset' : null),
|
||||
offsetX,
|
||||
offsetY,
|
||||
blurRadius,
|
||||
spreadRadius,
|
||||
color
|
||||
].filter(v => v !== null && v !== undefined)
|
||||
.map(toPx)
|
||||
.map(s => ('' + s).trim())
|
||||
.join(' ');
|
||||
};
|
||||
|
||||
const isLength = v => v === '0' || LENGTH_REG.test(v);
|
||||
const toNum = v => {
|
||||
if (!/px$/.test(v) && v !== '0') return v;
|
||||
const n = parseFloat(v);
|
||||
return !isNaN(n) ? n : v;
|
||||
};
|
||||
const toPx = n => typeof n === 'number' && n !== 0 ? (n + 'px') : n;
|
||||
|
||||
export const parse = str => str.split(VALUES_REG).map(s => s.trim()).map(parseValue);
|
||||
export const stringify = arr => arr.map(stringifyValue).join(', ');
|
||||
@@ -1,68 +0,0 @@
|
||||
import deepmerge from 'deepmerge';
|
||||
import constant from '../../../i18n/theme-editor.json';
|
||||
|
||||
export const filterConfigType = (name) => {
|
||||
switch (name) {
|
||||
case 'color':
|
||||
case 'typography':
|
||||
case 'border':
|
||||
return 'global';
|
||||
default:
|
||||
return 'local';
|
||||
}
|
||||
};
|
||||
|
||||
export const filterGlobalValue = (defaultConfig, userConfig) => {
|
||||
const valueObject = {};
|
||||
const globalArr = ['color', 'typography', 'border'];
|
||||
globalArr.forEach((global) => {
|
||||
const configObj = {};
|
||||
defaultConfig
|
||||
.find(config => (config.name === global))
|
||||
.config.forEach(c => (configObj[c.key] = deepmerge({}, c)));
|
||||
valueObject[global] = configObj;
|
||||
Object.keys(configObj).forEach((c) => {
|
||||
if (userConfig.global[c]) {
|
||||
configObj[c].value = userConfig.global[c];
|
||||
}
|
||||
});
|
||||
});
|
||||
return valueObject;
|
||||
};
|
||||
|
||||
export const getStyleDisplayValue = (displayValue, global) => {
|
||||
if (displayValue.startsWith('$')) {
|
||||
return global[displayValue].value;
|
||||
}
|
||||
return displayValue;
|
||||
};
|
||||
|
||||
const getLang = () => {
|
||||
return location.hash.replace('#', '').split('/')[1] || 'zh-CN';
|
||||
};
|
||||
|
||||
const getNameFromI18N = (name) => {
|
||||
const lang = getLang();
|
||||
return constant.filter(config => config.lang === lang)[0][name];
|
||||
};
|
||||
|
||||
export const getVariableDisplayName = (key) => {
|
||||
return getNameFromI18N('variable-name')[key] || key;
|
||||
};
|
||||
|
||||
export const getStyleDisplayName = (config, componentName) => {
|
||||
const displayNameMap = getNameFromI18N('display-name');
|
||||
if (config.name) {
|
||||
return getVariableDisplayName(config.key.replace('$--', ''));
|
||||
}
|
||||
let displayName = config.key.replace(`$--${componentName}-`, '');
|
||||
Object.keys(displayNameMap).forEach((name) => {
|
||||
displayName = displayName.replace(name, displayNameMap[name]);
|
||||
});
|
||||
displayName = displayName.replace(/-/g, ' ');
|
||||
return displayName.trim();
|
||||
};
|
||||
|
||||
export const getActionDisplayName = (key) => {
|
||||
return getNameFromI18N('action')[key] || key;
|
||||
};
|
||||
@@ -5,11 +5,11 @@
|
||||
v-model="theme"></el-color-picker>
|
||||
</template>
|
||||
|
||||
<style lang="scss">
|
||||
<style>
|
||||
.theme-picker {
|
||||
height: 80px;
|
||||
display: inline-block;
|
||||
// @utils-vertical-center;
|
||||
@utils-vertical-center;
|
||||
}
|
||||
|
||||
.theme-picker .el-color-picker__trigger {
|
||||
|
||||