feat: 主题编辑器渲染器开源 (#8820)

* feat: 主题编辑器渲染器开源

* 笔误

* 优化发布脚本

* 优化发布脚本

* 删除无用代码

* bugfix

* bugfix

* bugfix

* bugfix

---------

Co-authored-by: qinhaoyan <30946345+qinhaoyan@users.noreply.github.com>
This commit is contained in:
qkiroc 2023-11-23 19:57:10 +08:00 committed by GitHub
parent af68cce8d3
commit 76c2d1354c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
76 changed files with 18044 additions and 39 deletions

3
.gitignore vendored
View File

@ -14,6 +14,8 @@ _site
node_modules node_modules
/dist /dist
/lib /lib
**/esm
**/lib
/sdk /sdk
/public /public
/gh-pages /gh-pages
@ -26,6 +28,7 @@ node_modules
/npm /npm
/mock/cfc/cfc.zip /mock/cfc/cfc.zip
.rollup.cache .rollup.cache
/theme-npm
dist dist
tsconfig.tsbuildinfo tsconfig.tsbuildinfo

View File

@ -6,7 +6,8 @@
"packages/amis-ui", "packages/amis-ui",
"packages/amis", "packages/amis",
"packages/amis-editor-core", "packages/amis-editor-core",
"packages/amis-editor" "packages/amis-editor",
"packages/amis-theme-editor-helper"
], ],
"scripts": { "scripts": {
"fis3-serve": "fis3 server start --www ./public --port 8888 --no-daemon --no-browse", "fis3-serve": "fis3 server start --www ./public --port 8888 --no-daemon --no-browse",
@ -86,7 +87,7 @@
"magic-string": "^0.26.7", "magic-string": "^0.26.7",
"marked": "^4.2.1", "marked": "^4.2.1",
"monaco-editor": "0.30.1", "monaco-editor": "0.30.1",
"plugin-react-i18n": "1.0.1", "plugin-react-i18n": "1.0.4",
"postcss-scss": "^4.0.6", "postcss-scss": "^4.0.6",
"prismjs": "^1.29.0", "prismjs": "^1.29.0",
"react": "^18.2.0", "react": "^18.2.0",

View File

@ -47,6 +47,7 @@
"static" "static"
], ],
"dependencies": { "dependencies": {
"amis-theme-editor-helper": "*",
"axios": "0.21.1", "axios": "0.21.1",
"deep-diff": "1.0.2", "deep-diff": "1.0.2",
"json-ast-comments": "^1.1.0", "json-ast-comments": "^1.1.0",

View File

@ -10,5 +10,5 @@
] ]
}, },
"include": ["src/**/*"], "include": ["src/**/*"],
"references": [{"path": "../amis"}] "references": [{"path": "../amis"}, {"path": "../amis-theme-editor-helper"}]
} }

View File

@ -6,7 +6,7 @@ import {currentLocale} from 'i18n-runtime';
import {Portal} from 'react-overlays'; import {Portal} from 'react-overlays';
import {Icon} from './icons/index'; import {Icon} from './icons/index';
import LayoutList from './layout/index'; import LayoutList from './layout/index';
import themeConfig from 'amis-theme-editor-helper/lib/systemTheme/cxd'; import {cxdData} from 'amis-theme-editor-helper';
// 测试组织属性配置面板的国际化,可以放开如下注释 // 测试组织属性配置面板的国际化,可以放开如下注释
// import './renderer/InputTextI18n'; // import './renderer/InputTextI18n';
@ -14,7 +14,7 @@ import themeConfig from 'amis-theme-editor-helper/lib/systemTheme/cxd';
// import './utils/overwriteSchemaTpl'; // import './utils/overwriteSchemaTpl';
// const i18nEnabled = true; // const i18nEnabled = true;
const i18nEnabled = false; const i18nEnabled = false;
setThemeConfig(themeConfig); setThemeConfig(cxdData);
const schema = { const schema = {
type: 'page', type: 'page',

View File

@ -42,8 +42,8 @@
"dependencies": { "dependencies": {
"@webcomponents/webcomponentsjs": "^2.6.0", "@webcomponents/webcomponentsjs": "^2.6.0",
"amis-editor-core": "*", "amis-editor-core": "*",
"amis-theme-editor-helper": "*",
"amis-postcss": "1.0.0", "amis-postcss": "1.0.0",
"amis-theme-editor": "*",
"i18n-runtime": "*", "i18n-runtime": "*",
"lodash": "^4.17.15", "lodash": "^4.17.15",
"mobx-state-tree": "^3.17.3" "mobx-state-tree": "^3.17.3"
@ -102,8 +102,8 @@
"amis": "*", "amis": "*",
"amis-core": "*", "amis-core": "*",
"amis-formula": "*", "amis-formula": "*",
"amis-theme-editor": "*",
"amis-ui": "*", "amis-ui": "*",
"amis-theme-editor-helper": "*",
"i18n-runtime": "*", "i18n-runtime": "*",
"react": ">=16.8.6", "react": ">=16.8.6",
"react-dom": ">=16.8.6" "react-dom": ">=16.8.6"

View File

@ -51,16 +51,7 @@ import './renderer/InputRangeValueControl';
import './renderer/FunctionEditorControl'; import './renderer/FunctionEditorControl';
import './renderer/ListItemControl'; import './renderer/ListItemControl';
import 'amis-theme-editor/lib/locale/zh-CN'; import 'amis-theme-editor-helper';
import 'amis-theme-editor/lib/locale/en-US';
import 'amis-theme-editor/lib/renderers/Border';
import 'amis-theme-editor/lib/renderers/ColorPicker';
import 'amis-theme-editor/lib/renderers/Font';
import 'amis-theme-editor/lib/renderers/PaddingAndMargin';
import 'amis-theme-editor/lib/renderers/Radius';
import 'amis-theme-editor/lib/renderers/Shadow';
import 'amis-theme-editor/lib/renderers/Size';
import 'amis-theme-editor/lib/renderers.css';
export * from './component/BaseControl'; export * from './component/BaseControl';
export * from './icons/index'; export * from './icons/index';

View File

@ -10,5 +10,9 @@
] ]
}, },
"include": ["src/**/*"], "include": ["src/**/*"],
"references": [{"path": "../amis"}, {"path": "../amis-editor-core"}] "references": [
{"path": "../amis"},
{"path": "../amis-editor-core"},
{"path": "../amis-theme-editor-helper"}
]
} }

View File

@ -0,0 +1,35 @@
module.exports = {
entry: {
dir: './src'
},
file: {
test: /.*(ts|tsx|js|jsx)$/
},
includes: ['src/renderers'],
importInfo: {
source: 'i18n-runtime',
imported: 'i18n',
local: '_i18n'
},
i18nModule: 'i18n-runtime',
languages: [
{
name: 'en-US',
path: './src/locale'
},
{
name: 'zh-CN',
path: './src/locale'
}
],
output: {
fileName: 'theme-editor-i18n',
fileExtension: 'xlsx',
path: './'
},
translate: {
appId: '',
key: '',
host: 'http://api.fanyi.baidu.com'
}
};

View File

@ -0,0 +1,69 @@
{
"name": "amis-theme-editor-helper",
"version": "2.0.22-beta.9",
"description": "amis主题编辑器通用方法",
"main": "lib/index.js",
"module": "esm/index.js",
"types": "lib/index.d.ts",
"scripts": {
"test": "echo \"Error: no test specified\"",
"build": "npm run clean-dist && NODE_ENV=production rollup -c ",
"clean-dist": "rimraf lib/** esm/**",
"i18n:update": "npx i18n update --config=./i18nConfig.js",
"i18n:translate": "npx i18n translate --config=./i18nConfig.js --l=en-US",
"i18n:merge": "npx i18n merge --config=./i18nConfig.js --l=en-US"
},
"keywords": [
"amis",
"theme-editor-helper"
],
"author": "@fex",
"license": "ISC",
"files": [
"lib",
"esm"
],
"lint-staged": {
"{src,scss,examples}/**/**/*.{js,jsx,ts,tsx,scss,json}": [
"prettier --write"
]
},
"dependencies": {
"react": "^18.2.0",
"react-color": "^2.19.3",
"react-dom": "^18.2.0"
},
"devDependencies": {
"@rollup/plugin-url": "^7.0.0",
"@svgr/rollup": "^6.4.0",
"@types/async": "^2.0.45",
"@types/classnames": "^2.2.3",
"@types/codemirror": "^5.60.5",
"@types/deep-diff": "^1.0.0",
"@types/history": "^4.6.0",
"@types/hoist-non-react-statics": "^3.0.1",
"@types/lodash": "^4.14.76",
"@types/node": "^14.0.24",
"@types/react": "^18.0.24",
"@types/react-dom": "^18.0.8",
"@rollup/plugin-commonjs": "^22.0.0",
"@rollup/plugin-json": "^4.1.0",
"@rollup/plugin-node-resolve": "^13.3.0",
"@rollup/plugin-typescript": "^8.3.2",
"rollup": "^2.73.0",
"rollup-plugin-auto-external": "^2.0.0",
"rollup-plugin-license": "^2.7.0",
"@types/react-color": "^3.0.6",
"tslib": "^2.3.1",
"typescript": "^4.6.4",
"sass": "^1.49.7",
"sass-loader": "^12.5.0",
"style-loader": "^3.2.1"
},
"peerDependencies": {
"amis": "*",
"amis-core": "*",
"amis-ui": "*",
"i18n-runtime": "*"
}
}

View File

@ -0,0 +1,149 @@
// rollup.config.js
import commonjs from '@rollup/plugin-commonjs';
import json from '@rollup/plugin-json';
import resolve from '@rollup/plugin-node-resolve';
import typescript from '@rollup/plugin-typescript';
import license from 'rollup-plugin-license';
import autoExternal from 'rollup-plugin-auto-external';
import postcss from 'rollup-plugin-postcss';
import {
name,
version,
author,
main,
module,
dependencies
} from './package.json';
import path from 'path';
import svgr from '@svgr/rollup';
import fs from 'fs';
import i18nPlugin from 'plugin-react-i18n';
const i18nConfig = require('./i18nConfig');
const settings = {
globals: {}
};
const external = id =>
new RegExp(
`^(?:${Object.keys(dependencies ?? {})
.concat(fs.readdirSync(path.join(__dirname, '../../node_modules')))
.map(value =>
value.replace(/[|\\{}()[\]^$+*?.]/g, '\\$&').replace(/-/g, '\\x2d')
)
.join('|')})`
).test(id);
const input = ['./src/index.ts'];
export default [
{
input,
output: [
{
...settings,
dir: path.dirname(main),
format: 'cjs',
exports: 'named',
preserveModulesRoot: './src',
preserveModules: true // Keep directory structure and files
}
],
external,
plugins: getPlugins('cjs')
},
{
input,
output: [
{
...settings,
dir: path.dirname(module),
format: 'esm',
exports: 'named',
preserveModulesRoot: './src',
preserveModules: true // Keep directory structure and files
}
],
external,
plugins: getPlugins('esm')
}
];
function transpileDynamicImportForCJS(options) {
return {
name: 'transpile-dynamic-import-for-cjs',
renderDynamicImport({format, targetModuleId}) {
if (format !== 'cjs') {
return null;
}
return {
left: 'Promise.resolve().then(function() {return new Promise(function(fullfill) {require([',
right:
'], function(mod) {fullfill(require("tslib").__importStar(mod))})})})'
};
// return {
// left: 'Promise.resolve().then(function() {return new Promise(function(fullfill) {require.ensure([',
// right:
// '], function(r) {fullfill(_interopDefaultLegacy(r("' +
// targetModuleId +
// '")))})})})'
// };
}
};
}
function getPlugins(format = 'esm') {
const typeScriptOptions = {
typescript: require('typescript'),
sourceMap: false,
outputToFilesystem: true,
...(format === 'esm'
? {
compilerOptions: {
rootDir: './src',
outDir: path.dirname(module)
}
}
: {
compilerOptions: {
rootDir: './src',
outDir: path.dirname(main)
}
})
};
return [
i18nPlugin(i18nConfig),
typescript(typeScriptOptions),
svgr({
svgProps: {
className: 'icon'
},
prettier: false,
dimensions: false
}),
transpileDynamicImportForCJS(),
autoExternal(),
json(),
postcss({
minimize: true
}),
resolve({
jsnext: true,
main: true
}),
commonjs({
sourceMap: false
}),
license({
banner: `
${name} v${version}
Copyright 2018<%= moment().format('YYYY') > 2018 ? '-' + moment().format('YYYY') : null %> ${author}
`
})
];
}

View File

@ -0,0 +1,458 @@
type ResColor = {hex: string; hsv: number[]}[];
export class ColorGenerator {
color = '';
//十六进制颜色值的正则表达式
reg = /^#([0-9a-fA-f]{3}|[0-9a-fA-f]{6})$/;
constructor(color: string) {
this.setPrimaryColor(color);
}
/**
*
*/
getDerivedColor() {
const rgb = ColorGenerator.hexToRgb(this.color);
const [h, s, v] = ColorGenerator.rgbToHsv(rgb);
const scolors: ResColor = [];
const wcolors: ResColor = [];
const hsvCorrection = (hsv: number[]) => {
let h = hsv[0],
s = hsv[1],
v = hsv[2];
if (s < 10) {
s = 10;
}
return ColorGenerator.hsvCorrection([h, s, v]);
};
for (let i = 0; i < 4; i++) {
const index = i + 1;
let sh, ss, sv;
if (h > 60 && h < 300) {
// 冷色
sh = h + index * 2;
ss = s + index * 5;
sv = v - index * 15;
} else {
// 暖色
sh = h - index * 2;
ss = s + index * 5;
sv = v - index * 15;
}
const shsv = hsvCorrection([sh, ss, sv]);
const srgb = ColorGenerator.hsvToRgb(shsv);
const shex = ColorGenerator.rgbToHex(srgb);
scolors.push({hex: shex, hsv: shsv});
}
for (let i = 0; i < 5; i++) {
const index = i + 1;
let wh, ws, wv;
if (h > 60 && h < 300) {
// 冷色
wh = h - index * 1;
ws = s - index * (s / 5);
wv = v + index * 5;
} else {
// 暖色
wh = h + index * 1;
ws = s - index * (s / 5);
wv = v + index * (100 - v) * 5;
}
const whsv = hsvCorrection([wh, ws, wv]);
const wrgb = ColorGenerator.hsvToRgb(whsv);
const whex = ColorGenerator.rgbToHex(wrgb);
wcolors.push({hex: whex, hsv: whsv});
}
return [
...scolors.reverse(),
{hex: this.color, hsv: [h, s, v]},
...wcolors
];
}
/**
*
*/
getNeutralColor() {
const rgb = ColorGenerator.hexToRgb(this.color);
const [h, ,] = ColorGenerator.rgbToHsv(rgb);
const S = [65, 45, 25, 10, 6, 4, 2, 1, 1, 1, 0];
const V = [8, 15, 25, 40, 55, 75, 85, 92, 96, 98, 100];
const colors: ResColor = [];
for (let i = 0; i < 11; i++) {
const newHsv = ColorGenerator.hsvCorrection([h, S[i], V[i]]);
const newRgb = ColorGenerator.hsvToRgb(newHsv);
const newHex = ColorGenerator.rgbToHex(newRgb);
colors.push({hex: newHex, hsv: newHsv});
}
return colors;
}
/**
*
*/
getFunctionalColor() {
const rgb = ColorGenerator.hexToRgb(this.color);
const [h, s, v] = ColorGenerator.rgbToHsv(rgb);
const errorH = {a: 375.06, b: 0.6, c: 134.93, d: 353.95};
const warnH = {a: 217.7, b: -0.02, c: 514460.59, d: -118.56};
const successH = {a: 130.48, b: -0.24, c: 0.00066};
const errorS = {a: 95.12, b: 2.34, c: 72.07, d: 69.59};
const warnS = {a: 95.1, b: 0.53, c: 74.9, d: 66.82};
const successS = {a: 100.5, b: -6.41, c: 80.99, d: 65.5};
const errorV = {a: 100.21, b: -16.63, c: 89.6, d: 83};
const warnV = {a: 270.03, b: -0.1, c: 1.18, d: -103.6};
const successV = {a: 81.5, b: -6.31, c: 91.2, d: 64.5};
const hs = [
[
h === 0 ? 0 : ColorGenerator.functionY(h, errorH) - 3,
ColorGenerator.functionY(s, errorS) - 5,
ColorGenerator.functionY(s, errorV) + 7
],
[
ColorGenerator.functionY(h + 1, warnH) - 7,
ColorGenerator.functionY(s + 1, warnS) + 5,
ColorGenerator.functionY(s + 1, warnV) - 23
],
[
Math.round(successH.a + successH.b * h + successH.c * h * h),
ColorGenerator.functionY(s, successS) + 4,
ColorGenerator.functionY(s, successV) + 4
]
];
const colors = hs.map(hsv => {
hsv = ColorGenerator.hsvCorrection(hsv);
const newRgb = ColorGenerator.hsvToRgb(hsv);
const hex = ColorGenerator.rgbToHex(newRgb);
return {hex, hsv};
});
return colors;
}
/**
*
*/
getDataColor() {
const colors = ColorGenerator.getColorPalette(this.color);
const color1 = [
colors[0],
colors[4],
colors[8],
colors[12],
colors[16],
colors[20],
colors[23]
];
const color2 = [
colors[0],
colors[5],
colors[10],
colors[15],
colors[19],
colors[23],
colors[3]
];
const color3 = [
colors[0],
colors[1],
colors[2],
colors[3],
colors[4],
colors[5],
colors[6]
];
return [color1, color2, color3];
}
setPrimaryColor(color: string) {
if (this.reg.test(color)) {
this.color = color;
} else {
throw new Error('请传入十六进制色值');
}
}
static hexToRgb(hexColor: string) {
if (hexColor.length === 4) {
let hexColorNew = '#';
for (let i = 1; i < 4; i += 1) {
hexColorNew += hexColor
.slice(i, i + 1)
.concat(hexColor.slice(i, i + 1));
}
hexColor = hexColorNew;
}
//处理六位的颜色值
const hexColorChange: number[] = [];
for (let i = 1; i < 7; i += 2) {
hexColorChange.push(parseInt('0x' + hexColor.slice(i, i + 2)));
}
return hexColorChange;
}
static rgbToHex(rgb: number[]) {
const r = rgb[0],
g = rgb[1],
b = rgb[2];
const hexr = r.toString(16).padStart(2, '0');
const hexg = g.toString(16).padStart(2, '0');
const hexb = b.toString(16).padStart(2, '0');
return '#' + hexr + hexg + hexb;
}
static rgbToHsv(rgb: number[]) {
let r = rgb[0],
g = rgb[1],
b = rgb[2];
r = r / 255;
g = g / 255;
b = b / 255;
let h = 0,
s,
v;
const min = Math.min(r, g, b);
const max = (v = Math.max(r, g, b));
const difference = max - min;
if (max == min) {
h = 0;
} else {
switch (max) {
case r:
h = (g - b) / difference + (g < b ? 6 : 0);
break;
case g:
h = 2 + (b - r) / difference;
break;
case b:
h = 4 + (r - g) / difference;
break;
}
h = Math.round(h * 60);
}
if (max == 0) {
s = 0;
} else {
s = 1 - min / max;
}
s = Math.round(s * 100);
v = Math.round(v * 100);
return [h, s, v];
}
static hsvToRgb(hsv: number[]) {
let h = hsv[0],
s = hsv[1],
v = hsv[2];
s = s / 100;
v = v / 100;
let r = 0,
g = 0,
b = 0;
const i = Math.floor((h / 60) % 6);
const f = h / 60 - i;
const p = v * (1 - s);
const q = v * (1 - f * s);
const t = v * (1 - (1 - f) * s);
switch (i) {
case 0:
r = v;
g = t;
b = p;
break;
case 1:
r = q;
g = v;
b = p;
break;
case 2:
r = p;
g = v;
b = t;
break;
case 3:
r = p;
g = q;
b = v;
break;
case 4:
r = t;
g = p;
b = v;
break;
case 5:
r = v;
g = p;
b = q;
break;
default:
break;
}
r = this.rgbCorrection(Math.round(r * 255.0));
g = this.rgbCorrection(Math.round(g * 255.0));
b = this.rgbCorrection(Math.round(b * 255.0));
return [r, g, b];
}
static hsvCorrection(hsv: number[]) {
let h = hsv[0],
s = hsv[1],
v = hsv[2];
if (h < 0) {
h = 360 + h;
}
if (h >= 360) {
h = h - 360;
}
if (s < 0) {
s = 0;
}
if (s > 100) {
s = 100;
}
if (v < 0) {
v = 0;
}
if (v > 100) {
v = 100;
}
return [h, s, v];
}
static rgbCorrection(value: number) {
if (value < 0) {
return 0;
}
if (value > 255) {
return 255;
}
return value;
}
static functionY(
x: number,
coefficient: {a: number; b: number; c: number; d: number}
) {
const {a, b, c, d} = coefficient;
const res = (a - d) / (1 + Math.pow(x / c, b)) + d;
return Math.round(res);
}
static isLightColor(color: string) {
const rgb = ColorGenerator.hexToRgb(color);
const hsv = ColorGenerator.rgbToHsv(rgb);
return hsv[1] < 20 && hsv[2] > 90;
}
static getFontColor(color: string | undefined) {
if (!color) {
return '#fff';
}
return ColorGenerator.isLightColor(color) ? '#5C5F66' : '#fff';
}
static computedLight(R: number, G: number, B: number) {
const gray = 0.299 * R + 0.587 * G + 0.114 * B;
return {gray, light: (gray / 255) * 100};
}
static getColorPalette(color: string, vv: number = 0) {
let rgb = ColorGenerator.hexToRgb(color);
let [h, s, v] = ColorGenerator.rgbToHsv(rgb);
const newColors = [];
// 原色的灰色模型
let {gray, light: mainLight} = ColorGenerator.computedLight(
rgb[0],
rgb[1],
rgb[2]
);
newColors.push({
rgb: rgb,
hsv: [h, s, v],
gray,
light: mainLight,
checkedRgb: rgb,
checkedColor: ColorGenerator.rgbToHex(rgb),
checkedGray: gray,
checkedLight: mainLight
});
/** 基础校正 */
// // 降低亮度
// if (mainLight > 55) {
// mainLight = mainLight / 2;
// }
// // 提高饱和度
// if (s < 70) {
// s = 70 + 70 - s;
// }
// // 提高饱和度
// if (v < 70) {
// v = 70 + 70 - v;
// }
/** ***** */
for (let i = 1; i < 24; i++) {
const newH = (h + 15 * i) % 360;
const newRgb = ColorGenerator.hsvToRgb([newH, s, v]);
// 灰度关系
let {gray, light} = ColorGenerator.computedLight(
newRgb[0],
newRgb[1],
newRgb[2]
);
const newColor = {
rgb: rgb,
hsv: [h, s, v],
gray,
light,
checkedRgb: rgb,
checkedColor: ColorGenerator.rgbToHex(rgb),
checkedGray: gray,
checkedLight: light
};
let checkedS = s;
let checkedV = v;
// 灰色校正
let checkedRgb = newRgb;
// 降低饱和度
while (mainLight > light && checkedS > 0) {
checkedS--;
checkedRgb = ColorGenerator.hsvToRgb([newH, checkedS, checkedV]);
const {gray: checkedGray, light: checkedLight} =
ColorGenerator.computedLight(
checkedRgb[0],
checkedRgb[1],
checkedRgb[2]
);
light = checkedLight;
gray = checkedGray;
}
// 降低明度
while (mainLight < light && checkedV > 0) {
checkedV--;
checkedRgb = ColorGenerator.hsvToRgb([newH, checkedS, checkedV]);
const {gray: checkedGray, light: checkedLight} =
ColorGenerator.computedLight(
checkedRgb[0],
checkedRgb[1],
checkedRgb[2]
);
light = checkedLight;
gray = checkedGray;
}
newColor.checkedLight = light;
newColor.checkedGray = gray;
newColor.checkedRgb = checkedRgb;
newColor.checkedColor = ColorGenerator.rgbToHex(checkedRgb);
newColors.push(newColor);
}
return newColors;
}
}

View File

@ -0,0 +1,299 @@
import type {PlainObject, ThemeDefinition} from './declares';
export class ParseThemeData {
style: string[] = [];
class: string[] = [];
data: ThemeDefinition;
scope: string[];
theme: string;
constructor(data: ThemeDefinition, scope: string[]) {
this.data = data;
this.scope = scope;
this.theme = data.config.key;
}
generator() {
const {global, component} = this.data;
const {colors, fonts, borders, sizes, shadows} = global;
this.parseColor(colors);
this.parseFont(fonts);
this.parseGlobalCommon(borders);
this.parseGlobalCommon(sizes);
this.parseSizesBase(sizes);
this.parseShadows(shadows);
for (let key in component) {
if (key === 'button1') {
this.parseButton(component['button1']);
} else if (key === 'inputRating') {
this.parseInputRating(component['inputRating']);
} else {
this.parseComponentCommon(component[key]);
}
}
}
getStyle() {
return this.getCssVariable() + this.getCustomClass();
}
getCssVariable() {
return `${this.scope.join(', ')}{${this.style.join(';')};}\n`;
}
getCustomClass() {
return `${this.class.join('\n')}`;
}
/**
* 使less或scss编译后使用
*/
getCustomStyle() {
const customStyle = this.data?.customStyle?.style || '';
return customStyle;
}
/**
* css变量
*/
cssFormat(key: string, value: string) {
if (!value) {
return;
}
this.style.push(`${key}: ${value}`);
}
/**
* class
*/
classFormat(classname: string, value: string) {
// 自定义的不需要在命名空间下了
this.class.push(`${classname}{${value}}`);
}
/**
*
*/
parseColor(colors: any) {
this.cssFormat('--colors-neutral-fill-none', 'translate');
for (let key in colors) {
const color = colors[key];
if (key !== 'brand') {
color.body.forEach((item: any) => {
const prefix = item.token;
for (let colorKey in item.body) {
if (colorKey === 'colors') {
item.body.colors.forEach((color: any) => {
this.cssFormat(color.token, color.color);
});
} else if (!Array.isArray(item.body[colorKey])) {
this.cssFormat(prefix + colorKey, item.body[colorKey]);
}
}
});
} else {
const prefix = color.token;
for (let colorKey in color.body) {
if (colorKey === 'colors') {
color.body.colors.forEach((color: any) => {
this.cssFormat(color.token, color.color);
});
} else if (!Array.isArray(color.body[colorKey])) {
this.cssFormat(prefix + colorKey, color.body[colorKey]);
}
}
}
}
}
/**
*
*/
parseFont(fonts: any) {
for (let key in fonts) {
const font = fonts[key];
if (key === 'base') {
let family = '';
font.body.forEach((item: any, index: number) => {
family += item.value || '';
if (index !== font.body.length - 1) {
family += ', ';
}
});
this.cssFormat(font.token, family);
} else {
font.body.forEach((item: any) => {
this.cssFormat(item.token, item.value);
});
}
}
}
// 解析基础尺寸
parseSizesBase(item: any) {
const reg = /\d+(\.\d+)?/;
const unitReg = /[^\d\.]+/;
const start = parseFloat(item.size.start.match(reg)[0]);
const base = item.size.base;
const unit = item.size.start.match(unitReg)[0];
for (let i = 0; i < 50; i++) {
this.cssFormat(`--sizes-base-${i + 1}`, start + i * base + unit);
}
}
/**
*
*/
parseGlobalCommon(items: any) {
for (let key in items) {
const item = items[key];
item.body.forEach((i: any) => {
this.cssFormat(i.token, i.value);
});
}
}
/**
*
*/
parseShadows(items: any) {
const item = items.shadow;
item.body.forEach((i: any) => {
const shadowStyle = i.value.map(
(shadow: any) =>
`${shadow.inset ? 'inset' : ''} ${shadow.x} ${shadow.y} ${
shadow.blur
} ${shadow.spread} ${shadow.color}`
);
this.cssFormat(i.token, shadowStyle.join(', '));
});
}
/**
*
*/
setComponentStyle(key: string, token: string, value: string | PlainObject) {
if (typeof value === 'string') {
this.cssFormat(token + key, value);
} else {
if (key.indexOf('padding-and-margin') > -1) {
for (let k in value) {
this.cssFormat(
token + key.replace('padding-and-margin', '') + k,
value[k]
);
}
} else if (key.indexOf('size') > -1) {
for (let k in value) {
this.cssFormat(token + key.replace('size', '') + k, value[k]);
}
} else if (key.indexOf('font') > -1) {
for (let k in value) {
this.cssFormat(token + key.replace('font', '') + k, value[k]);
}
} else if (key.indexOf('border') > -1) {
for (let k in value) {
this.cssFormat(token + key.replace('border', '') + k, value[k]);
}
} else {
for (let k in value) {
this.cssFormat(`${token}${k}`, value[k]);
}
}
}
}
/**
* Button
*/
parseButton(button: any) {
const {type, size} = button;
const setButtonCssValue = (token: string, body: any) => {
for (let key in body) {
const data = body[key];
this.setComponentStyle(key, token, data);
}
};
for (let item of type) {
['default', 'hover', 'active', 'disabled'].forEach(state => {
setButtonCssValue(item[state].token, item[state].body);
});
if (item.custom) {
const fontType = item.type;
const style = (state: string) =>
[
`color: var(--button-${fontType}-${state}-font-color)`,
`background: var(--button-${fontType}-${state}-bg-color)`,
`box-shadow: var(--button-${fontType}-${state}-shadow)`,
`border-width: var(--button-${fontType}-${state}-top-border-width) var(--button-${fontType}-${state}-right-border-width) var(--button-${fontType}-${state}-bottom-border-width) var(--button-${fontType}-${state}-left-border-width)`,
`border-color: var(--button-${fontType}-${state}-top-border-color) var(--button-${fontType}-${state}-right-border-color) var(--button-${fontType}-${state}-bottom-border-color) var(--button-${fontType}-${state}-left-border-color)`,
`border-style: var(--button-${fontType}-${state}-top-border-style) var(--button-${fontType}-${state}-right-border-style) var(--button-${fontType}-${state}-bottom-border-style) var(--button-${fontType}-${state}-left-border-style)`
].join(';');
this.classFormat(`.cxd-Button--${fontType}`, `${style('default')}`);
this.classFormat(
`.cxd-Button--${fontType}:not(:disabled):not(.is-disabled):hover`,
`${style('hover')}`
);
this.classFormat(
`.cxd-Button--${fontType}:not(:disabled):not(.is-disabled):hover:active`,
`${style('active')}`
);
}
}
for (let item of size) {
setButtonCssValue(item.token, item.body);
if (item.custom) {
const fontType = item.type;
this.classFormat(
`.cxd-Button--size-${fontType}`,
[
`font-size: var(--button-size-${fontType}-fonSize)`,
`font-weight: var(--button-size-${fontType}-fontWeight)`,
`line-height: var(--button-size-${fontType}-lineHeight)`,
`min-width: var(--button-size-${fontType}-minWidth)`,
`height: var(--button-size-${fontType}-height)`,
`border-radius: var(--button-size-${fontType}-top-right-border-radius) var(--button-size-${fontType}-top-left-border-radius) var(--button-size-${fontType}-bottom-right-border-radius) var(--button-size-${fontType}-bottom-left-border-radius)`,
`padding: var(--button-size-${fontType}-paddingTop) var(--button-size-${fontType}-paddingRight) var(--button-size-${fontType}-paddingBottom) var(--button-size-${fontType}-paddingLeft)`,
`margin: var(--button-size-${fontType}-marginTop) var(--button-size-${fontType}-marginRight) var(--button-size-${fontType}-marginBottom) var(--button-size-${fontType}-marginLeft)`
].join(';')
);
}
}
}
/**
* Tranfer
*/
parseTransfer(transfer: any) {
for (let typeKey in transfer) {
const token = transfer[typeKey].token;
const body = transfer[typeKey].body;
for (let key in body) {
this.setComponentStyle(key, token, body[key]);
}
}
}
/**
* inputRating
*/
parseInputRating(inputRating: any) {
const data = JSON.parse(JSON.stringify(inputRating));
const colors = data.activeColors;
this.cssFormat('--Rating-colors', `'${JSON.stringify(colors)}'`);
delete data.activeColors;
this.parseComponentCommon(data);
}
// 解析组件通用方法
parseComponentCommon(component: any) {
if (component.token) {
// 有token时结束递归
const token = component.token;
for (let key in component.body) {
this.setComponentStyle(key, token, component.body[key]);
}
} else {
for (let key in component) {
if (typeof component[key] === 'object') {
this.parseComponentCommon(component[key]);
}
}
}
}
}

View File

@ -0,0 +1,163 @@
export interface Colors {
main?: string;
none?: string;
colors: {
label: string;
token: string;
color: string;
index: number;
}[];
common: {
label: string;
id: string;
color: number;
}[];
}
export interface Font {
label: string;
token: string;
value?: string | number;
body?: {value: string | number}[];
}
export interface Border {
label: string;
token: string;
disabled?: boolean;
value: string;
}
export interface Size {
label: string;
disabled?: boolean;
token: string;
value: string;
}
export interface ShadowData {
inset: boolean;
x: string;
y: string;
blur: string;
spread: string;
color: string;
}
export interface Shadow {
label: string;
token: string;
disabled?: boolean;
value: ShadowData[];
}
export interface ThemeDefinition {
version?: string;
config: {
name: string;
key: string;
description: string;
};
global: {
colors: {
brand: {
token: string;
label: string;
body: Colors;
};
neutral: {
token: string;
label: string;
body: {
token: string;
label: string;
body: Colors;
}[];
};
func: {
token: string;
label: string;
body: {
token: string;
label: string;
body: Colors;
}[];
};
data?: {
label: string;
body: {
label: string;
token: string;
colors: {value: string}[];
custom?: boolean;
}[];
};
};
fonts: {
base: {
label: string;
token: string;
body: {value: string}[];
};
size: {
label: string;
token: string;
body: Font[];
};
lineHeight: {
label: string;
token: string;
body: Font[];
};
weight: {
label: string;
token: string;
body: Font[];
};
};
borders: {
width: {
label: string;
token: string;
body: Border[];
};
style: {
label: string;
token: string;
body: Border[];
};
radius: {
label: string;
token: string;
body: Border[];
};
};
sizes: {
size: {
label: string;
token: string;
base: number;
body: Size[];
start: string;
};
};
shadows: {
shadow: {
label: string;
token: string;
body: Shadow[];
};
};
};
component: {
[x: string]: any;
};
customStyle?: {
[css: string]: string;
};
icons?: any;
}
export interface PlainObject {
[propsName: string]: any;
}

View File

@ -0,0 +1,202 @@
import type {Colors, PlainObject, ThemeDefinition} from './declares';
const COLORLABELMAP: PlainObject = {
main: '主色',
default: '常规',
active: '点击',
hover: '悬浮',
bg: '背景',
strong: '强调/正文标题',
lessStrong: '次强调/正文标题',
info: '次要信息',
disabledInfo: '置灰信息',
border: '描边/分割线',
cardBg: '卡片背景色',
none: '透明'
};
interface Options {
show?: boolean;
label: string;
value: string;
realValue?: any;
children?: Options[];
}
export interface GlobalData {
colorOptions?: Options[];
fontFamilyOptions?: Options[];
fontSizeOptions?: Options[];
lineHeightOptions?: Options[];
fontWeightOptions?: Options[];
borderRadiusOptions?: Options[];
borderWidthOptions?: Options[];
borderStyleOptions?: Options[];
sizesOptions?: Options[];
shadowOptions?: Options[];
}
export function getGlobalData(data: ThemeDefinition | undefined): GlobalData {
if (!data || !data.global) {
return {};
}
const {colors, fonts, borders, sizes, shadows} = data.global;
const colorOptions: Options[] = [];
const fontFamilyOptions: Options[] = [];
const fontSizeOptions: Options[] = [];
const fontWeightOptions: Options[] = [];
const lineHeightOptions: Options[] = [];
const borderRadiusOptions: Options[] = [];
const borderWidthOptions: Options[] = [];
const borderStyleOptions: Options[] = [];
const sizesOptions: Options[] = [];
const shadowOptions: Options[] = [];
// 解析颜色
function getGlobalColors(item: {label: string; token: string; body: Colors}) {
const children: Options[] = [];
item.body.common.forEach((common, i: number) => {
children.push({
label: common.label,
value: `var(${item.token}${common.color + 1})`,
realValue: item.body.colors[common.color].color
});
});
// if (item.token === '--colors-neutral-fill-') {
// children.push({
// label: COLORLABELMAP['none'],
// value: `var(${item.token}none)`
// });
// }
return {
label: item.label,
value: item.token,
children: children
};
}
colorOptions.push({
label: '品牌色',
value: 'brand',
children: [getGlobalColors(colors.brand)]
});
const neutralColors: any = {
label: '中性色',
value: 'neutral',
children: []
};
colors.neutral.body.forEach((color, i: number) => {
neutralColors.children.push(getGlobalColors(color));
});
colorOptions.push(neutralColors);
const funcColors: any = {
label: '辅助色',
value: 'neutral',
children: []
};
colors.func.body.forEach((color, i: number) => {
funcColors.children.push(getGlobalColors(color));
});
colorOptions.push(funcColors);
// 解析文字
for (let k in fonts) {
let key = k as 'base' | 'size' | 'lineHeight' | 'weight';
const options = {
size: fontSizeOptions,
lineHeight: lineHeightOptions,
weight: fontWeightOptions
};
const children: {label: string; value: string; realValue: string}[] = [];
if (key !== 'base') {
fonts[key].body.forEach((font, i: number) => {
children.push({
label: `${font.label}(${font.value})`,
value: `var(${font.token})`,
realValue: `${font.value}`
});
});
options[key].push(...children);
} else {
fonts['base'].body.forEach((font, i: number) => {
children.push({
label: font.value,
value: font.value,
realValue: font.value
});
});
fontFamilyOptions.push(...children);
}
}
// 解析边框
for (let k in borders) {
let key = k as 'width' | 'style' | 'radius';
const options = {
width: borderWidthOptions,
style: borderStyleOptions,
radius: borderRadiusOptions
};
const children: Options[] = [];
borders[key].body.forEach((border, i: number) => {
children.push({
label:
key === 'style' ? border.label : `${border.label}(${border.value})`,
realValue: border.value,
value: `var(${border.token})`
});
});
options[key].push(...children);
}
// 解析常用尺寸
sizes.size.body.forEach(size => {
sizesOptions.push({
label: `${size.label}(${size.value})`,
value: `var(${size.token})`,
realValue: size.value
});
});
// 解析扩展尺寸
const baseSizeStart = sizes.size.start;
const baseSizeStartNumber = parseFloat(baseSizeStart);
const baseSizeStartUnit = baseSizeStart.replace(
baseSizeStartNumber.toString(),
''
);
const baseSizeBase = sizes.size.base;
for (let i = 1; i <= 50; i++) {
const realValue =
(i - 1) * baseSizeBase + baseSizeStartNumber + baseSizeStartUnit;
sizesOptions.push({
label: `尺寸${i}(${realValue})`,
value: `var(--sizes-base-${i})`,
realValue
});
}
// 解析阴影
shadows.shadow.body.forEach(shadow => {
shadowOptions.push({
label: shadow.label,
value: `var(${shadow.token})`,
realValue: shadow.value
});
});
return {
colorOptions,
fontFamilyOptions,
fontSizeOptions,
lineHeightOptions,
fontWeightOptions,
borderRadiusOptions,
borderWidthOptions,
borderStyleOptions,
sizesOptions,
shadowOptions
};
}

View File

@ -0,0 +1,72 @@
import type {PlainObject} from './declares';
const styleMap: PlainObject = {
border: ['border-top', 'border-right', 'border-left', 'border-bottom']
};
export function styleBorder(style: CSSStyleDeclaration) {
const styleList = styleMap.border;
const data: PlainObject = {};
for (const item of styleList) {
const values = style.getPropertyValue(item);
const [border, position] = item.split('-');
const [borderWidth, borderStyle, ...borderColor] = values.split(' ');
data[`${position}-${border}-width`] = borderWidth;
data[`${position}-${border}-style`] = borderStyle;
data[`${position}-${border}-color`] = borderColor.join('');
}
return data;
}
export function styleBackground(style: CSSStyleDeclaration) {
const image = style.getPropertyPriority('background-image');
let data = image;
if (image === 'none') {
data = style.getPropertyValue('background-color');
}
return data;
}
export function getStyleById(id: string, name?: string) {
if (!name) {
return null;
}
let dom: any = document.getElementsByName(id);
if (dom.length === 0) {
return null;
}
dom = dom[0];
const list = name.split('.');
name = list[list.length - 1];
const [styleName] = name.split(':');
const style = getComputedStyle(dom);
let data: any = {};
switch (styleName) {
case 'border':
data = styleBorder(style);
break;
case 'color':
data = style.getPropertyValue('color');
break;
case 'background':
data = styleBackground(style);
break;
}
return data;
}
export function getCssVarByName(
name: string,
className: string = '.ThemeEditor-body-content-item-content'
): string {
name = name?.replace('var', '').replace('(', '').replace(')', '');
try {
const res = getComputedStyle(
document.querySelector(className)!
).getPropertyValue(name);
return res;
} catch (error) {
return '';
}
}

View File

@ -0,0 +1,21 @@
export function findOrCreactStyle(id: string) {
let varStyleTag = document.getElementById(id);
if (!varStyleTag) {
varStyleTag = document.createElement('style');
varStyleTag.id = id;
document.body.appendChild(varStyleTag);
}
return varStyleTag;
}
export function insertStyle(style: string, id: string) {
const varStyleTag = findOrCreactStyle(id);
// bca-disable-line
varStyleTag.innerHTML = style;
}
export function addStyle(style: string, id: string) {
const varStyleTag = findOrCreactStyle(id);
// bca-disable-line
varStyleTag.innerHTML += style;
}

View File

@ -0,0 +1 @@
<?xml version="1.0" encoding="UTF-8"?><svg viewBox="0 0 16 16" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"><rect id="1-FL" stroke="currentColor" x="2.5" y="2.5" width="11" height="11" stroke-width="1" fill="none" stroke-linecap="butt" stroke-linejoin="round"/><line x1="5" y1="8" x2="11" y2="8" id="2-LW" stroke="currentColor" stroke-width="1" fill="none" stroke-linecap="butt" stroke-linejoin="round"/><line x1="8" y1="5" x2="8" y2="11" id="3-LW" stroke="currentColor" stroke-width="1" fill="none" stroke-linecap="butt" stroke-linejoin="round"/></svg>

After

Width:  |  Height:  |  Size: 600 B

View File

@ -0,0 +1,11 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="25px" height="25px" viewBox="0 0 25 25" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<g stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g transform="translate(-1696.000000, -299.000000)">
<g transform="translate(1696.914182, 299.205057)">
<path d="M0,0 L21,0 C22.6568542,-3.04359188e-16 24,1.34314575 24,3 L24,24 L24,24 L0,0 Z" id="矩形" fill="#2468F2" transform="translate(12.000000, 12.000000) rotate(-270.000000) translate(-12.000000, -12.000000) "></path>
<polyline id="路径" stroke="#FFFFFF" stroke-linecap="round" stroke-linejoin="round" points="12 16.4626435 15 19.4626435 21 13.4626435"></polyline>
</g>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 828 B

View File

@ -0,0 +1,10 @@
<svg width="24px" height="25px" viewBox="0 0 24 25" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<g stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g transform="translate(-2105.000000, -299.000000)">
<g transform="translate(2104.995034, 299.205057)">
<path d="M0,0 L21,0 C22.6568542,-3.04359188e-16 24,1.34314575 24,3 L24,24 L24,24 L0,0 Z" id="矩形" fill="#E8E9EB" transform="translate(12.000000, 12.000000) rotate(-270.000000) translate(-12.000000, -12.000000) "></path>
<polyline id="路径" stroke="#FFFFFF" stroke-linecap="round" stroke-linejoin="round" points="12 16.4626435 15 19.4626435 21 13.4626435"></polyline>
</g>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 789 B

View File

@ -0,0 +1,18 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="20px" height="21px" viewBox="0 0 20 21" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<g id="页面-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="主题配置-颜色" transform="translate(-123.000000, -339.000000)">
<g id="单排侧边栏" transform="translate(109.000000, 200.000000)">
<g id="编组-3" transform="translate(0.000000, 125.570131)">
<g id="编组备份-2" transform="translate(14.000000, 14.000000)">
<rect id="矩形备份-2" x="0" y="0" width="20" height="20"></rect>
<rect id="矩形备份" stroke="#151B26" stroke-width="1.25" stroke-linejoin="round" x="2.5" y="3.75" width="15" height="12.5"></rect>
<line x1="11.7094895" y1="6.84057953" x2="8.34749408" y2="13.125" id="直线-3备份" stroke="#151B26" stroke-width="1.25" stroke-linecap="round"></line>
<polyline id="直线-5" stroke="#151B26" stroke-width="1.25" stroke-linecap="round" stroke-linejoin="round" transform="translate(13.643713, 10.000000) rotate(-315.000000) translate(-13.643713, -10.000000) " points="12.3937133 8.75129365 14.8937133 8.75129365 14.8937133 11.2487063"></polyline>
<polyline id="直线-5备份" stroke="#151B26" stroke-width="1.25" stroke-linecap="round" stroke-linejoin="round" transform="translate(6.580642, 10.000000) scale(-1, 1) rotate(-315.000000) translate(-6.580642, -10.000000) " points="5.33064187 8.75129365 7.83064187 8.75129365 7.83064187 11.2487063"></polyline>
</g>
</g>
</g>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.7 KiB

View File

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="utf-8"?>
<svg version="1.1" id="_x30_" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 17 17" style="enable-background:new 0 0 17 17;" xml:space="preserve">
<circle fill="#D4E5FF" cx="8.5" cy="8.5" r="8.5"/>
<path fill="#6E9DFF" d="M16.5,11.5l-3.2-3c-0.2-0.2-0.5-0.2-0.7,0l-2.8,2.6c-0.2,0.2-0.5,0.2-0.7,0l-4-4.3c-0.2-0.2-0.5-0.2-0.7,0
l-4,4.4C1.6,14.6,4.7,17,8.5,17C12.2,17,15.3,14.7,16.5,11.5z"/>
<circle id="_x32_" fill="#6E9DFF" cx="10.9" cy="5.5" r="1.3"/>
</svg>

After

Width:  |  Height:  |  Size: 562 B

View File

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="utf-8"?>
<svg version="1.1" id="_x30_" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 17 17" style="enable-background:new 0 0 17 17;" xml:space="preserve">
<circle fill="#E8E9EB" cx="8.5" cy="8.5" r="8.5"/>
<path fill="#CBCDD1" d="M16.5,11.5l-3.2-3c-0.2-0.2-0.5-0.2-0.7,0l-2.8,2.6c-0.2,0.2-0.5,0.2-0.7,0l-4-4.3c-0.2-0.2-0.5-0.2-0.7,0
l-4,4.4C1.6,14.6,4.7,17,8.5,17C12.2,17,15.3,14.7,16.5,11.5z"/>
<circle fill="#CBCDD1" cx="10.9" cy="5.5" r="1.3"/>
</svg>

After

Width:  |  Height:  |  Size: 552 B

View File

@ -0,0 +1,20 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="20px" height="21px" viewBox="0 0 20 21" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<g id="页面-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="主题配置-颜色" transform="translate(-123.000000, -279.000000)">
<g id="单排侧边栏" transform="translate(109.000000, 200.000000)">
<g id="编组-33" transform="translate(0.000000, 65.570131)">
<g id="编组-22备份-3" transform="translate(14.000000, 14.000000)">
<rect id="矩形" x="0" y="0" width="20" height="20"></rect>
<g id="编组" transform="translate(2.000000, 2.000000)" stroke="#333333" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.25">
<polygon id="路径" points="5.2 2.8 8 0 10.8 2.8 8 5.6"></polygon>
<polygon id="路径" points="10.4 8.4 13.2 5.6 16 8.4 13.2 11.2"></polygon>
<polygon id="路径" points="5.2 13.2 8 10.4 10.8 13.2 8 16"></polygon>
<polygon id="路径" points="0 8 2.8 5.2 5.6 8 2.8 10.8"></polygon>
</g>
</g>
</g>
</g>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.3 KiB

View File

@ -0,0 +1,18 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="18px" height="18px" viewBox="0 0 18 18" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<g id="11.1终稿" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="图标" transform="translate(-141.000000, -40.000000)">
<g id="自定义设置" transform="translate(142.000000, 41.000000)">
<g id="编组-28备份">
<rect id="矩形" x="0" y="0" width="16" height="16"></rect>
</g>
<rect id="矩形" fill="#84868C" x="7.11577461" y="2.95100764" width="6.91305466" height="1" rx="0.5"></rect>
<rect id="矩形备份-49" fill="#84868C" x="7.11577461" y="5.98938234" width="5.18768508" height="1" rx="0.5"></rect>
<rect id="矩形备份-51" fill="#84868C" x="7.11577461" y="9.02775704" width="6.91305466" height="1" rx="0.5"></rect>
<rect id="矩形备份-50" fill="#84868C" x="7.11577461" y="12.0661317" width="5.18768508" height="1" rx="0.5"></rect>
<path d="M4.28402126,2.5 L4.28402126,3.98813377 M4.28402126,6.73009787 L4.28402126,8.87389474 M4.28402126,11.9388703 L4.28402126,13.5" id="形状" stroke="#84868C" stroke-linecap="round" stroke-linejoin="bevel"></path>
<path d="M4.25,9.19464196 C4.98767176,9.19464196 5.58567287,9.79264308 5.58567287,10.5303148 C5.58567287,11.2679866 4.98767176,11.8659877 4.25,11.8659877 C3.51232824,11.8659877 2.91432713,11.2679866 2.91432713,10.5303148 C2.91432713,9.79264308 3.51232824,9.19464196 4.25,9.19464196 Z M4.25,4.04216118 C4.98767176,4.04216118 5.58567287,4.6401623 5.58567287,5.37783405 C5.58567287,6.11550581 4.98767176,6.71350693 4.25,6.71350693 C3.51232824,6.71350693 2.91432713,6.11550581 2.91432713,5.37783405 C2.91432713,4.6401623 3.51232824,4.04216118 4.25,4.04216118 Z" id="形状结合" stroke="#84868C" stroke-linejoin="round"></path>
</g>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 2.0 KiB

View File

@ -0,0 +1 @@
<?xml version="1.0" encoding="UTF-8"?><svg viewBox="0 0 16 16" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"><g id="trash" transform="translate(2.000000, 1.500000)" stroke="#151B26"><rect id="1-FL" stroke-linejoin="round" x="1.5" y="2.5" width="9" height="10" stroke="currentColor" stroke-width="1" fill="none" stroke-linecap="butt"/><line x1="0" y1="2.5" x2="12.004017" y2="2.5" id="2-L" stroke-linecap="butt" stroke="currentColor" stroke-width="1" fill="none" stroke-linejoin="round"/><line x1="4.5299753" y1="5.999" x2="4.5299753" y2="8.999" id="3-LW" stroke-linecap="butt" stroke="currentColor" stroke-width="1" fill="none" stroke-linejoin="round"/><line x1="7.5299753" y1="5.999" x2="7.5299753" y2="8.999" id="4-LW" stroke-linecap="butt" stroke="currentColor" stroke-width="1" fill="none" stroke-linejoin="round"/><line x1="4.5" y1="0.5" x2="7.5" y2="0.5" id="5-L" stroke-linecap="butt" stroke="currentColor" stroke-width="1" fill="none" stroke-linejoin="round"/></g></svg>

After

Width:  |  Height:  |  Size: 1.0 KiB

View File

@ -0,0 +1,18 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="20px" height="21px" viewBox="0 0 20 21" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<g id="页面-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="字体排版" transform="translate(-146.000000, -173.000000)" stroke-width="1.25">
<g id="编组-12" transform="translate(132.000000, 104.215478)">
<g id="单排侧边栏" transform="translate(0.000000, 49.784522)">
<g id="侧导航icon" transform="translate(0.000000, 5.570131)">
<g id="4.图标元件/7.通用/7.分类/分类-线备份-3" transform="translate(14.000000, 14.000000)">
<rect id="矩形" stroke="currentColor" stroke-linejoin="round" x="2.70106592" y="2.70231592" width="14.603164" height="5.84786816"></rect>
<rect id="矩形备份-5" stroke="currentColor" stroke-linejoin="round" x="2.70106592" y="11.4510659" width="5.84786816" height="5.84786816"></rect>
<rect id="矩形备份-4" stroke="currentColor" stroke-linejoin="round" x="11.4563618" y="11.4510659" width="5.84786816" height="5.84786816" rx="2.92393408"></rect>
</g>
</g>
</g>
</g>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.4 KiB

View File

@ -0,0 +1,54 @@
import {registerIcon, Icon} from 'amis';
import CheckboxCheck from './checkbox-check.svg';
import Checkbox from './checkbox.svg';
import Code from './code.svg';
import Component from './component.svg';
import Global from './global.svg';
import Custom from './custom.svg';
import Lock from './lock.svg';
import Unlock from './unlock.svg';
import Italic from './italic.svg';
import Underline from './underline.svg';
import LineThrough from './line-through.svg';
import textLeft from './text-left.svg';
import textCenter from './text-center.svg';
import textRight from './text-right.svg';
import textJustify from './text-justify.svg';
import verticalTop from './vertical-top.svg';
import verticalMiddle from './vertical-middle.svg';
import verticalBottom from './vertical-bottom.svg';
registerIcon('checkbox-check', CheckboxCheck);
registerIcon('checkbox', Checkbox);
registerIcon('code', Code);
registerIcon('component', Component);
registerIcon('global', Global);
registerIcon('custom', Custom);
registerIcon('lock', Lock);
registerIcon('unlock', Unlock);
registerIcon('italic', Italic);
registerIcon('underline', Underline);
registerIcon('line-through', LineThrough);
registerIcon('text-align-left', textLeft);
registerIcon('text-align-center', textCenter);
registerIcon('text-align-right', textRight);
registerIcon('text-align-justify', textJustify);
registerIcon('vertical-align-top', verticalTop);
registerIcon('vertical-align-middle', verticalMiddle);
registerIcon('vertical-align-bottom', verticalBottom);
import AddButton from './add-button.svg';
registerIcon('add-button', AddButton);
import DeleteButton from './delete-button.svg';
registerIcon('delete-button', DeleteButton);
// 颜色选择器
import ColorPickerImg from './color-picker-img.svg';
import ColorPickerImgActive from './color-picker-img-active.svg';
registerIcon('color-picker-img', ColorPickerImg);
registerIcon('color-picker-img-active', ColorPickerImgActive);
export {Icon};

View File

@ -0,0 +1,15 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="16px" height="16px" viewBox="0 0 16 16" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<g id="11.1终稿" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="图标" transform="translate(-142.000000, -209.000000)">
<g id="字符斜体" transform="translate(142.000000, 209.000000)">
<rect id="矩形备份-9" opacity="0.5" x="0" y="0" width="16" height="16"></rect>
<g id="编组-9" transform="translate(4.000000, 2.000000)" fill="currentColor">
<rect id="矩形" x="0" y="11.0710985" width="6.39371687" height="1.546875"></rect>
<rect id="矩形备份-10" x="2.52648496" y="0" width="6.39371687" height="1.54579613"></rect>
<polygon id="矩形备份-11" transform="translate(4.467389, 6.517991) rotate(-75.000000) translate(-4.467389, -6.517991) " points="-1.63309621 5.77231404 10.5726478 5.73461081 10.5678735 7.26366786 -1.63787052 7.30137109"></polygon>
</g>
</g>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.1 KiB

View File

@ -0,0 +1,16 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="17px" height="16px" viewBox="0 0 17 16" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<g id="11.1终稿" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="图标" transform="translate(-234.000000, -209.000000)">
<g id="编组-7备份" transform="translate(234.455199, 209.000000)">
<rect id="矩形备份-9" opacity="0.5" x="0" y="0" width="16" height="16"></rect>
<text id="S" font-family="PingFangSC-Medium, PingFang SC" font-size="14" font-weight="400" line-spacing="14" fill="currentColor">
<tspan x="2.90740741" y="14">S</tspan>
</text>
<g id="编组-10" transform="translate(2.907407, 8.000000)" fill="currentColor">
<rect id="矩形" x="0" y="0" width="10.1851852" height="1.546875"></rect>
</g>
</g>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1011 B

View File

@ -0,0 +1,15 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="16px" height="16px" viewBox="0 0 16 16" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<g id="11.1终稿" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="图标" transform="translate(-142.000000, -137.000000)">
<g id="编组-23" transform="translate(142.000000, 137.002288)">
<rect id="矩形" x="0" y="0" width="16" height="16.0045789"></rect>
<g id="编组" transform="translate(2.000000, 1.333715)" stroke="#5C5F66" stroke-linejoin="round" stroke-width="1.5">
<rect id="矩形" x="0" y="6.00171711" width="12" height="7.33543202" rx="0.666666667"></rect>
<path d="M2.66666667,6.00171711 L2.66666667,3.33428728 C2.66666667,1.49281043 4.15906667,0 6,0 C7.84093333,0 9.33333333,1.49281043 9.33333333,3.33428728 L9.33333333,6.00171711" id="路径" stroke-linecap="round"></path>
<line x1="6" y1="8.66914693" x2="6" y2="10.6697193" id="路径" stroke-linecap="round"></line>
</g>
</g>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.1 KiB

View File

@ -0,0 +1,15 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="17px" height="16px" viewBox="0 0 17 16" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<g id="11.1终稿" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="图标" transform="translate(-329.000000, -209.000000)">
<g id="字符居中对齐" transform="translate(329.823018, 209.000000)">
<rect id="矩形" x="0" y="0" width="16" height="16"></rect>
<g id="编组-11" transform="translate(2.000000, 2.000000)" fill="currentColor">
<rect id="矩形" x="0" y="0" width="12" height="1.5"></rect>
<rect id="矩形备份-13" x="1.71428571" y="10" width="8.57142857" height="1.5"></rect>
<rect id="矩形备份-7" x="2.57142857" y="5" width="6.85714286" height="1.5"></rect>
</g>
</g>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 967 B

View File

@ -0,0 +1,15 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="17px" height="16px" viewBox="0 0 17 16" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<g id="11.1终稿" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="图标" transform="translate(-404.000000, -209.000000)">
<g id="字符水平对齐" transform="translate(404.728065, 209.000000)">
<rect id="矩形" x="0" y="0" width="16" height="16"></rect>
<g id="编组-11" transform="translate(2.000000, 2.000000)" fill="currentColor">
<rect id="矩形" x="0" y="0" width="12" height="1.5"></rect>
<rect id="矩形备份-13" x="0" y="10" width="12" height="1.5"></rect>
<rect id="矩形备份-7" x="0" y="5" width="12" height="1.5"></rect>
</g>
</g>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 933 B

View File

@ -0,0 +1,13 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="17px" height="16px" viewBox="0 0 17 16" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<g id="11.1终稿" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="图标" transform="translate(-290.000000, -209.000000)">
<g id="字符左对齐" transform="translate(290.455199, 209.000000)">
<rect id="矩形" x="0" y="0" width="16" height="16"></rect>
<rect id="矩形" fill="currentColor" x="2" y="2" width="12" height="1.5"></rect>
<rect id="矩形备份-13" fill="currentColor" x="2" y="12" width="8.57142857" height="1.5"></rect>
<rect id="矩形备份-7" fill="currentColor" x="2" y="7" width="6.85714286" height="1.5"></rect>
</g>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 876 B

View File

@ -0,0 +1,15 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="17px" height="16px" viewBox="0 0 17 16" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<g id="11.1终稿" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="图标" transform="translate(-368.000000, -209.000000)">
<g id="字符右对齐" transform="translate(368.728065, 209.000000)">
<rect id="矩形" x="0" y="0" width="16" height="16"></rect>
<g id="编组-11" transform="translate(2.000000, 2.000000)" fill="currentColor">
<rect id="矩形" x="0" y="0" width="12" height="1.5"></rect>
<rect id="矩形备份-13" x="3.42857143" y="10" width="8.57142857" height="1.5"></rect>
<rect id="矩形备份-7" x="5.14285714" y="5" width="6.85714286" height="1.5"></rect>
</g>
</g>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 964 B

View File

@ -0,0 +1,12 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="16px" height="16px" viewBox="0 0 16 16" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<g id="11.1终稿" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="图标" transform="translate(-189.000000, -209.000000)">
<g id="字符下划线" transform="translate(189.000000, 209.000000)">
<rect id="矩形备份-9" opacity="0.5" x="0" y="0" width="16" height="16"></rect>
<path d="M8.20648148,11.5205022 C9.54685185,11.5205022 10.5735185,11.1595647 11.3007407,10.4665647 C12.027963,9.75912719 12.3987037,8.73406469 12.3987037,7.39137719 L12.3987037,1.75435242 L10.8444444,1.75435242 L10.8444444,7.42025219 C10.8444444,8.34425219 10.6305556,9.02281469 10.217037,9.47037719 C9.78925926,9.91793969 9.11907407,10.1489397 8.20648148,10.1489397 C7.27962963,10.1489397 6.60944444,9.91793969 6.18166667,9.47037719 C5.75388889,9.02281469 5.55425926,8.34425219 5.55425926,7.42025219 L5.55425926,1.75435242 L4,1.75435242 L4,7.39137719 C4,8.73406469 4.37074074,9.75912719 5.11222222,10.4810022 C5.82518519,11.1740022 6.85185185,11.5205022 8.20648148,11.5205022 Z" id="U" fill="currentColor" fill-rule="nonzero"></path>
<rect id="矩形" fill="currentColor" x="3" y="12.7543524" width="10.1851852" height="1.546875"></rect>
</g>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.4 KiB

View File

@ -0,0 +1,15 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="16px" height="16px" viewBox="0 0 16 16" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<g id="11.1终稿" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="图标" transform="translate(-192.000000, -137.000000)">
<g id="编组-24" transform="translate(192.000000, 137.000000)">
<rect id="矩形" x="0" y="0" width="16" height="16"></rect>
<g id="编组" transform="translate(2.750000, 1.333333)" stroke="#5C5F66" stroke-linejoin="round" stroke-width="1.5">
<rect id="矩形" x="0" y="6.01586653" width="10.5" height="7.33333333" rx="0.666666667"></rect>
<path d="M1.91666495,6 L1.91666495,3.33489986 C1.91493333,1.62340653 3.22423333,0.189059864 4.9453,0.0170565308 C6.66633333,-0.154946803 8.2391,0.991359864 8.58333333,2.6686332" id="路径" stroke-linecap="round"></path>
<line x1="5.25" y1="8.66666653" x2="5.25" y2="10.6666665" id="路径" stroke-linecap="round"></line>
</g>
</g>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.1 KiB

View File

@ -0,0 +1,12 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="17px" height="16px" viewBox="0 0 17 16" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<g id="11.1终稿" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="图标" transform="translate(-513.000000, -209.000000)">
<g id="字符低对齐" transform="translate(521.728065, 217.000000) scale(1, -1) translate(-521.728065, -217.000000) translate(513.728065, 209.000000)">
<rect id="矩形" transform="translate(8.000000, 8.000000) scale(1, -1) translate(-8.000000, -8.000000) " x="0" y="0" width="16" height="16"></rect>
<rect id="矩形" fill="currentColor" x="2" y="3.77398484" width="12" height="1.5"></rect>
<polyline id="路径-5" stroke="currentColor" stroke-width="1.5" points="5.57080651 10.3385561 8 8 10.4291935 10.3385561"></polyline>
</g>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 976 B

View File

@ -0,0 +1,13 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="17px" height="16px" viewBox="0 0 17 16" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<g id="11.1终稿" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="图标" transform="translate(-477.000000, -209.000000)">
<g id="字符垂直居中对齐" transform="translate(477.728065, 209.000000)">
<rect id="矩形" x="0" y="0" width="16" height="16"></rect>
<rect id="矩形" fill="currentColor" x="2" y="7.25" width="12" height="1.5"></rect>
<polyline id="路径-5" stroke="currentColor" stroke-width="1.5" points="5.57080651 13.8145713 8 11.4760152 10.4291935 13.8145713"></polyline>
<polyline id="路径-5备份" stroke="currentColor" stroke-width="1.5" transform="translate(8.000000, 3.354707) scale(1, -1) translate(-8.000000, -3.354707) " points="5.57080651 4.52398484 8 2.18542875 10.4291935 4.52398484"></polyline>
</g>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.0 KiB

View File

@ -0,0 +1,12 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="17px" height="16px" viewBox="0 0 17 16" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<g id="11.1终稿" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="图标" transform="translate(-441.000000, -209.000000)">
<g id="字符顶对齐" transform="translate(441.728065, 209.000000)">
<rect id="矩形" x="0" y="0" width="16" height="16"></rect>
<rect id="矩形" fill="currentColor" x="2" y="5.37983306" width="12" height="1.5"></rect>
<polyline id="路径-5" stroke="currentColor" stroke-width="1.5" points="5.57080651 11.9444043 8 9.60584823 10.4291935 11.9444043"></polyline>
</g>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 814 B

View File

@ -0,0 +1,10 @@
export * from './helper/ColorGenerator';
export * from './helper/ParseThemeData';
export * from './helper/declares';
export * from './helper/getGlobalData';
export * from './helper/styleOperation';
export * from './systemTheme/index';
export * from './helper/styleHelper';
export * from './renderers/index';
import './locale/index';
import './style/index.scss';

View File

@ -0,0 +1,233 @@
import {extendLocale} from 'i18n-runtime';
extendLocale('en-US', {
'8f6ea8f1a35f96ba401e4fce9ddeb4b0':
'Please pass in the hexadecimal color value',
'fbae87bcc352f6933541fb77a07418ed': 'Primary color',
'22b777e6fcb613b8ba83ced9594cd07e': 'Ordinary',
'4363c17ebb346b646af55bd8c8075915': 'Click',
'062d0b688adb10f3af5ebc2fd2667f1c': 'Floating',
'8e1b944f4389bdaab6f11d5bc83190c8': 'Background',
'd5fa0ac3fb033291acadd025db40cf8c': 'Highlight/text title',
'7835fd1dece3cf3750cb0db039b2ae73': 'Sub-highlight/text title',
'b97ef9fe546e82e4b5f84661006a8ca7': 'Secondary information',
'54c155a9c985b0244666f36abe342b7a': 'Gray information',
'8318e9299a55c306333b4a2a43dbb6e2': 'Stroke/Divide Line',
'9f83cbd8f26e028346ecb459c4be9c01': 'Card background color',
'1110ba0bda5a251c55247f122e923848': 'transparent',
'2b250fe214bc8b93fb78d795a47d7a6c': 'Brand color',
'af09bd51b66a26d8db3119e95b5d28fe': 'Neutral color',
'b6c3e2dcf4053e5f24d15b63a29f5afd': 'Auxiliary color',
'a2de03c5b7ec653d8eadaeeb9043d41a': 'Size {{@1}} ({{@2}})',
'cc4c575642609fbf059a5df81eb86bfc': 'Solid line',
'61f6f4fc0b806ac9d41ad0792e6155f6': 'Dashed line',
'b1e0ebac23ed95807ecc566da3ffab48': 'Dotted line',
'd81bb206a889656035b929cd8bb1ef10': 'nothing',
'e0dfa25ebceabddb2180720d36d4c3b6': 'border-top ',
'a8b0c20416853bda54120bf19477ad11': 'whole',
'a80a25b59908402cf7ee31a07d0e7739': 'border-left ',
'57463587977a534f7859eb9d7c536629': 'border-right ',
'154d5216e42c916884431f0eea951999': 'bottom',
'a4f758412c3797290c957544c56db443': 'Inherit General',
'd8a4e8cdc29e9aa576e669ed165892c9': 'Configure separately',
'aa05fd09a619ddbf07d8d903e6d32c5e': 'currency',
'ee5841a88da34c5a0e0515c4d863752a': 'Transparent',
'517c1de3f9f069c1c33003ec8d75c3da': 'Enter color values or name search',
'd6a80fc3f53d0b11e5f96a538b096c06': 'Color not matched',
'c7706039e8ad85969df13ce3458d199a': 'Gradient angle',
'21f3929a4484e6e992af64ec1dd3a576': 'Original size',
'0f1fd39145bad43e18f81337e0144c8c': 'Full of',
'e0d76824dfe5e09c7068b44f605266d2': 'appropriate',
'e39d3b7a3600d9327221a637f910fc0b': 'stretching',
'e1ff2c83c09f2dc6cc74ae02ab6b8222': 'Tile',
'7ddd9dbf373f760acfd63778469b5c4b': 'Horizontal tiling',
'4ab931e0f709f9b493e660156925a113': 'Tile Vertically',
'61a87a021904dc65995e99d4c476cb21': 'Image position',
'7778401c65bfef9c0ad4d543e3b5b310': 'Common Colors',
'769d88e425e03120b83ee4ed6b9d588e': 'complete',
'95b351c86267f3aedf89520959bce689': 'edit',
'ec8baa57611b5a89a37b31c7432a01d7': 'Click on the color above to add',
'a1c76c6e1bd796959e536718e04d10ca': 'Theme Colors',
'255f442c4a1b92624a6e96541202a0be': 'Custom Colors',
'879f4e7bd863a00f77d30f05076ac6cb': '1.3x',
'4905c69b940b0d94cf8aec83bc8dcc83': '1.5x',
'268c43e529c54fb458397b9c13351a67': '1.7x',
'efb399e557c1f444ba215c8e2dbfb891': 'Bold Simplified',
'4e9edbb054a1fc52fe2012ff8cb3b20e': 'Blackbody Complex',
'bd8e7ebd31bd804a20986f7dd3739900': 'Holly Black Simplified Chinese',
'd55a1b98030839c3ce3606d7d2c80235': 'Pingfang Hong Kong',
'c9045965fa0fbf29323518d79c9da0f1': 'Ping Fang Jian',
'c1ef096e25d96c451fd39c172b3f569a': 'Pingfang Fanfan',
'09e4d5659a11cf8a55f59e867b30ab75': 'Song typeface - Simplified Chinese',
'56d3dcaab79fe10dfbc4b80f0d9d72a4': 'Song typeface complex',
'2c1605abdc63ac897a76aeba5dcf36a4': 'Chinese Bold',
'db37a0bd2e60503e939e8eee02511550': 'Chinese Song typeface',
'81d6da77d656c6a9c3cbd795ae4444ea': 'italic',
'f6f8ea0815881fe9a4aa9352a7fe2299': 'Underline',
'a120a873412470089bec1dfd1b581fc9': 'Strikethrough',
'413f48cc71f71083ce532a86e3efdc21': 'Align Left',
'56c17ba6a56c01706ae00a31611deb03': 'Align Center',
'fd8e9572cc6bf87653c4d8f8b8dd0db9': 'Align Right',
'da1b972efb29f850b50e219ad4d98ba5': 'Align Both Ends',
'2af8c8235ae57c6a7486883f86701ab3': 'Top alignment',
'8bc0ba58bf73b03668ca9b6a74c99f89': 'align vertical center',
'a6d154c4db5068074e32863821c450e1': 'Bottom ',
'9c07532d0c9acfecfc4ec2eb265c3e03': 'character',
'c988dd65ce45c335db5c4354eec7c110': 'Word weight',
'17169fd8c2ffa82c4e1d08e7267725f4': 'Row height',
'8456bc40d48da5af833f1c63385e9879': 'font',
'df68a5dc8f8847179b7afdf943f80796': 'Upper left corner',
'e717b4ae480e7c073fd5a44647a7f0da': 'Upper right corner',
'2a97dfb2d236c87c41fd588f006111dc': 'Lower left corner',
'1c9bc9dab33944e953412f8b22cb024a': 'Lower right corner',
'9cf15d01ed2846c4104d1607836bbe79': 'Shadow preview',
'f1d4ff50f3828f9b73412e7d94e6dd6e': 'custom',
'803205e38834280d9e6a75993ac00764': 'shadow',
'6f9c7d7109f2b4b5a759359a455201e9': 'No Shadow',
'26db990dad6d76c6725375b24c0941e1': 'Shadow layer',
'b24a723b73f96ab3340fe9502370ee13': 'Inner Shadow',
'92d393c2ae53f424856479d090de718f': 'External genitalia shadow',
'203bab8001257b60e1aed951a0939393': 'vague',
'2dc90225b8033d17c41b08f39fa42de2': 'extend',
'48110cb1579623335cf6a1e2327e5af1': 'Lock Scale',
'17399f02e23b5f5b9b3dedee03a2d538': 'Unlock',
'a2b62974f4d7564bb68b570116f25a10': 'Minimum width',
'e4e625f8f933ccfd0fe44a41fb02655f': 'Extended Configuration',
'3e42b9d1f06cd5ad39c37d93fd98329d': 'Imitate Antd',
'00a42062d24846499934cf5c753aedfe': 'Platform preset themes',
'1c61673194f8543ead4128ce52a79f5f': 'Basic font',
'94d322455c11e7666f5448ce1c4c14cd': 'Operations Title - Large',
'e291cdc6b012b1ed5b8243fdaa44c204': 'Operations Title - Medium',
'd20e34eb25d164b3a868e12b710b9a27': 'Operations Title - Small',
'701a94041742976d6f5ebf2450b60ed2': 'Title - Large',
'cae9d44e7f6bb7fc305ed3ed97d420a9': 'Title - Middle',
'39a7ffed69e7f163bb0b163af441a4a3': 'Title - Small',
'15d1505fc16b73315b2a0e2a923743b6': 'Body General Large',
'64de1d8e51342a0de719f676a8ae5d15': 'Body General Small',
'deefca7e66ebaac1ed4f27655961286c': 'Watermark Text',
'fc55aff8c7e01416e93ac218d98b3b74': 'Font size',
'f72ce9ad683cc82e0eab557ffc9c67a0': 'Extra small',
'23ecf42cada8bf2715792d718544d107': 'minimum',
'391b8fa9c747a1799353ab856e666ad5': 'small',
'fd6e80f1e0199d6ecc3ee81ae04aa9ef': 'normal',
'aed1dfbc31703955e64806b799b67645': 'in',
'ab18e30c0dc4093ceeda8961fac3d1f4': 'large',
'973d9d0bcdbcdbec6de879c1572c2300': 'maximum',
'3386da5f56fac758ed0f18e024ecb943': 'Extra large',
'c8339fd2a85af4ba66084d28df808de4': 'size',
'82832013777f9ec3a3406c0f771ddbc1': 'Failure Color',
'07d5f1fb5d239633dc4b2ddce27b52de': 'Warning color',
'd2775b9d4d00a2ca7414635618c6e802': 'Success Color',
'd3770b4e046c533df1946eb5a2763a54': 'Link Color',
'6b5040281083fce17fd3e8006d9a7cc3': 'Prompt color',
'cf4d9e177b415e58c29371b9b22f3390': 'Other colors',
'4b4dc05ed0aa65da0abdb8cb92ae1fb3': 'Auxiliary instructions',
'710ad08b11419332713360d2750cd707': 'Disabled',
'35796bb8ca4342a4390dfb3c464bebb4': 'Pure white text',
'ca746b1ff10193a3ce20878dec04a733': 'characters',
'2a03e7cc0afd5fc3519cd06bf59b538f': 'Pure white filling',
'da3cfffa69723748fecfc8e964b7996e': 'Light/Disable Background',
'8c47ecd40d7f739e308567de89accd56': 'Division line',
'40fab37fcc50ecd7d9a570a24757a503': 'Deep/gray bottom suspension',
'756e44b36d4d962cef2732db02aefdd1': 'filling',
'b37c14c49311fc0cd3288af9925808c8': 'shallow',
'21ac5a493ae8ab9bba043ca126433ca9': 'deep',
'fa7132688004917a89ed807b5be00d27': 'heavy',
'84fe608676a8fe47637b824434cb225d': 'line',
'328215447d0e128a845729dab5ce9837': 'Data color',
'18c63459a2c069022c7790430f761214': 'default',
'e7c37575b8b33fca7c8e94f712aa2385': 'classical',
'fb2936372e13759bd6a6e113fcbafb68': 'transition',
'39003734d1d700d5bd97bf1e7a2fcf73': 'style',
'48d67284c554350eea37fc8762e447a1': 'Medium thick',
'804c19b95172c55f1796babbbb770899': 'Extra thick',
'fb0af8105da1f0f57ce265340239a376': 'thickness',
'c121ed6712e8231da4e3803e6eaf703c': 'Fillet 1',
'ae15c0d31ae01fcea65b7e483f1b942d': 'Fillet 2',
'829fbc73be5187c3f3d4e403e8cbecbc': 'Fillet 3',
'a797a13eef06c6b3ea2d52f60d216259': 'Fillet 4',
'c02a7a69675e7cf1abeae6d279670471': 'Fillet 5',
'f4276b865c626bb67ac41013c6da0317': 'Fillet 6',
'0103eb2d3dca70270d1a74e9ec987ac9': 'fillet',
'efababbf5f440be0e19e40f4369b5ac1': 'Shadow sm',
'658cd4f2239e0d04e596ec1f65d5f9df': 'Shadow MD',
'940e477cb0b6a7a847862db402b79c07': 'Shadow lg',
'9ed233fc6677d73b458d45b250ecc3a1': 'Shadow xl',
'c08787dc714fd5d7b2a1217b3d4afe8d': 'Shadow 2xl',
'b3bb412da3c93f51b935c5df4759b7a6': 'Default General',
'77602d53a9b948cb43c9affb46ea4a6f': 'Default levitation',
'62c5ed2938e91f0589e6333d9c5c124f': 'Default click',
'b3dad626b64ac5063c6a1e88f8a88322': 'Disabled by default',
'00dc03d70dd2321afa1c18b2186e7e2b': 'main',
'bde770827b9137ddb3eb676878af9709': 'secondary',
'9a5e272968e173fb42c66a56eb93e4a7': 'enhance',
'd8c7e04c8e2be23dd3b81a31db6e04f1': 'information',
'330363dfc524cff2488f2ebde0500896': 'success',
'900c70fa5f7dbc014e6f762d5e0e885c': 'warning',
'540f84ddc0883866b229f71c2844199a': 'danger',
'48d0a09bdd5fe7e89f0a445b0ffdf14f': 'Light color',
'41e8e8b9935c9ee4e88b06643a2d5b81': 'Dark color',
'bfe68d5844f8e54602760e18f45954f7': 'link',
'eadd05ba6a99ca43492efe5dad7325ad': 'secondary',
'b6453aea1848b65a9a76cccca94715ec': 'Basic configuration',
'c3e817974de836e80c95cc6ce5718eff': 'Search box',
'829abe5a8dcd0579a340d20636b59276': 'grouping',
'd58ba4b5e94680fcb08300e176502fb8': 'Tabular form',
'7600db82433e763d16e3f1e91aa4ab80': 'Tree form',
'd2fedacfc0f313fcc5d0a24d4d6d81db': 'Cascade selection',
'09bbfb387dce6201df1ccef2aab161a6': 'Clearable',
'94621f44f98c996e49d5b214aebefffc': 'word count ',
'56f40e132c8369340439255fa1073070': 'Single line input box',
'8685115115e4f8c8daf97a31528721ff': 'Multiline input box',
'57d14839d1098d99811f44d68dd0957e': 'Prefix/Suffix',
'055293fb3cf2b1fcbc60317a2ae6916a': 'Password input box',
'67b958a2d172f2b3474629f9f6724109': 'Additional components',
'97d07614380da93d257f9fbf81aa56fb': 'text',
'e1371d733ff347664655629011b4130f': 'Basic Style',
'6d609769ad11b37dd509ec06362f0b73': 'Enhanced version',
'3e08fbf3806981c18666fff59718c85c': 'With unit selection',
'ec1323a8ba34dd36b33e4e6baf22f076': 'Unit selector',
'f99484b21ba7a64a748c60b52ea0401e': 'Column display',
'd58a55bceec7591f43232e958928ed10': 'shut',
'8493205602379573013b8d3335981175': 'open',
'911bafa046cd76ecbc80ae199bd4a6e8': 'Switch Description',
'fb090c01ee012eac2bb26751aeb5a3c4': 'Switch status text',
'c4b07f2e6b60c5752a70551ff77ccedf': 'Default state',
'db98f889ce6bc235e66bd4b2a788d137': 'check box',
'5ef69f62dc668c1a3e68b51c50a2530a': 'icon',
'6bfb9bb2218ff32b6139e98bc93707c0': 'Image upload',
'443f46c76ebe6ec4eb502f95c451e4b0': 'Multiple Choice',
'73e0299c2fb3a564af0a7cff42540542': 'Group mode',
'0e2eeb150583b23ed4234d58b81c18e4': 'Table Mode',
'c2981042c21c8b5fa4451337d484d7db': 'Tree mode',
'df011658c33f610e9b9d3302909a7f2b': 'range',
'4092ed98e9035652d4c9ca9441701ed7': 'basic',
'3fea7ca76cdece641436d7ab0d02ab1b': 'state',
'528c13332418466dba644a1bde0d1fdd': 'Punctate',
'eedfc4d3b93ca4831e94efa2ac3be6f8': 'Simple mode',
'0796ba76b4b553687e5ffaeb78512ccb': 'basis',
'035692d6fc368765e391602aad0bf39a': 'Add Icon',
'ea15ae2b7fba76c83eec6d0986d15197': 'option',
'b05a75d95e71561fccc84306c95388e0': 'Popup Options',
'02d9819ddaaaeb1b7b22b12608c7e5ca': 'prompt',
'19de37513f3cb55919d32c0d559a0559': 'Small size',
'8aa7e04f48d51d5cd37ca94866187904': 'Normal size',
'21814e10b7abc9e05e6fc3b505b34844': 'Large size',
'2009e3d873e6f5e0978b1e123692c024': 'Facial labels',
'8cc6e3e65831f4e034d2a9ce6c68863a': 'Linear label',
'507d869237db8b0c47b07bdf824d4ae2': 'Status label',
'01f2895cef02a670e0268e1f97ee9445': 'Color status',
'a465db53b8c98f42caa15ca5662f9c90': 'direction',
'533fbb06156c17f0040128567708d23e': 'Configure different states',
'240210b3088bcbea7588047000e89d9e': 'Default Style',
'16a20243f9b741c08216dc9548de2968': 'whole',
'3bdd08adab6ea90b9164b20a0e4151ac': 'describe',
'3fca5e5be30a99b8ca5e14173773f47c': 'Picture Item',
'32c65d8d7431e76029678ec7bb73a5ab': 'title',
'e84ef1c5e5128107492f6813fa9a396b': 'Custom Columns',
'1f23b9dd74b629ba5bfd5eaf8e2f498d': 'Large size',
'c0215e2abf0fe27597acba2be64f6993': 'Small size',
'93dee976f68681ec6950380d757d8c18': 'Multiple selection mode',
'9be232c5cffa019aab21bd631ff23462': 'Yunshe',
'1dfba2e7e2df2efc4a25f4f2adcba25e': 'System preset theme'
});

View File

@ -0,0 +1,2 @@
import './en-US';
import './zh-CN';

View File

@ -0,0 +1,232 @@
import {extendLocale} from 'i18n-runtime';
extendLocale('zh-CN', {
'8f6ea8f1a35f96ba401e4fce9ddeb4b0': '请传入十六进制色值',
'fbae87bcc352f6933541fb77a07418ed': '主色',
'22b777e6fcb613b8ba83ced9594cd07e': '常规',
'4363c17ebb346b646af55bd8c8075915': '点击',
'062d0b688adb10f3af5ebc2fd2667f1c': '悬浮',
'8e1b944f4389bdaab6f11d5bc83190c8': '背景',
'd5fa0ac3fb033291acadd025db40cf8c': '强调/正文标题',
'7835fd1dece3cf3750cb0db039b2ae73': '次强调/正文标题',
'b97ef9fe546e82e4b5f84661006a8ca7': '次要信息',
'54c155a9c985b0244666f36abe342b7a': '置灰信息',
'8318e9299a55c306333b4a2a43dbb6e2': '描边/分割线',
'9f83cbd8f26e028346ecb459c4be9c01': '卡片背景色',
'1110ba0bda5a251c55247f122e923848': '透明',
'2b250fe214bc8b93fb78d795a47d7a6c': '品牌色',
'af09bd51b66a26d8db3119e95b5d28fe': '中性色',
'b6c3e2dcf4053e5f24d15b63a29f5afd': '辅助色',
'a2de03c5b7ec653d8eadaeeb9043d41a': '尺寸{{@1}}({{@2}})',
'cc4c575642609fbf059a5df81eb86bfc': '实线',
'61f6f4fc0b806ac9d41ad0792e6155f6': '虚线',
'b1e0ebac23ed95807ecc566da3ffab48': '点线',
'd81bb206a889656035b929cd8bb1ef10': '无',
'e0dfa25ebceabddb2180720d36d4c3b6': '上边框',
'a8b0c20416853bda54120bf19477ad11': '全部',
'a80a25b59908402cf7ee31a07d0e7739': '左边框',
'57463587977a534f7859eb9d7c536629': '右边框',
'154d5216e42c916884431f0eea951999': '下边框',
'a4f758412c3797290c957544c56db443': '继承常规',
'd8a4e8cdc29e9aa576e669ed165892c9': '分别配置',
'aa05fd09a619ddbf07d8d903e6d32c5e': '通用',
'ee5841a88da34c5a0e0515c4d863752a': '透明-transparent',
'517c1de3f9f069c1c33003ec8d75c3da': '输入色值或名称搜索',
'd6a80fc3f53d0b11e5f96a538b096c06': '未匹配到颜色',
'c7706039e8ad85969df13ce3458d199a': '渐变角度',
'21f3929a4484e6e992af64ec1dd3a576': '原始尺寸',
'0f1fd39145bad43e18f81337e0144c8c': '充满',
'e0d76824dfe5e09c7068b44f605266d2': '合适',
'e39d3b7a3600d9327221a637f910fc0b': '拉伸',
'e1ff2c83c09f2dc6cc74ae02ab6b8222': '平铺',
'7ddd9dbf373f760acfd63778469b5c4b': '横向平铺',
'4ab931e0f709f9b493e660156925a113': '纵向平铺',
'61a87a021904dc65995e99d4c476cb21': '图片位置',
'7778401c65bfef9c0ad4d543e3b5b310': '常用颜色',
'769d88e425e03120b83ee4ed6b9d588e': '完成',
'95b351c86267f3aedf89520959bce689': '编辑',
'ec8baa57611b5a89a37b31c7432a01d7': '点击上方颜色添加',
'a1c76c6e1bd796959e536718e04d10ca': '主题颜色',
'255f442c4a1b92624a6e96541202a0be': '自定义颜色',
'879f4e7bd863a00f77d30f05076ac6cb': '1.3倍',
'4905c69b940b0d94cf8aec83bc8dcc83': '1.5倍',
'268c43e529c54fb458397b9c13351a67': '1.7倍',
'efb399e557c1f444ba215c8e2dbfb891': '黑体-简',
'4e9edbb054a1fc52fe2012ff8cb3b20e': '黑体-繁',
'bd8e7ebd31bd804a20986f7dd3739900': '冬青黑体简体中文',
'd55a1b98030839c3ce3606d7d2c80235': '苹方-港',
'c9045965fa0fbf29323518d79c9da0f1': '苹方-简',
'c1ef096e25d96c451fd39c172b3f569a': '苹方-繁',
'09e4d5659a11cf8a55f59e867b30ab75': '宋体-简',
'56d3dcaab79fe10dfbc4b80f0d9d72a4': '宋体-繁',
'2c1605abdc63ac897a76aeba5dcf36a4': '华文黑体',
'db37a0bd2e60503e939e8eee02511550': '华文宋体',
'81d6da77d656c6a9c3cbd795ae4444ea': '斜体',
'f6f8ea0815881fe9a4aa9352a7fe2299': '下划线',
'a120a873412470089bec1dfd1b581fc9': '删除线',
'413f48cc71f71083ce532a86e3efdc21': '左对齐',
'56c17ba6a56c01706ae00a31611deb03': '居中对齐',
'fd8e9572cc6bf87653c4d8f8b8dd0db9': '右对齐',
'da1b972efb29f850b50e219ad4d98ba5': '两端对齐',
'2af8c8235ae57c6a7486883f86701ab3': '顶对齐',
'8bc0ba58bf73b03668ca9b6a74c99f89': '垂直居中对齐',
'a6d154c4db5068074e32863821c450e1': '底对齐',
'9c07532d0c9acfecfc4ec2eb265c3e03': '字符',
'c988dd65ce45c335db5c4354eec7c110': '字重',
'17169fd8c2ffa82c4e1d08e7267725f4': '行高',
'8456bc40d48da5af833f1c63385e9879': '字体',
'df68a5dc8f8847179b7afdf943f80796': '左上角',
'e717b4ae480e7c073fd5a44647a7f0da': '右上角',
'2a97dfb2d236c87c41fd588f006111dc': '左下角',
'1c9bc9dab33944e953412f8b22cb024a': '右下角',
'9cf15d01ed2846c4104d1607836bbe79': '阴影预览',
'f1d4ff50f3828f9b73412e7d94e6dd6e': '自定义',
'803205e38834280d9e6a75993ac00764': '阴影',
'6f9c7d7109f2b4b5a759359a455201e9': '无阴影',
'26db990dad6d76c6725375b24c0941e1': '阴影层',
'b24a723b73f96ab3340fe9502370ee13': '内阴影',
'92d393c2ae53f424856479d090de718f': '外阴影',
'203bab8001257b60e1aed951a0939393': '模糊',
'2dc90225b8033d17c41b08f39fa42de2': '扩展',
'48110cb1579623335cf6a1e2327e5af1': '锁定比例',
'17399f02e23b5f5b9b3dedee03a2d538': '解除锁定',
'a2b62974f4d7564bb68b570116f25a10': '最小宽度',
'e4e625f8f933ccfd0fe44a41fb02655f': '扩展配置',
'3e42b9d1f06cd5ad39c37d93fd98329d': '仿Antd',
'00a42062d24846499934cf5c753aedfe': '平台预设主题',
'1c61673194f8543ead4128ce52a79f5f': '基础字体',
'94d322455c11e7666f5448ce1c4c14cd': '运营标题-大',
'e291cdc6b012b1ed5b8243fdaa44c204': '运营标题-中',
'd20e34eb25d164b3a868e12b710b9a27': '运营标题-小',
'701a94041742976d6f5ebf2450b60ed2': '标题-大',
'cae9d44e7f6bb7fc305ed3ed97d420a9': '标题-中',
'39a7ffed69e7f163bb0b163af441a4a3': '标题-小',
'15d1505fc16b73315b2a0e2a923743b6': '正文-常规-大',
'64de1d8e51342a0de719f676a8ae5d15': '正文-常规-小',
'deefca7e66ebaac1ed4f27655961286c': '水印文字',
'fc55aff8c7e01416e93ac218d98b3b74': '字号',
'f72ce9ad683cc82e0eab557ffc9c67a0': '特小',
'23ecf42cada8bf2715792d718544d107': '极小',
'391b8fa9c747a1799353ab856e666ad5': '小',
'fd6e80f1e0199d6ecc3ee81ae04aa9ef': '正常',
'aed1dfbc31703955e64806b799b67645': '中',
'ab18e30c0dc4093ceeda8961fac3d1f4': '大',
'973d9d0bcdbcdbec6de879c1572c2300': '极大',
'3386da5f56fac758ed0f18e024ecb943': '特大',
'c8339fd2a85af4ba66084d28df808de4': '尺寸',
'82832013777f9ec3a3406c0f771ddbc1': '失败色',
'07d5f1fb5d239633dc4b2ddce27b52de': '警告色',
'd2775b9d4d00a2ca7414635618c6e802': '成功色',
'd3770b4e046c533df1946eb5a2763a54': '链接色',
'6b5040281083fce17fd3e8006d9a7cc3': '提示色',
'cf4d9e177b415e58c29371b9b22f3390': '其他色',
'4b4dc05ed0aa65da0abdb8cb92ae1fb3': '辅助说明',
'710ad08b11419332713360d2750cd707': '禁用',
'35796bb8ca4342a4390dfb3c464bebb4': '纯白文字',
'ca746b1ff10193a3ce20878dec04a733': '文字',
'2a03e7cc0afd5fc3519cd06bf59b538f': '纯白填充',
'da3cfffa69723748fecfc8e964b7996e': '浅/禁用背景',
'8c47ecd40d7f739e308567de89accd56': '分割线',
'40fab37fcc50ecd7d9a570a24757a503': '深/灰底悬浮',
'756e44b36d4d962cef2732db02aefdd1': '填充',
'b37c14c49311fc0cd3288af9925808c8': '浅',
'21ac5a493ae8ab9bba043ca126433ca9': '深',
'fa7132688004917a89ed807b5be00d27': '重',
'84fe608676a8fe47637b824434cb225d': '线条',
'328215447d0e128a845729dab5ce9837': '数据色',
'18c63459a2c069022c7790430f761214': '默认',
'e7c37575b8b33fca7c8e94f712aa2385': '经典',
'fb2936372e13759bd6a6e113fcbafb68': '过渡',
'39003734d1d700d5bd97bf1e7a2fcf73': '样式',
'48d67284c554350eea37fc8762e447a1': '中粗',
'804c19b95172c55f1796babbbb770899': '特粗',
'fb0af8105da1f0f57ce265340239a376': '粗细',
'c121ed6712e8231da4e3803e6eaf703c': '圆角1',
'ae15c0d31ae01fcea65b7e483f1b942d': '圆角2',
'829fbc73be5187c3f3d4e403e8cbecbc': '圆角3',
'a797a13eef06c6b3ea2d52f60d216259': '圆角4',
'c02a7a69675e7cf1abeae6d279670471': '圆角5',
'f4276b865c626bb67ac41013c6da0317': '圆角6',
'0103eb2d3dca70270d1a74e9ec987ac9': '圆角',
'efababbf5f440be0e19e40f4369b5ac1': '阴影sm',
'658cd4f2239e0d04e596ec1f65d5f9df': '阴影md',
'940e477cb0b6a7a847862db402b79c07': '阴影lg',
'9ed233fc6677d73b458d45b250ecc3a1': '阴影xl',
'c08787dc714fd5d7b2a1217b3d4afe8d': '阴影2xl',
'b3bb412da3c93f51b935c5df4759b7a6': '默认常规',
'77602d53a9b948cb43c9affb46ea4a6f': '默认悬浮',
'62c5ed2938e91f0589e6333d9c5c124f': '默认点击',
'b3dad626b64ac5063c6a1e88f8a88322': '默认禁用',
'00dc03d70dd2321afa1c18b2186e7e2b': '主要',
'bde770827b9137ddb3eb676878af9709': '次要',
'9a5e272968e173fb42c66a56eb93e4a7': '增强',
'd8c7e04c8e2be23dd3b81a31db6e04f1': '信息',
'330363dfc524cff2488f2ebde0500896': '成功',
'900c70fa5f7dbc014e6f762d5e0e885c': '警告',
'540f84ddc0883866b229f71c2844199a': '危险',
'48d0a09bdd5fe7e89f0a445b0ffdf14f': '浅色',
'41e8e8b9935c9ee4e88b06643a2d5b81': '深色',
'bfe68d5844f8e54602760e18f45954f7': '链接',
'eadd05ba6a99ca43492efe5dad7325ad': '中等',
'b6453aea1848b65a9a76cccca94715ec': '基础配置',
'c3e817974de836e80c95cc6ce5718eff': '搜索框',
'829abe5a8dcd0579a340d20636b59276': '分组',
'd58ba4b5e94680fcb08300e176502fb8': '表格形式',
'7600db82433e763d16e3f1e91aa4ab80': '树形式',
'd2fedacfc0f313fcc5d0a24d4d6d81db': '级联选择',
'09bbfb387dce6201df1ccef2aab161a6': '可清除',
'94621f44f98c996e49d5b214aebefffc': '字数统计',
'56f40e132c8369340439255fa1073070': '单行输入框',
'8685115115e4f8c8daf97a31528721ff': '多行输入框',
'57d14839d1098d99811f44d68dd0957e': '前缀/后缀',
'055293fb3cf2b1fcbc60317a2ae6916a': '密码输入框',
'67b958a2d172f2b3474629f9f6724109': '附加组件',
'97d07614380da93d257f9fbf81aa56fb': '文本',
'e1371d733ff347664655629011b4130f': '基础样式',
'6d609769ad11b37dd509ec06362f0b73': '加强版',
'3e08fbf3806981c18666fff59718c85c': '带单位选择',
'ec1323a8ba34dd36b33e4e6baf22f076': '单位选择器',
'f99484b21ba7a64a748c60b52ea0401e': '列显示',
'd58a55bceec7591f43232e958928ed10': '关',
'8493205602379573013b8d3335981175': '开',
'911bafa046cd76ecbc80ae199bd4a6e8': '开关说明',
'fb090c01ee012eac2bb26751aeb5a3c4': '开关状态文本',
'c4b07f2e6b60c5752a70551ff77ccedf': '默认态',
'db98f889ce6bc235e66bd4b2a788d137': '复选框',
'5ef69f62dc668c1a3e68b51c50a2530a': '图标',
'6bfb9bb2218ff32b6139e98bc93707c0': '图片上传',
'443f46c76ebe6ec4eb502f95c451e4b0': '多选',
'73e0299c2fb3a564af0a7cff42540542': '分组模式',
'0e2eeb150583b23ed4234d58b81c18e4': '表格模式',
'c2981042c21c8b5fa4451337d484d7db': '树模式',
'df011658c33f610e9b9d3302909a7f2b': '范围',
'4092ed98e9035652d4c9ca9441701ed7': '基本',
'3fea7ca76cdece641436d7ab0d02ab1b': '状态',
'528c13332418466dba644a1bde0d1fdd': '点状',
'eedfc4d3b93ca4831e94efa2ac3be6f8': '简单模式',
'0796ba76b4b553687e5ffaeb78512ccb': '基础',
'035692d6fc368765e391602aad0bf39a': '添加图标',
'ea15ae2b7fba76c83eec6d0986d15197': '选项',
'b05a75d95e71561fccc84306c95388e0': '弹窗选项',
'02d9819ddaaaeb1b7b22b12608c7e5ca': '提示',
'19de37513f3cb55919d32c0d559a0559': 'small尺寸',
'8aa7e04f48d51d5cd37ca94866187904': 'normal尺寸',
'21814e10b7abc9e05e6fc3b505b34844': 'large尺寸',
'2009e3d873e6f5e0978b1e123692c024': '面性标签',
'8cc6e3e65831f4e034d2a9ce6c68863a': '线性标签',
'507d869237db8b0c47b07bdf824d4ae2': '状态标签',
'01f2895cef02a670e0268e1f97ee9445': '颜色状态',
'a465db53b8c98f42caa15ca5662f9c90': '方向',
'533fbb06156c17f0040128567708d23e': '配置 不同状态',
'240210b3088bcbea7588047000e89d9e': '默认样式',
'16a20243f9b741c08216dc9548de2968': '整体',
'3bdd08adab6ea90b9164b20a0e4151ac': '描述',
'3fca5e5be30a99b8ca5e14173773f47c': '图片项',
'32c65d8d7431e76029678ec7bb73a5ab': '标题',
'e84ef1c5e5128107492f6813fa9a396b': '自定义列',
'1f23b9dd74b629ba5bfd5eaf8e2f498d': '尺寸大',
'c0215e2abf0fe27597acba2be64f6993': '尺寸小',
'93dee976f68681ec6950380d757d8c18': '多选模式',
'9be232c5cffa019aab21bd631ff23462': '云舍',
'1dfba2e7e2df2efc4a25f4f2adcba25e': '系统预设主题'
});

View File

@ -0,0 +1,343 @@
/**
* @file
* @description
*/
import cx from 'classnames';
import React, {useEffect, useState} from 'react';
import {FormItem} from 'amis-core';
import type {FormControlProps} from 'amis-core';
import cloneDeep from 'lodash/cloneDeep';
import {Select} from 'amis-ui';
import ColorPicker from './ColorPicker';
import ThemeSelect from './ThemeSelect';
import {i18n as _i18n} from 'i18n-runtime';
import {
getValueByPath,
getInheritValue,
formatInheritData,
setInheritData
} from '../util';
interface BorderProps {
custom?: boolean;
needColorCustom?: boolean;
}
interface Options {
label: string;
value: string;
realValue?: any;
parent?: boolean;
}
const defaultStyleOptions = [
{
label: '实线',
value: 'solid',
realValue: 'solid'
},
{
label: '虚线',
value: 'dashed',
realValue: 'dashed'
},
{
label: '点线',
value: 'dotted',
realValue: 'dotted'
}
];
const defaultBorderWidthOptions = [
{
value: 'none',
label: '无',
realValue: 'none'
},
{
value: '1px',
label: '1px',
realValue: '1px'
},
{
value: '2px',
label: '2px',
realValue: '2px'
},
{
value: '4px',
label: '4px',
realValue: '4px'
}
];
const borderItems = [
{
item: 'top',
tip: '上边框'
},
{
item: 'all',
tip: '全部'
},
{
item: 'left',
tip: '左边框'
},
{
item: 'right',
tip: '右边框'
},
{
item: 'bottom',
tip: '下边框'
}
];
function BoxBorder(props: BorderProps & FormControlProps) {
const {
onChange,
value = {},
data,
custom,
label,
needColorCustom,
state,
editorThemePath
} = props;
const [borderWidthOptions, setBorderWidthOptions] = useState(
cloneDeep(
props.borderWidthOptions ||
data.borderWidthOptions ||
defaultBorderWidthOptions
)
);
const [borderStyleOptions, setBorderStyleOptions] = useState(
cloneDeep(
props.borderStyleOptions || data.borderStyleOptions || defaultStyleOptions
)
);
const [colorOptions, setColorOptions] = useState(
cloneDeep(props.colorOptions || data.colorOptions)
);
const [borderType, setBorderType] = useState<string>('all');
const editorDefaultValue = formatData(getValueByPath(editorThemePath, data));
const editorInheritValue = getInheritValue(editorThemePath, data);
const borderData = formatData(value || {});
useEffect(() => {
if (state && state !== 'default') {
const type = borderType === 'all' ? 'top' : borderType;
const styleOptions = cloneDeep(borderStyleOptions);
if (styleOptions[0].parent) {
styleOptions[0].value = editorThemePath
? 'inherit'
: `var(${data.default.token}${type}-border-style)`;
styleOptions[0].realValue = '继承常规';
} else {
styleOptions.unshift({
label: '继承常规',
value: editorThemePath
? 'inherit'
: `var(${data?.default?.token}${type}-border-style)`,
parent: true,
realValue: '继承常规'
});
}
setBorderStyleOptions(styleOptions);
}
}, [borderType]);
function formatData(sourceData: any) {
if (!sourceData) {
return null;
}
const data = formatInheritData(cloneDeep(sourceData));
const fn = (type: string) => {
if (
data[`top-border-${type}`] === data[`right-border-${type}`] &&
data[`right-border-${type}`] === data[`bottom-border-${type}`] &&
data[`bottom-border-${type}`] === data[`left-border-${type}`]
) {
data[`all-border-${type}`] = data[`top-border-${type}`];
} else {
data[`all-border-${type}`] = 'custom';
}
};
fn('width');
fn('style');
fn('color');
return data;
}
function getLabel(value?: string, option?: any) {
if (value === 'inherit') {
return '继承常规';
}
const res = option?.find((item: any) => item.value === value);
if (res) {
return res.label;
}
return value;
}
function getKey(field: string) {
return `${borderType}-border-${field}`;
}
function changeType(value: string) {
setBorderType(value);
}
function changeItem(key: string) {
return (val: string | undefined) => {
let field = getKey(key);
if (val === 'custom') {
return;
}
let changeValue = {};
if (borderType === 'all') {
let newValue: Record<string, any> = {};
// 过滤掉all
let items = borderItems.filter(position => position?.item !== 'all');
items.forEach(item => {
let itemKey = `${item.item}-border-${key}`;
newValue[itemKey] = val;
});
changeValue = {
...value,
...newValue
};
} else {
changeValue = {
...value,
[field]: val
};
}
onChange(setInheritData(changeValue, editorInheritValue));
};
}
return (
<div className="Theme-Border">
{label ? <div className="Theme-Border-label">{label}</div> : null}
<div className="Theme-Border-content">
{custom ? (
<div className="Theme-Border-items">
{borderItems.map(item => {
let valueKey = `border-${item.item}`;
return (
<div
key={valueKey}
className={cx(
`Theme-Border-item Theme-Border-item--${item.item}`,
{
'Theme-Border-item--active': borderType === item.item
}
)}
onClick={() => changeType(item.item)}
>
<span data-tooltip={item.tip} data-position="top"></span>
</div>
);
})}
</div>
) : (
<div className="Theme-Border-all"></div>
)}
<div
className={cx(
'Theme-Border-settings',
!custom && 'Theme-Border-settings--all'
)}
>
<ThemeSelect
{...props}
options={borderWidthOptions}
value={borderData[getKey('width')]}
onChange={value => changeItem('width')(value)}
itemName={`${
borderType === 'all' ? 'top' : borderType
}-border-width`}
state={state}
inheritValue={editorThemePath ? 'inherit' : ''}
placeholder={editorDefaultValue?.[getKey('width')]}
/>
<div className="Theme-Border-settings-style-color">
<Select
options={borderStyleOptions}
value={borderData[getKey('style')]}
placeholder={getLabel(
editorDefaultValue?.[getKey('style')],
borderStyleOptions
)}
onChange={(item: any) => changeItem('style')(item.value)}
clearable={!!editorDefaultValue}
renderMenu={(item: Options) => {
return item.realValue === 'none' ? (
<span></span>
) : item.parent ? (
<span>{item.label}</span>
) : (
<div className="Theme-Border-style">
<div
className="Theme-Border-style-line"
style={{borderStyle: item.realValue}}
></div>
<span>{_i18n(item.label)}</span>
</div>
);
}}
renderValueLabel={(item: Options) => {
return item.realValue === 'none' ? (
<span></span>
) : item.parent ? (
<span>{item.label}</span>
) : (
<div className="Theme-Border-style">
<div
className="Theme-Border-style-line"
style={{borderStyle: item.realValue}}
></div>
</div>
);
}}
/>
<ColorPicker
{...props}
value={borderData[getKey('color')]}
options={colorOptions}
onChange={changeItem('color')}
needCustom={needColorCustom ?? false}
needTheme
itemName={`${
borderType === 'all' ? 'top' : borderType
}-border-color`}
placeholder={editorDefaultValue?.[getKey('color')]}
/>
</div>
</div>
</div>
</div>
);
}
@FormItem({
type: 'amis-theme-border',
strictMode: false,
renderLabel: false
})
export class BorderRenderer extends React.Component<FormControlProps> {
render() {
return <BoxBorder {...this.props} custom={this.props.custom ?? true} />;
}
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,329 @@
/**
*
*/
import {FormItem} from 'amis-core';
import type {FormControlProps} from 'amis-core';
import {Overlay, PopOver} from 'amis-ui';
import React, {useEffect, useState} from 'react';
import cx from 'classnames';
import cloneDeep from 'lodash/cloneDeep';
import ThemeSelect from './ThemeSelect';
import {
getValueByPath,
getInheritValue,
formatInheritData,
setInheritData
} from '../util';
interface PaddingAndMarginProps extends FormControlProps {
custom: boolean;
}
function PaddingAndMarginDialog(props: PaddingAndMarginProps) {
const {
onChange,
value,
data,
custom,
label,
options,
hideMargin,
hidePadding,
state,
editorThemePath
} = props;
const [type, setType] = useState('all');
const [customRef, setCustomRef] = useState<Element | null>(null);
const [customShow, setCustomShow] = useState(false);
const [customIndex, setCustomIndex] = useState(0);
const [customKey, setCustomKey] = useState('marginTop');
const [isPaddingInherit, setIsPaddingInherit] = useState<boolean>(false);
const [isMarginInherit, setIsMarginInherit] = useState<boolean>(false);
const LABELS = [
{value: 'marginTop'},
{value: 'marginRight'},
{value: 'marginBottom'},
{value: 'marginLeft'},
{value: 'paddingTop'},
{value: 'paddingRight'},
{value: 'paddingBottom'},
{value: 'paddingLeft'}
].filter(n => {
if (hideMargin) {
return !!~n.value.indexOf('padding');
} else if (hidePadding) {
return !!~n.value.indexOf('margin');
} else {
return n;
}
});
const editorDefaultValue = formatData(getValueByPath(editorThemePath, data));
const editorInheritValue = getInheritValue(editorThemePath, data);
const spaceData = formatData(value || {});
const optionsData = options || data.sizesOptions || [];
function formatData(sourceData: any) {
if (!sourceData) {
return null;
}
const data = formatInheritData(cloneDeep(sourceData));
if (
data?.marginTop === data?.marginRight &&
data?.marginRight === data?.marginBottom &&
data?.marginBottom === data?.marginLeft
) {
data.margin = data?.marginTop;
} else {
data.margin = 'custom';
}
if (
data?.paddingTop === data?.paddingRight &&
data?.paddingRight === data?.paddingBottom &&
data?.paddingBottom === data?.paddingLeft
) {
data.padding = data?.paddingTop;
} else {
data.padding = 'custom';
}
return data;
}
function onSpaceChange(position: number | string) {
return (value: string | undefined) => {
const res = cloneDeep(spaceData);
delete res.margin;
delete res.padding;
if (value === 'custom') {
return;
}
if (position === 'margin-all') {
if (value?.includes('all')) {
const defaultToken = (key: string) =>
`var(${data.default.token}${key})`;
res.marginTop = defaultToken('marginTop');
res.marginRight = defaultToken('marginRight');
res.marginBottom = defaultToken('marginBottom');
res.marginLeft = defaultToken('marginLeft');
} else {
res.marginTop = value;
res.marginRight = value;
res.marginBottom = value;
res.marginLeft = value;
}
} else if (position === 'padding-all') {
if (value?.includes('all')) {
const defaultToken = (key: string) =>
`var(${data.default.token}${key})`;
res.paddingTop = defaultToken('paddingTop');
res.paddingRight = defaultToken('paddingRight');
res.paddingBottom = defaultToken('paddingBottom');
res.paddingLeft = defaultToken('paddingLeft');
} else {
res.paddingTop = value;
res.paddingRight = value;
res.paddingBottom = value;
res.paddingLeft = value;
}
} else if (typeof position === 'number') {
const label = LABELS[position].value;
res[label] = value;
if (label.includes('padding')) {
setIsPaddingInherit(false);
} else {
setIsMarginInherit(false);
}
}
onChange(setInheritData(res, editorInheritValue));
};
}
function findRealValue(value: string) {
return (
optionsData.find((item: any) => item.value === value)?.realValue || value
);
}
function handleCustomClick(e: React.MouseEvent, index: number, key: string) {
setCustomShow(true);
setCustomRef(e.currentTarget);
setCustomIndex(index);
setCustomKey(key);
}
useEffect(() => {
if (state && state !== 'default' && value) {
if (
value['paddingTop']?.includes('default-paddingTop') &&
value['paddingBottom']?.includes('default-paddingBottom') &&
value['paddingRight']?.includes('default-paddingRight') &&
value['paddingLeft']?.includes('default-paddingLeft')
) {
setIsPaddingInherit(true);
}
if (
value['marginTop']?.includes('default-marginTop') &&
value['marginBottom']?.includes('default-marginBottom') &&
value['marginRight']?.includes('default-marginRight') &&
value['marginLeft']?.includes('default-marginLeft')
) {
setIsMarginInherit(true);
}
}
}, [value]);
useEffect(() => {
if (spaceData.margin === 'custom' || spaceData.padding === 'custom') {
setType('custom');
}
}, []);
return (
<div className="Theme-PaddingAndMargin">
{label ? (
<div className="Theme-PaddingAndMargin-title">{label}</div>
) : null}
<div className="Theme-PaddingAndMargin-inner">
<div
className={cx(
'Theme-PaddingAndMargin-label',
custom && 'Theme-PaddingAndMargin-label--custom'
)}
>
<div
className={cx(
'Theme-PaddingAndMargin-label-all',
type === 'all' && 'Theme-PaddingAndMargin-label-all--active'
)}
onClick={() => setType('all')}
></div>
{custom ? (
<div
className={cx(
'Theme-PaddingAndMargin-label-custom',
type === 'custom' &&
'Theme-PaddingAndMargin-label-custom--active'
)}
onClick={() => setType('custom')}
>
<div></div>
<div></div>
</div>
) : null}
</div>
{type === 'all' ? (
<>
{!hideMargin && (
<div className="Theme-PaddingAndMargin-input">
<ThemeSelect
{...props}
options={optionsData}
value={
isMarginInherit
? `var(${data.default.token}margin-all)`
: spaceData.margin
}
onChange={onSpaceChange('margin-all')}
itemName="margin-all"
state={state}
inheritValue={editorThemePath ? 'inherit' : ''}
placeholder={editorDefaultValue?.margin}
/>
<div className="Theme-PaddingAndMargin-input-label">Margin</div>
</div>
)}
{!hidePadding && (
<div className="Theme-PaddingAndMargin-input">
<ThemeSelect
{...props}
options={optionsData}
value={
isPaddingInherit
? `var(${data.default.token}padding-all)`
: spaceData.padding
}
onChange={onSpaceChange('padding-all')}
itemName="padding-all"
state={state}
inheritValue={editorThemePath ? 'inherit' : ''}
placeholder={editorDefaultValue?.padding}
/>
<div className="Theme-PaddingAndMargin-input-label">
Padding
</div>
</div>
)}
</>
) : null}
</div>
{type !== 'all' ? (
<div
className={cx(
'Theme-PaddingAndMargin-custom',
!hidePadding && 'Theme-PaddingAndMargin-custom--padding',
!hideMargin && 'Theme-PaddingAndMargin-custom--margin'
)}
>
{LABELS.map((item, index) => {
return (
<div
key={item.value}
className={cx('Theme-PaddingAndMargin-custom-' + item.value)}
onClick={e => handleCustomClick(e, index, item.value)}
>
<div>
{findRealValue(
spaceData[item.value] || editorDefaultValue?.[item.value]
) || '-'}
</div>
</div>
);
})}
<Overlay
// @ts-ignore
container={document.body}
// @ts-ignore
target={customRef}
show={customShow}
rootClose={false}
>
<PopOver overlay onHide={() => setCustomShow(false)}>
<div className="Theme-PaddingAndMargin-custom-popover">
<ThemeSelect
{...props}
options={optionsData}
value={spaceData[customKey]}
onChange={onSpaceChange(customIndex)}
itemName={customKey}
state={state}
inheritValue={editorThemePath ? 'inherit' : ''}
placeholder={editorDefaultValue?.[customKey]}
/>
</div>
</PopOver>
</Overlay>
</div>
) : null}
</div>
);
}
@FormItem({
type: 'amis-theme-padding-and-margin',
strictMode: false,
renderLabel: false
})
export default class PaddingAndMarginDialogRender extends React.Component<PaddingAndMarginProps> {
render() {
return (
<PaddingAndMarginDialog
{...this.props}
custom={this.props.custom ?? true}
/>
);
}
}

View File

@ -0,0 +1,248 @@
/**
* @file
* @description
*/
import cx from 'classnames';
import React, {useEffect, useState} from 'react';
import {FormItem, RendererProps, resolveVariableAndFilter} from 'amis-core';
import type {FormControlProps} from 'amis-core';
import cloneDeep from 'lodash/cloneDeep';
import ThemeSelect from './ThemeSelect';
import {
getValueByPath,
getInheritValue,
formatInheritData,
setInheritData
} from '../util';
interface RadiusProps {
custom: boolean;
}
const radiusItems = [
{
item: 'top-left',
tip: '左上角'
},
{
item: 'top-right',
tip: '右上角'
},
{
item: 'bottom-left',
tip: '左下角'
},
{
item: 'bottom-right',
tip: '右下角'
}
];
function BoxRadius(props: RadiusProps & RendererProps) {
const {
onChange,
value = {},
data,
custom,
label,
borderRadiusOptions,
state,
editorThemePath
} = props;
let options = cloneDeep(borderRadiusOptions || data.borderRadiusOptions);
if (typeof borderRadiusOptions === 'string') {
options = resolveVariableAndFilter(borderRadiusOptions, data, '| raw');
}
const [radiusType, setRadiusType] = useState<string>('all');
const [isInherit, setIsInherit] = useState<boolean>(false);
const editorDefaultValue = formatData(getValueByPath(editorThemePath, data));
const editorInheritValue = getInheritValue(editorThemePath, data);
const borderData = formatData(value || {});
function formatData(sourceData: any) {
if (!sourceData) {
return null;
}
const data = formatInheritData(cloneDeep(sourceData));
if (
data[`top-right-border-radius`] === data[`top-left-border-radius`] &&
data[`top-left-border-radius`] === data[`bottom-right-border-radius`] &&
data[`bottom-right-border-radius`] === data[`bottom-left-border-radius`]
) {
data[`all-border-radius`] = data[`top-right-border-radius`];
} else {
data[`all-border-radius`] = 'custom';
}
return data;
}
function getKey(type: string) {
return `${type}-border-radius`;
}
function changeItem(type: string) {
return (val: string) => {
let field = getKey(type);
if (val === 'custom') {
return;
}
let changeValue = {};
if (type === 'all') {
let newValue: Record<string, any> = {};
const items = radiusItems;
items.forEach(item => {
let itemKey = `${item.item}-border-radius`;
if (
state &&
state !== 'default' &&
val?.includes('all-border-radius')
) {
const defaultToken = (key: string) =>
`var(${data.default.token}${key})`;
newValue[itemKey] = defaultToken(itemKey);
} else {
newValue[itemKey] = val;
}
});
changeValue = {
...value,
...newValue
};
} else {
changeValue = {
...value,
[field]: val
};
}
onChange(setInheritData(changeValue, editorInheritValue));
setIsInherit(false);
};
}
useEffect(() => {
if (state && state !== 'default') {
if (
value['top-left-border-radius']?.includes(
'default-top-left-border-radius'
) &&
value['top-right-border-radius']?.includes(
'default-top-right-border-radius'
) &&
value['bottom-left-border-radius']?.includes(
'default-bottom-left-border-radius'
) &&
value['bottom-right-border-radius']?.includes(
'default-bottom-right-border-radius'
)
) {
setIsInherit(true);
}
}
}, [value]);
useEffect(() => {
if (borderData['all-border-radius'] === 'custom') {
setRadiusType('custom');
}
}, []);
return (
<div className="Theme-Radius">
{label ? <div className="Theme-Radius-label">{label}</div> : null}
<div className="Theme-Radius-inner">
<div
className={cx(
'Theme-Radius-item',
custom && 'Theme-Radius-item--custom'
)}
>
<div
className={cx(
'Theme-Radius-item-all',
radiusType === 'all' && 'Theme-Radius-item-all--active'
)}
onClick={() => setRadiusType('all')}
></div>
{custom ? (
<div
className={cx(
'Theme-Radius-item-custom',
radiusType === 'custom' && 'Theme-Radius-item-custom--active'
)}
onClick={() => setRadiusType('custom')}
></div>
) : null}
</div>
<div className="Theme-Radius-settings">
<ThemeSelect
{...props}
options={options}
value={
isInherit
? `var(${data.default.token}all-border-radius)`
: borderData[getKey('all')]
}
onChange={changeItem('all')}
extraUnit={['px']}
disabled={radiusType === 'custom'}
itemName={'all-border-radius'}
state={state}
inheritValue={editorThemePath ? 'inherit' : ''}
placeholder={editorDefaultValue?.[getKey('all')]}
/>
</div>
</div>
<div className="Theme-Radius-settings-custom">
{radiusType === 'custom'
? radiusItems.map(item => {
const position = item.item;
return (
<div
className="Theme-Radius-settings-custom-item"
key={item.item}
>
<ThemeSelect
{...props}
options={options}
value={borderData[getKey(position)]}
onChange={changeItem(position)}
extraUnit={['px']}
itemName={position + '-border-radius'}
state={state}
inheritValue={editorThemePath ? 'inherit' : ''}
placeholder={editorDefaultValue?.[getKey(position)]}
menuTpl="realValue"
/>
<div
className={cx(
'Theme-Radius-settings-custom-item-label',
'Theme-Radius-settings-custom-item-' + position
)}
></div>
</div>
);
})
: null}
</div>
</div>
);
}
@FormItem({
type: 'amis-theme-radius',
strictMode: false,
renderLabel: false
})
export class RadiusRenderer extends React.Component<FormControlProps> {
render() {
return <BoxRadius {...this.props} custom={this.props.custom ?? true} />;
}
}

View File

@ -0,0 +1,447 @@
/**
* @file Shadow.tsx
* @description
*/
import React from 'react';
import {observer} from 'mobx-react';
import cx from 'classnames';
import {FormItem, PlainObject, render} from 'amis-core';
import type {FormControlProps} from 'amis-core';
import type {ShadowData} from '../helper/declares';
import {NumberInput, Overlay, PopOver, Select} from 'amis-ui';
import cloneDeep from 'lodash/cloneDeep';
import find from 'lodash/find';
import isEqual from 'lodash/isEqual';
import {ThemeWrapperHeader} from './ThemeWrapper';
import ColorPicker from './ColorPicker';
import {Icon as ThemeIcon} from '../icons/index';
import {getValueByPath, getInheritValue, setInheritData} from '../util';
interface ShadowEditorProps extends FormControlProps {}
interface ShadowViewProps {
show: boolean;
target: any;
name: string;
value: string[];
close: () => void;
}
interface ShadowOption {
label?: string;
value?: string;
realValue: ShadowData[];
}
function ShadowView(props: ShadowViewProps) {
const {show, target, name, value, close} = props;
return (
<Overlay
// @ts-ignore
container={document.body}
target={target.current}
show={show}
placement="top"
offset={[0, -8]}
>
<PopOver overlay={false} onHide={close}>
<div className="Theme-ShadowView">
<div className="Theme-ShadowView-header"></div>
<div className="Theme-ShadowView-body">
<div className="Theme-ShadowView-body-shadow">
<div
className="Theme-ShadowView-body-shadow-square"
style={{boxShadow: value?.join(', ') || 'none'}}
></div>
</div>
<div className="Theme-ShadowView-body-title">{name}</div>
<div className="Theme-ShadowView-body-value">
{value?.map((shadow: string, index: number) => (
<div className="Theme-ShadowView-body-value-item" key={index}>
{shadow}
</div>
))}
</div>
</div>
</div>
</PopOver>
</Overlay>
);
}
function ShadowEditor(props: ShadowEditorProps) {
const {
data,
onChange,
value,
hasSenior,
options,
colorOptions,
state,
itemName,
editorThemePath
} = props;
const target = React.useRef<HTMLDivElement>(null);
const [open, toggleOpen] = React.useState(true);
const [senior, toggleSenior] = React.useState(false);
const [show, toggleViewShow] = React.useState(false);
const customShadow = {
label: '自定义',
value: 'custom',
realValue: [
{
inset: false,
x: '0px',
y: '0px',
blur: '0px',
spread: '0px',
color: 'transparent'
}
],
visible: false
};
const shadowOptions = options
? [...options, customShadow]
: [...cloneDeep(data.shadowOptions || []), customShadow];
if (state && state !== 'default') {
shadowOptions.unshift({
value: editorThemePath ? 'inherit' : `var(${data.default.token}shadow)`,
label: '继承常规',
realValue: editorThemePath
? ['继承常规']
: [`var(${data.default.token}${itemName})`]
});
}
const editorDefaultValue = getValueByPath(editorThemePath, data);
const editorInheritValue = getInheritValue(editorThemePath, data);
const defaultValue = value
? (value.indexOf('inherit:') > -1 && 'inherit') ||
find(cloneDeep(shadowOptions), item => item.value === value) ||
formateCustomValue(value)
: null;
const [shadowData, setShadowData] = React.useState<ShadowOption | undefined>(
defaultValue
);
React.useEffect(() => {
if (
defaultValue &&
(!shadowData || defaultValue.value !== shadowData.value)
) {
setShadowData(defaultValue);
}
}, [defaultValue]);
function formateCustomValue(value: string) {
const color: PlainObject = {};
let colorIndex = 0;
value = value.trim().replace(/((rgba|rgb|var)\(.*?\))|(#.{6})/g, $1 => {
const key = '$' + colorIndex;
colorIndex++;
color[key] = $1;
return key;
});
const realValue = value.split(',').map((item: string) => {
let inset = false;
if (item.includes('inset')) {
inset = true;
item = item.replace('inset', '');
}
item = item.trim();
const css = item.split(' ');
return {
inset,
x: css[0],
y: css[1],
blur: css[2],
spread: css[3],
color: color[css[4]]
};
});
return {
label: '自定义',
value: 'custom',
realValue
};
}
function formatRealValue(value?: ShadowData[]) {
if (!value) {
return {value: '', source: []};
}
const res = value.map((shadow: ShadowData) => {
return `${shadow.inset ? 'inset' : ''} ${shadow.x || ''} ${
shadow.y || ''
} ${shadow.blur || ''} ${shadow.spread || ''} ${
shadow.color || 'transparent'
}`;
});
return {value: res.join(', '), source: res};
}
function onShadowSelect(value: string) {
if (value === 'custom') {
return;
}
if (value) {
const findItem = find(shadowOptions, item => item.value === value);
if (findItem?.value) {
setShadowData(findItem);
onChange(setInheritData(findItem.value, editorInheritValue));
}
} else {
setShadowData(undefined);
onChange(undefined);
}
}
function changeToCustom(shadowData: ShadowOption) {
if (!shadowData.value) {
return shadowData;
}
const findItem = find(
shadowOptions,
item => item.value === shadowData.value
);
if (!isEqual(shadowData.realValue, findItem.realValue)) {
return {
...shadowData,
label: '自定义',
value: 'custom'
};
}
return shadowData;
}
function handleAdd(inset: boolean) {
const newData = changeToCustom({
...(shadowData || {
label: '自定义',
value: 'custom'
}),
realValue: [
...(shadowData?.realValue || []),
{
inset,
x: '0px',
y: '0px',
blur: '0px',
spread: '0px',
color: 'transparent'
}
]
});
setShadowData(newData);
onChange(formatRealValue(newData.realValue).value);
}
function handleDelete(index: number) {
if (shadowData!.realValue.length === 1) {
return;
}
let data = cloneDeep(shadowData);
data!.realValue.splice(index, 1);
const newData = changeToCustom(data!);
setShadowData(newData);
onChange(formatRealValue(newData.realValue).value);
}
function handleEdit(value: string, type: keyof ShadowData, index: number) {
if (type !== 'color') {
value += 'px';
}
(shadowData!.realValue[index][type] as string) = value;
const newData = changeToCustom(shadowData!);
setShadowData(newData);
onChange(formatRealValue(newData.realValue).value);
}
// 数据格式化
const formatter = (value: string | number) => {
return value + 'px';
};
// 还原数据
const parser = (value: string) => {
return parseFloat(value);
};
return (
<div className="Theme-ShadowEditor">
<ThemeWrapperHeader
title="阴影"
hasSenior={hasSenior}
senior={senior}
toggleSenior={toggleSenior}
open={open}
toggleOpen={toggleOpen}
/>
{open && (
<div className="Theme-ShadowEditor-body">
<div className="Theme-ShadowEditor-line">
<div
ref={target}
className="Theme-ShadowEditor-view"
onMouseOver={() => toggleViewShow(true)}
onMouseOut={() => toggleViewShow(false)}
>
<div
style={{
boxShadow: formatRealValue(shadowData?.realValue).value
}}
className="Theme-ShadowEditor-view-inner"
></div>
</div>
<ShadowView
target={target}
show={show}
close={() => {
toggleViewShow(false);
}}
name={shadowData?.label || '无阴影'}
value={formatRealValue(shadowData?.realValue).source}
/>
<div className="Theme-ShadowEditor-item">
<Select
options={shadowOptions}
clearable
value={shadowData?.value}
onChange={(res: any) => {
onShadowSelect(res.value);
}}
placeholder={editorDefaultValue || '无阴影'}
/>
</div>
</div>
{senior || shadowData?.value === 'custom' ? (
<div className="Theme-ShadowEditor-customContent">
<div className="Theme-Wrapper-header Theme-ShadowEditor-sub-header">
<div className="Theme-Wrapper-header-left"></div>
<div className="Theme-Wrapper-header-right">
{render({
type: 'dropdown-button',
level: 'link',
btnClassName: 'Theme-ShadowEditor-add',
icon: 'plus',
hideCaret: true,
closeOnClick: true,
align: 'right',
buttons: ['', 'inset'].map(item => {
return {
label: item ? '内阴影' : '外阴影',
onClick: () => handleAdd(!!item)
};
})
})}
</div>
</div>
{shadowData?.realValue.length
? shadowData.realValue.map(
(item: ShadowData, index: number) => (
<div className="Theme-ShadowEditor-line" key={index}>
<div className="Theme-ShadowEditor-item">
<div className="Theme-ShadowEditor-color-picker">
<ColorPicker
needCustom
needTheme
value={item.color}
options={colorOptions || data.colorOptions || []}
onChange={(value: string) => {
handleEdit(value, 'color', index);
}}
/>
</div>
<div className="Theme-ShadowEditor-item-label">
{item.inset ? '内阴影' : '外阴影'}
</div>
</div>
<div className="Theme-ShadowEditor-item">
<NumberInput
value={parseFloat(item.x)}
parser={parser}
formatter={formatter}
onChange={value => {
handleEdit(value as any, 'x', index);
}}
/>
<div className="Theme-ShadowEditor-item-label">X</div>
</div>
<div className="Theme-ShadowEditor-item">
<NumberInput
value={parseFloat(item.y)}
parser={parser}
formatter={formatter}
onChange={value => {
handleEdit(value as any, 'y', index);
}}
/>
<div className="Theme-ShadowEditor-item-label">Y</div>
</div>
<div className="Theme-ShadowEditor-item">
<NumberInput
value={parseFloat(item.blur)}
parser={parser}
formatter={formatter}
onChange={value => {
handleEdit(value as any, 'blur', index);
}}
/>
<div className="Theme-ShadowEditor-item-label">
</div>
</div>
<div className="Theme-ShadowEditor-item">
<NumberInput
value={parseFloat(item.spread)}
parser={parser}
formatter={formatter}
onChange={value => {
handleEdit(value as any, 'spread', index);
}}
/>
<div className="Theme-ShadowEditor-item-label">
</div>
</div>
<div className="Theme-ShadowEditor-item trash-icon">
<ThemeIcon
icon="trash"
className={cx(
'common-icon',
shadowData.realValue.length === 1 &&
'disabled-icon'
)}
onClick={() => {
handleDelete(index);
}}
/>
</div>
</div>
)
)
: null}
</div>
) : null}
</div>
)}
</div>
);
}
export default observer(ShadowEditor);
@FormItem({
type: 'amis-theme-shadow-editor',
strictMode: false,
renderLabel: false
})
export class ShadowEditorRenderer extends React.Component<ShadowEditorProps> {
render() {
return <ShadowEditor {...this.props} />;
}
}

View File

@ -0,0 +1,260 @@
/**
* @file Size.tsx
* @description
*/
import React from 'react';
import {observer} from 'mobx-react';
import {FormItem} from 'amis-core';
import type {FormControlProps} from 'amis-core';
import {Icon as ThemeIcon} from '../icons/index';
import cx from 'classnames';
import {Button} from 'amis-ui';
import ThemeSelect from './ThemeSelect';
import {find} from 'lodash';
import {
getValueByPath,
getInheritValue,
formatInheritData,
setInheritData
} from '../util';
interface SizeEditorProps extends FormControlProps {
hideWidth?: boolean;
hideHeight?: boolean;
hideMinWidth?: boolean;
}
function SizeEditor(props: SizeEditorProps) {
const {
data,
sizesOptions = data.sizesOptions,
value: defaultValue,
onChange,
hideWidth,
hideHeight,
hideMinWidth,
editorThemePath,
label
} = props;
const [lock, setLockValue] = React.useState(0);
const [value, setValue] = React.useState<{
width?: string;
height?: string;
minWidth?: string;
}>({
width: '',
height: '',
minWidth: ''
});
const RULE = /[0-9\.]*/;
const editorDefaultValue = getValueByPath(editorThemePath, data);
const editorInheritValue = getInheritValue(editorThemePath, data);
React.useEffect(() => {
const timer = setTimeout(() => {
if (defaultValue) {
setValue(formatInheritData(defaultValue));
}
}, 100);
return () => clearTimeout(timer);
}, [defaultValue]);
function handleChange(valueTemp: any) {
if (sizesOptions && sizesOptions.length) {
let value: {
width?: string;
height?: string;
minWidth?: string;
} = {};
['width', 'height', 'minWidth'].forEach(
(key: 'width' | 'height' | 'minWidth') => {
const sizeFind = find(
sizesOptions,
item => item.realValue === valueTemp[key]
);
value[key] = sizeFind ? sizeFind.value : valueTemp[key];
}
);
onChange(setInheritData(value, editorInheritValue));
return;
}
onChange(valueTemp);
}
function setValueByLock({
data,
type
}: {
data: string;
type: 'width' | 'height';
}) {
if (lock) {
const changeType = type === 'width' ? 'height' : 'width';
let finalValue = '';
let originNum = getNumByOption(data);
let num = type === 'width' ? originNum / lock : originNum * lock;
num = Number(num.toFixed(2));
if (lock === 1) {
finalValue = data;
} else if (data.indexOf('var') > -1) {
const findItem = find(
sizesOptions,
item => item.realValue === num + 'rem'
);
if (findItem) {
finalValue = findItem.value;
} else {
finalValue = num + 'rem';
}
} else {
const unit = data.replace(originNum.toString(), '');
finalValue = num + unit;
}
const valueTemp = {
...value,
[type]: data,
[changeType]: finalValue
};
setValue(valueTemp);
handleChange(valueTemp);
}
}
function setValueByType(data: string, type: string) {
if (lock && (type === 'width' || type === 'height')) {
setValueByLock({data, type});
return;
}
const valueTemp = {
...value,
[type]: data
};
setValue(valueTemp);
handleChange(valueTemp);
}
function getNumByOption(value: string) {
if (!value) {
return 0;
}
const matchValue = value.match(RULE);
if (matchValue && matchValue[0]) {
return Number(matchValue[0]);
}
if (!sizesOptions || !sizesOptions.length) {
return 0;
}
const findItem = find(sizesOptions, item => item.value === value);
const matchFindValue = findItem ? findItem.realValue.match(RULE) : 0;
return matchFindValue && matchFindValue[0] ? Number(matchFindValue[0]) : 0;
}
return (
<div className="Theme-SizeEditor">
{label ? <div className="Theme-SizeEditor-label">{label}</div> : null}
<div className="Theme-SizeEditor-body">
<div
className={cx(
'Theme-SizeEditor-line',
(hideWidth || hideHeight) && 'Theme-SizeEditor-item-sigle',
!hideWidth && !hideHeight && 'Theme-SizeEditor-line-no-hide'
)}
>
<div className="Theme-SizeEditor-size">
{!hideWidth && (
<div className="Theme-SizeEditor-item">
<div className="Theme-SizeEditor-item-label">W</div>
<ThemeSelect
{...props}
options={sizesOptions}
value={value['width']}
onChange={(value: string) => setValueByType(value, 'width')}
itemName="width"
placeholder={editorDefaultValue?.width}
/>
</div>
)}
{!hideHeight && (
<div className="Theme-SizeEditor-item">
<div className="Theme-SizeEditor-item-label">H</div>
<ThemeSelect
{...props}
options={sizesOptions}
value={value['height']}
onChange={(value: string) => setValueByType(value, 'height')}
itemName="height"
placeholder={editorDefaultValue?.height}
/>
</div>
)}
</div>
{!hideWidth && !hideHeight && (
<div className="Theme-SizeEditor-lock">
{!lock ? (
<Button
tooltip="锁定比例"
tooltipPlacement="left"
onClick={() => {
if (!value['width'] || !value['height']) {
setLockValue(0);
} else {
const width = getNumByOption(value['width']);
const height = getNumByOption(value['height']);
if (width && height) {
setLockValue(Number((width / height).toFixed(2)));
} else {
setLockValue(0);
}
}
}}
>
<ThemeIcon icon="unlock" className="common-icon" />
</Button>
) : (
<Button
tooltip="解除锁定"
tooltipPlacement="left"
onClick={() => {
setLockValue(0);
}}
>
<ThemeIcon icon="lock" className="common-icon" />
</Button>
)}
</div>
)}
</div>
{!hideMinWidth && (
<div className="Theme-SizeEditor-line Theme-SizeEditor-item-sigle">
<div className="Theme-SizeEditor-item">
<div className="Theme-SizeEditor-item-label"></div>
<ThemeSelect
{...props}
options={sizesOptions}
value={value['minWidth']}
onChange={(value: string) => setValueByType(value, 'minWidth')}
itemName="minWidth"
placeholder={editorDefaultValue?.minWidth}
/>
</div>
</div>
)}
</div>
</div>
);
}
export default observer(SizeEditor);
@FormItem({
type: 'amis-theme-size-editor',
strictMode: false,
renderLabel: false
})
export class SizeEditorRenderer extends React.Component<SizeEditorProps> {
render() {
return <SizeEditor {...this.props} />;
}
}

View File

@ -0,0 +1,345 @@
/**
* @file ThemeSelect.tsx
* @description
*/
import React, {useEffect, useRef, useState} from 'react';
import {Icon, Overlay, PopOver, TooltipWrapper} from 'amis-ui';
import cloneDeep from 'lodash/cloneDeep';
import debounce from 'lodash/debounce';
import {FormItem, resolveVariableAndFilter, highlight} from 'amis-core';
import type {FormControlProps} from 'amis-core';
import cx from 'classnames';
import {
getValueByPath,
getInheritValue,
formatInheritData,
setInheritData
} from '../util';
interface Option {
label: any;
value: string;
realValue?: string;
html?: any;
}
interface ThemeSelectProps {
options?: Option[];
value?: string;
extraUnit?: Array<string>;
onChange: (value: string | undefined) => void;
disabled?: boolean;
data?: any;
state?: string;
itemName?: string;
menuTpl?: string;
inheritValue?: string;
placeholder?: string;
editorThemePath?: any;
isEditorTpl?: boolean;
}
interface ThemeSelectContentProps extends ThemeSelectProps {
target: any;
value: string;
extraUnit: Array<string>;
}
// 根字体大小
const remFactor =
parseFloat(getComputedStyle(window.document.documentElement).fontSize) || 16;
function ThemeSelectContent(props: ThemeSelectContentProps) {
const {
options: originalOptions,
onChange,
extraUnit,
target,
disabled,
menuTpl,
placeholder,
editorThemePath,
data,
isEditorTpl
} = props;
// 期望value是string类型
const value = String(formatInheritData(props.value));
const input = useRef<HTMLInputElement>(null);
const [currentItem, setCurrentItem] = useState<Option | undefined>(undefined);
const [options, setOptions] = useState<Option[] | undefined>(originalOptions);
const [showOptions, setShowOptions] = useState(false);
const editorDefaultValue = getValueByPath(editorThemePath, data);
const editorInheritValue = getInheritValue(editorThemePath, data);
useEffect(() => {
const res = originalOptions?.find(item => item.value === value);
setCurrentItem(res);
if (!res) {
formatOptions(value);
input.current && (input.current.value = value);
}
}, [value]);
function getRealValue(value?: string) {
if (value === 'inherit') {
return '继承常规';
}
const res = originalOptions?.find(item => item.value === value);
if (res) {
return res.label;
}
return value === 'custom' ? '分别配置' : value;
}
function clearThemeValue() {
onChange(undefined);
setTimeout(() => {
input.current?.focus();
}, 10);
}
function formatOptions(value: string) {
const tempList = cloneDeep(originalOptions) || [];
const items = tempList.filter(item => item.realValue?.includes(value));
const list = [];
if (!value || Number.isNaN(parseFloat(value))) {
list.push(...tempList);
setOptions(list);
return;
} else if (items.length > 0) {
list.push(...items);
}
const number = parseFloat(value);
let unit = cloneDeep(extraUnit);
if (!/^\d*$/.test(value)) {
unit = unit.filter(item => (number + item).includes(value));
}
const extraUnitList =
unit.map(unit => {
let label = number + unit;
if (unit === 'rem') {
label += `(${number * remFactor}px)`;
}
return {
value: number + unit,
label,
realValue: number + unit
};
}) || [];
list.unshift(...extraUnitList);
if (extraUnit.includes('rem') && unit.includes('px')) {
list.unshift({
value: number / remFactor + 'rem',
label: `${number}px->${number / remFactor}rem`,
realValue: number / remFactor + 'rem'
});
}
setOptions(
list.map(item => ({
...item,
html: highlight(item.label, value)
}))
);
}
function valueOnChange(value: string) {
return debounce(() => {
if (value) {
onChange(
isEditorTpl ? setInheritData(value, editorInheritValue) : value
);
} else {
onChange(undefined);
}
})();
}
function onInputChange(res: any) {
const value = res.currentTarget.value;
formatOptions(value);
valueOnChange(value);
}
function onSelectValue(item: Option) {
onChange(
isEditorTpl ? setInheritData(item.value, editorInheritValue) : item.value
);
setShowOptions(false);
input.current && (input.current.value = item.value);
}
function openOptions() {
if (!disabled) {
setShowOptions(true);
}
}
const tooltipLabel =
value === 'inherit' ? '继承常规' : currentItem?.label || '分别配置';
return (
<>
{currentItem ||
value === 'custom' ||
value?.includes('var') ||
value === 'inherit' ? (
<div
onClick={openOptions}
className={cx(
'theme-select',
disabled && 'theme-select--disabled',
showOptions,
showOptions && 'theme-select--active'
)}
>
<TooltipWrapper
trigger="hover"
placement="top"
tooltip={{
children: () => <div>{tooltipLabel}</div>
}}
disabled={!!menuTpl}
>
<div className="ThemeSelectContent-theme">
{menuTpl ? (
<div>
{(currentItem && (currentItem as any)[menuTpl]) || '分别配置'}
</div>
) : (
<div>{tooltipLabel}</div>
)}
{!disabled ? (
<Icon icon="close" className="icon" onClick={clearThemeValue} />
) : null}
</div>
</TooltipWrapper>
</div>
) : (
<div
className={cx(
'theme-select',
disabled && 'theme-select--disabled',
showOptions && 'theme-select--active'
)}
>
<input
className="ThemeSelectContent-input"
type="text"
onChange={onInputChange}
onFocus={openOptions}
ref={input}
disabled={disabled}
placeholder={getRealValue(
isEditorTpl ? editorDefaultValue : placeholder
)}
/>
</div>
)}
<Overlay
container={document.body as any}
target={target}
show={showOptions && !!options?.length}
rootClose
>
<PopOver overlay onHide={() => setShowOptions(false)}>
<div
className="ThemeSelectContent-input-select"
style={{
minWidth: target?.clientWidth + 'px'
}}
>
{options?.map(item => {
return (
<div
key={item.label}
onClick={() => onSelectValue(item)}
className={cx(
currentItem?.value === item.value &&
'ThemeSelectContent-input-select-item--active'
)}
>
{item.html || item.label}
</div>
);
})}
</div>
</PopOver>
</Overlay>
</>
);
}
function ThemeSelect(props: ThemeSelectProps) {
const {
data,
value: originValue,
options: originOptions,
extraUnit = ['px', 'rem', '%'],
disabled,
state,
itemName,
inheritValue,
isEditorTpl
} = props;
const themeSelect = useRef<HTMLDivElement>(null);
const [options, setOptions] = React.useState<Option[]>(getOptions());
function getOptions() {
const list = cloneDeep(
typeof originOptions === 'string'
? resolveVariableAndFilter(originOptions, data, '| raw')
: isEditorTpl && !originOptions
? data?.sizesOptions || []
: originOptions || []
);
if (
state &&
state !== 'default' &&
list[0] &&
list[0].value !== `var(${data?.default?.token}${itemName})`
) {
const name = isEditorTpl
? 'inherit'
: `var(${data?.default?.token}${itemName})`;
list.unshift({
label: '继承常规',
value: inheritValue || name,
realValue: '继承常规'
});
}
return list;
}
useEffect(() => {
setOptions(getOptions());
}, [originOptions]);
return (
<div ref={themeSelect}>
<ThemeSelectContent
{...props}
value={originValue || ''}
options={options}
extraUnit={extraUnit}
target={themeSelect.current}
disabled={disabled}
/>
</div>
);
}
export default ThemeSelect;
@FormItem({
type: 'amis-theme-select',
strictMode: false,
renderLabel: true
})
export class ThemeSelectRenderer extends React.Component<FormControlProps> {
render() {
return <ThemeSelect {...this.props} />;
}
}

View File

@ -0,0 +1,115 @@
/**
* @file ThemeWrapper.tsx
* @description
*/
import React from 'react';
import {render, Renderer} from 'amis';
import {Icon as ThemeIcon} from '../icons/index';
import cx from 'classnames';
import type {FormControlProps} from 'amis-core';
import {pick} from 'lodash';
import {TooltipWrapper} from 'amis-ui';
interface ThemeWrapperProps {
hasSenior?: boolean;
hasOpen?: boolean;
senior?: boolean;
toggleSenior?: (value: boolean) => void;
open?: boolean;
toggleOpen?: (value: boolean) => void;
title?: string;
}
interface ThemeWrapperControlProps extends FormControlProps {
hasSenior?: boolean;
title?: string;
body?: any;
seniorBody?: any;
}
export function ThemeWrapperHeader(props: ThemeWrapperProps) {
const {hasSenior, hasOpen, senior, toggleSenior, open, toggleOpen, title} =
props;
return (
<div className="Theme-Wrapper">
<div className="Theme-Wrapper-header">
<div className="Theme-Wrapper-header-left">{title}</div>
<div className="Theme-Wrapper-header-right">
{hasSenior && (
<TooltipWrapper
tooltip="扩展配置"
tooltipTheme="dark"
placement="left"
>
<ThemeIcon
icon="custom"
className="common-icon"
onClick={() => toggleSenior && toggleSenior(!senior)}
/>
</TooltipWrapper>
)}
{hasOpen && (
<ThemeIcon
icon="right-arrow-bold"
className={cx('arrow-icon', open ? 'arrow-icon-reverse' : '')}
onClick={() => toggleOpen && toggleOpen(!open)}
/>
)}
</div>
</div>
</div>
);
}
function ThemeWrapperControl(props: ThemeWrapperControlProps) {
const {hasSenior = false, hasOpen = false, body, seniorBody, title} = props;
const [open, toggleOpen] = React.useState(true);
const [senior, toggleSenior] = React.useState(false);
const bodyProps = pick(props, [
'data',
'formMode',
'formLabelAlign',
'formLabelWidth',
'formHorizontal',
'onChange'
]);
return (
<div className="Theme-Wrapper">
{title || title === '' ? (
<ThemeWrapperHeader
hasSenior={hasSenior}
hasOpen={hasOpen}
senior={senior}
toggleSenior={toggleSenior}
open={open}
toggleOpen={toggleOpen}
title={title}
/>
) : null}
<div
className="Theme-Wrapper-body"
style={{display: open ? 'block' : 'none'}}
>
{body ? render(body, bodyProps) : null}
<div
className="Theme-Wrapper-senior"
style={{display: senior ? 'block' : 'none'}}
>
{seniorBody ? render(seniorBody, bodyProps) : null}
</div>
</div>
</div>
);
}
@Renderer({
type: 'amis-theme-wrapper'
})
export default class ThemeWrapperRenderer extends React.Component<ThemeWrapperControlProps> {
render() {
return <ThemeWrapperControl {...this.props} />;
}
}

View File

@ -0,0 +1,8 @@
import './PaddingAndMargin';
import './Border';
import './Radius';
import './ColorPicker';
import './Size';
import './Font';
import './Shadow';
import './ThemeWrapper';

View File

@ -0,0 +1,181 @@
.Theme-Border {
&-label {
margin-bottom: px2rem(10px);
color: #5c5f66;
font-size: 12px;
}
&-content {
display: flex;
justify-content: space-between;
}
&-all {
background: #f7f7f9;
border-radius: 4px;
height: px2rem(32px);
display: inline-flex;
align-items: center;
justify-content: center;
flex: 0 0 px2rem(32px);
&:after {
content: '';
height: px2rem(14px);
width: px2rem(14px);
display: block;
border: 2px solid #2468f2;
}
}
&-items {
position: relative;
width: px2rem(72px);
height: px2rem(72px);
background: #f7f7f9;
border-radius: px2rem(4px);
.Theme-Border-item {
position: absolute;
cursor: pointer;
height: px2rem(14px);
width: px2rem(14px);
}
.Theme-Border-item--all {
left: 50%;
top: 50%;
transform: translate(-50%, -50%);
border: 2px solid #5c5f66;
}
.Theme-Border-item--right {
right: px2rem(7px);
top: 50%;
transform: translateY(-50%);
border: 2px solid #d4d6d9;
&:after {
content: '';
display: block;
height: px2rem(14px);
width: 2px;
background: #5c5f66;
position: absolute;
right: -2px;
top: -2px;
}
}
.Theme-Border-item--left {
left: px2rem(7px);
top: 50%;
transform: translateY(-50%);
border: 2px solid #d4d6d9;
&:after {
content: '';
display: block;
height: px2rem(14px);
width: 2px;
background: #5c5f66;
position: absolute;
left: -2px;
top: -2px;
}
}
.Theme-Border-item--top {
top: px2rem(7px);
left: 50%;
transform: translate(-50%);
border: 2px solid #d4d6d9;
&:after {
content: '';
display: block;
width: px2rem(14px);
height: 2px;
background: #5c5f66;
position: absolute;
right: -2px;
top: -2px;
}
}
.Theme-Border-item--bottom {
bottom: px2rem(7px);
left: 50%;
transform: translate(-50%);
border: 2px solid #d4d6d9;
&:after {
content: '';
display: block;
width: px2rem(14px);
height: 2px;
background: #5c5f66;
position: absolute;
right: -2px;
bottom: -2px;
}
}
.Theme-Border-item--active.Theme-Border-item--all {
border: 2px solid #2468f2;
}
.Theme-Border-item--active {
&:after {
background: #2468f2;
}
}
}
&-settings {
flex: 1;
margin-left: px2rem(16px);
.cxd-Form-item {
margin-bottom: 0;
}
.theme-select {
margin-bottom: px2rem(8px);
}
&-style-color {
display: flex;
justify-content: space-between;
.cxd-Select {
flex: 1;
margin-right: px2rem(4px);
}
}
}
&-settings-width {
width: 100%;
margin-bottom: px2rem(8px);
}
&-settings--all {
margin-left: px2rem(5px);
display: flex;
justify-content: space-between;
.theme-select {
margin-bottom: 0;
margin-right: px2rem(5px);
width: px2rem(80px);
flex: 1 0;
}
.Theme-Border-settings-style-color {
display: flex;
justify-content: space-between;
flex: 1;
.cxd-Select {
width: px2rem(96px);
height: px2rem(32px);
margin-left: px2rem(4px);
}
}
}
&-style {
display: flex;
width: 100%;
align-items: center;
&-line {
border: 1px solid #000000;
height: 1px;
flex: 1;
margin-right: px2rem(14px);
}
}
.is-active {
.Theme-Border-style-line {
border-color: #2468f2;
}
}
}

View File

@ -0,0 +1,600 @@
$ns: cxd-;
.Theme-ColorPicker {
&-label-out {
height: px2rem(32px);
width: px2rem(32px);
border-radius: px2rem(4px);
cursor: pointer;
overflow: hidden;
}
&-label {
height: px2rem(32px);
width: px2rem(32px);
}
&.is-disabled {
color: #b8babf;
border-color: #e8e9eb;
background: #f7f8fa;
}
&.is-readOnly {
pointer-events: none;
}
}
.Theme-ColorPicker-title {
margin-bottom: px2rem(10px);
color: #5c5f66;
font-size: 12px;
}
.Theme-ColorPicker--input {
display: flex;
height: px2rem(32px);
border: 1px solid #e8e9eb;
border-radius: px2rem(4px);
padding: 0px px2rem(10px);
align-items: center;
cursor: pointer;
.Theme-ColorPicker-label-out {
height: px2rem(22px);
width: px2rem(22px);
border-radius: px2rem(4px);
overflow: hidden;
flex-shrink: 0;
}
.Theme-ColorPicker-label {
height: px2rem(22px);
width: px2rem(22px);
}
.Theme-ColorPicker-input {
margin-left: px2rem(6px);
overflow: hidden;
flex-grow: 1;
width: auto;
max-width: 100%;
> div {
white-space: nowrap;
max-width: 100%;
overflow: hidden;
text-overflow: ellipsis;
}
&--placeholder {
color: var(--Form-select-placeholderColor);
}
}
.Theme-ColorPicker-arrow {
width: px2rem(16px);
text-align: center;
display: flex;
align-items: center;
justify-content: center;
line-height: 1;
transform: rotate(90deg);
transition: transform 0.2s;
& > svg {
width: 0.625rem;
height: 0.625rem;
top: 0;
color: var(--default-icon-color);
}
}
.Theme-ColorPicker-arrow--active {
transform: rotate(270deg);
}
}
.Theme-ColorSelect {
width: px2rem(240px);
&-tab {
display: flex;
padding: px2rem(14px) px2rem(12px);
border: 1px solid #e8e9eb;
& > div {
height: px2rem(16px);
width: px2rem(16px);
border-radius: 50%;
margin-right: px2rem(12px);
cursor: pointer;
& > svg {
height: px2rem(16px);
width: px2rem(16px);
}
}
&-color {
background-color: #e8e9eb;
}
&-color--active {
background: #d4e5ff;
border: 1px solid #2468f2;
}
&-gradient {
background-image: linear-gradient(180deg, #f4f4f4 0%, #b8babf 100%);
}
&-gradient--active {
background-image: linear-gradient(180deg, #ffffff 0%, #6296ff 99%);
border: 1px solid #2468f2;
}
&-img--active > svg {
border: 1px solid #2468f2;
border-radius: 50%;
}
}
&-tab {
&-sub {
display: flex;
font-size: 12px;
color: #5c5f66;
padding: px2rem(12px) 0;
margin: 0 px2rem(14px);
border-bottom: 1px solid #e8e9eb;
&-item {
margin-right: px2rem(30px);
cursor: pointer;
}
&--active {
color: #2468f2;
}
}
}
&-content {
padding: px2rem(12px);
}
&-PresetColors {
margin-top: px2rem(10px);
padding-top: px2rem(10px);
border-top: 1px solid #e8e9eb;
&-header {
font-size: 12px;
color: #5c5f66;
}
&-edit {
float: right;
cursor: pointer;
&:hover {
color: #2468f2;
}
}
&-editing {
color: #2468f2;
}
&-content {
margin: 0 px2rem(-4px);
margin-top: px2rem(4px);
display: flex;
flex-wrap: wrap;
& > div {
cursor: pointer;
height: px2rem(20px);
width: px2rem(20px);
border-radius: px2rem(2px);
margin: 0 px2rem(4px);
display: flex;
align-items: center;
justify-content: center;
position: relative;
> div {
height: px2rem(20px);
width: px2rem(20px);
}
}
&-placeholder {
font-size: 12px;
color: #b8babf;
}
}
&-content-editing {
& > div:hover {
&::before {
content: '';
display: block;
position: absolute;
top: 0;
bottom: 0;
left: 0;
right: 0;
background-color: rgba(0, 0, 0, 0.4);
}
&::after {
font-family: 'Font Awesome 5 Free';
content: '\f2ed';
color: #fff;
position: absolute;
font-size: 12px;
}
}
}
}
}
.ThemeColorList {
max-height: px2rem(310px);
width: px2rem(216px);
overflow: auto;
&-title {
font-size: 12px;
color: #151b26;
}
&-content {
display: flex;
margin: px2rem(12px) 0;
&-title {
font-size: 12px;
color: #5c5f66;
font-weight: 400;
margin-right: px2rem(12px);
flex: px2rem(36px) 0 0;
line-height: px2rem(24px);
}
&-label {
height: px2rem(24px);
width: px2rem(24px);
border-radius: px2rem(2px);
margin-right: px2rem(8px);
cursor: pointer;
display: inline-flex;
justify-content: center;
align-items: center;
}
&-label-inner {
height: px2rem(20px);
width: px2rem(20px);
border-radius: px2rem(2px);
}
&-label--border {
border: 1px solid #f7f7f9;
}
&-label--active {
border: 1px solid #2468f2;
border-radius: 2px;
}
}
&-content--top {
margin-top: 0;
position: relative;
}
&-content--search {
position: absolute;
right: 0;
input {
font-size: 12px;
}
.cxd-SearchBox.is-active {
width: px2rem(216px);
}
}
}
.Theme-GradientColor {
&-slider {
display: flex;
align-items: center;
margin-bottom: px2rem(10px);
}
&-slider-inner {
margin: 0 px2rem(7px);
height: px2rem(8px);
position: relative;
display: flex;
align-items: center;
cursor: copy;
flex: 1 1 auto;
margin-right: px2rem(10px);
border: 1px solid #a5a5a5;
border-radius: px2rem(4px);
&-item {
position: absolute;
height: px2rem(14px);
width: px2rem(14px);
border-radius: 50%;
border: 2px solid #ffffff;
cursor: pointer;
box-shadow: 0px 0px 2px 1px #a5a5a5;
}
&-item--active {
box-shadow: 0px 0px 2px 1px #2468f2;
}
}
&-range {
width: px2rem(40px);
position: relative;
.cxd-Number {
height: px2rem(26px);
}
.cxd-Number-handler-wrap {
display: none !important;
}
.cxd-Number-input {
padding: 0 px2rem(4px);
font-size: 12px;
}
&-panel {
width: px2rem(70px);
background: #fff;
padding: px2rem(4px);
&-title {
font-size: 12px;
color: #5c5f66;
transform: scale(0.9);
margin-bottom: px2rem(4px);
}
&-content {
height: 50px;
width: 50px;
margin: 0 auto;
border-radius: 50%;
background: #d0d0d0;
position: relative;
&-handler {
height: 8px;
width: 8px;
border-radius: 50%;
background: #5c5f66;
position: absolute;
cursor: pointer;
left: 12px;
}
}
}
}
}
.Theme-ImageInput {
.resourceManager-background,
.#{$ns}ImageControl-addBtn,
.#{$ns}ImageControl-item,
.#{$ns}Image-thumb,
.#{$ns}Image--thumb {
width: 100%;
}
.#{$ns}Form-item {
margin-bottom: px2rem(8px);
}
&-func {
display: grid;
grid-column-gap: px2rem(10px);
grid-template-columns: auto px2rem(32px) px2rem(32px);
}
}
.Theme-ImageInput-position {
height: px2rem(32px);
width: px2rem(32px);
overflow: hidden;
cursor: pointer;
border: 1px solid #e8e9eb;
border-radius: px2rem(4px);
display: grid;
grid-template-columns: repeat(3, 33.33%);
grid-template-rows: repeat(3, 33.33%);
&-item {
border: 1px solid #e8e9eb;
&:nth-child(1) {
border-top: none;
border-left: none;
}
&:nth-child(2) {
border-top: none;
border-left: none;
border-right: none;
}
&:nth-child(3) {
border-top: none;
border-right: none;
}
&:nth-child(4) {
border-top: none;
border-left: none;
border-bottom: none;
}
&:nth-child(5) {
border: none;
}
&:nth-child(6) {
border-top: none;
border-right: none;
border-bottom: none;
}
&:nth-child(7) {
border-left: none;
border-bottom: none;
}
&:nth-child(8) {
border-left: none;
border-right: none;
border-bottom: none;
}
&:nth-child(9) {
border-right: none;
border-bottom: none;
}
}
&-item--active {
background: #2468f2;
}
}
.Theme-ImageInput-position-container {
padding: px2rem(16px);
padding-top: px2rem(10px);
.Theme-ImageInput-position-title {
font-size: 12px;
margin-bottom: px2rem(10px);
}
}
.Theme-ImageInput-position-content {
width: 100px;
height: 100px;
cursor: pointer;
overflow: hidden;
border: 1px solid #e8e9eb;
border-radius: px2rem(4px);
display: grid;
grid-template-columns: repeat(3, 33.33%);
grid-template-rows: repeat(3, 33.33%);
&-item--active {
background: #2468f2;
}
&-item {
border: 1px solid #e8e9eb;
&:nth-child(1) {
border-top: none;
border-left: none;
}
&:nth-child(2) {
border-top: none;
border-left: none;
border-right: none;
}
&:nth-child(3) {
border-top: none;
border-right: none;
}
&:nth-child(4) {
border-top: none;
border-left: none;
border-bottom: none;
}
&:nth-child(5) {
border: none;
}
&:nth-child(6) {
border-top: none;
border-right: none;
border-bottom: none;
}
&:nth-child(7) {
border-left: none;
border-bottom: none;
}
&:nth-child(8) {
border-left: none;
border-right: none;
border-bottom: none;
}
&:nth-child(9) {
border-right: none;
border-bottom: none;
}
&:hover {
background: #e6f0ff;
}
}
}
.Theme-ImageInput-color {
width: px2rem(32px);
height: px2rem(32px);
cursor: pointer;
border-radius: px2rem(4px);
background-image: linear-gradient(
45deg,
#f7f8fa 25%,
transparent 25%,
transparent 75%,
#f7f8fa 75%,
#f7f8fa
),
linear-gradient(
45deg,
#f7f8fa 25%,
transparent 25%,
transparent 75%,
#f7f8fa 75%,
#f7f8fa
);
background-size: 10px 10px;
background-position: 0 0, 5px 5px;
border: 1px solid #f7f7f9;
}
.Theme-ImageInput-color-container {
padding: 16px;
}
.Theme-ImageInput-color-content {
&-tab {
display: flex;
font-size: 12px;
color: #5c5f66;
padding-bottom: px2rem(14px);
margin-bottom: px2rem(14px);
border-bottom: 1px solid #e8e9eb;
&-item {
margin-right: px2rem(30px);
cursor: pointer;
&--active {
color: #2468f2;
}
}
}
}
.Theme-CustomColor,
.Theme-GradientColor {
.sketch-picker {
box-shadow: none !important;
padding: 0 !important;
}
}
.ThemeColor--transparent {
background-color: #fff !important;
background-image: linear-gradient(
45deg,
#f7f8fa 25%,
transparent 25%,
transparent 75%,
#f7f8fa 75%,
#f7f8fa
),
linear-gradient(
45deg,
#f7f8fa 25%,
transparent 25%,
transparent 75%,
#f7f8fa 75%,
#f7f8fa
) !important;
background-size: 10px 10px !important;
background-position: 0 0, 5px 5px !important;
border: 1px solid #f7f7f9;
}
.ThemeColor--delete {
border: 1px solid #f7f7f9;
width: 100%;
height: 100%;
background: #fff;
&::before {
content: '';
height: 2px;
width: 100%;
display: block;
transform: rotate(-45deg) translateY(-50%);
background-color: #f23d3d;
margin-top: 50%;
}
}
[color-tooltip] {
position: relative;
&:hover {
&:before {
display: block;
}
}
&:before {
content: attr(color-tooltip);
width: max-content;
padding: px2rem(6px);
display: none;
position: absolute;
font-size: 12px;
bottom: px2rem(-35px);
left: 50%;
transform: scale(0.9) translateX(-50%);
box-shadow: 0 0.125rem 0.25rem rgba(0, 0, 0, 0.075);
border-radius: px2rem(2px);
background: #fff;
z-index: 1500;
}
}

View File

@ -0,0 +1,97 @@
$ns: cxd-;
.Theme-FontEditor {
.common-icon {
width: px2rem(16px);
height: px2rem(16px);
cursor: pointer;
color: #5c5f66;
}
&-line {
display: flex;
justify-content: space-between;
margin-bottom: px2rem(12px);
.#{$ns}Button {
padding: px2rem(6px) px2rem(8px);
}
}
&-item {
display: flex;
flex: 1;
margin-right: px2rem(4px);
align-items: top;
flex-direction: column;
min-width: 0;
&:last-child {
margin-right: 0;
}
&-label {
font-size: 12px;
color: #5c5f66;
line-height: px2rem(20px);
margin-top: px2rem(4px);
text-align: center;
}
.#{$ns}Form-item {
flex: 1;
margin: 0;
}
.#{$ns}Select {
font-size: 12px;
}
.#{$ns}Select-popover {
min-width: px2rem(150px) !important;
}
.color-picker {
background: #151b26;
border-radius: 4px;
width: px2rem(32px);
height: px2rem(32px);
}
&-color-picker {
width: px2rem(32px);
flex: 0 1 2rem;
}
}
&-font-line {
margin: 0;
}
&-font-style {
display: flex;
justify-content: stretch;
background: #f7f7f9;
margin-bottom: px2rem(12px);
margin-top: px2rem(8px);
&-icon {
flex: 1;
display: flex;
justify-content: center;
align-items: center;
height: px2rem(32px);
cursor: pointer;
}
.right-line {
border-right: 1px solid #d8d8d8;
}
&-selected {
.common-icon {
color: #2468f2;
}
}
}
}

View File

@ -0,0 +1,224 @@
$bg: url('data:image/svg+xml;base64,Cjxzdmcgd2lkdGg9IjI1NnB4IiBoZWlnaHQ9IjEzMnB4IiB2aWV3Qm94PSIwIDAgMjU2IDEzMiIgdmVyc2lvbj0iMS4xIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHhtbG5zOnhsaW5rPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hsaW5rIj4KICAgIDxnIGlkPSLpobXpnaItMSIgc3Ryb2tlPSJub25lIiBzdHJva2Utd2lkdGg9IjEiIGZpbGw9Im5vbmUiIGZpbGwtcnVsZT0iZXZlbm9kZCI+CiAgICAgICAgPHJlY3QgaWQ9IuefqeW9oiIgZmlsbD0iI0VFRjNGRSIgeD0iMCIgeT0iMCIgd2lkdGg9IjI1NiIgaGVpZ2h0PSIxMzIiIHJ4PSI0Ij48L3JlY3Q+CiAgICAgICAgPHBhdGggZD0iTTEuNTgwNzA5MDIsMC44MTQyODgxMyBMMTI4LDY2IEwxLjU4MDcwOTAyLDEzMS4xODU3MTIgQzAuNjIwMTMxOTM0LDEzMC40NTUxMDUgMS41OTIwMDcxMWUtMTYsMTI5LjI5OTk3MiAwLDEyOCBMMCw0IEMtMS41OTIwMDcxMWUtMTYsMi43MDAwMjc1NCAwLjYyMDEzMTkzNCwxLjU0NDg5NDY2IDEuNTgwNzA5MDIsMC44MTQyODgxMyBaIE0yNTYsNCBMMjU2LDEyOCBDMjU2LDEyOS4yOTk1MiAyNTUuMzgwMywxMzAuNDU0MzAxIDI1NC40MjAyOTQsMTMxLjE4NDk0OSBMMTI4LDY2IEwyNTQuNDE5MjkxLDAuODE0Mjg4MTMgQzI1NS4zNzk4NjgsMS41NDQ4OTQ2NiAyNTYsMi43MDAwMjc1NCAyNTYsNCBaIiBpZD0i5b2i54q257uT5ZCIIiBmaWxsPSIjRTNFRUZGIj48L3BhdGg+CiAgICAgICAgPHBhdGggZD0iTTIxMSwyMyBMMjExLDEwOSBMNDQsMTA5IEw0NCwyMyBMMjExLDIzIFogTTE5OSwyOSBMNTYsMjkgTDU2LDEwMyBMMTk5LDEwMyBMMTk5LDI5IFoiIGlkPSLlvaLnirbnu5PlkIgiIGZpbGw9IiNGRkZGRkYiPjwvcGF0aD4KICAgICAgICA8cmVjdCBpZD0i55+p5b2iIiBmaWxsPSIjRkZGRkZGIiB4PSIxMTEiIHk9IjU3IiB3aWR0aD0iMzQiIGhlaWdodD0iMTgiPjwvcmVjdD4KICAgIDwvZz4KPC9zdmc+');
.Theme-PaddingAndMargin {
&-title {
margin-bottom: px2rem(10px);
color: #5c5f66;
font-size: 12px;
}
&-inner {
display: flex;
justify-content: space-between;
.theme-select {
width: 100%;
}
}
&-input {
flex-direction: column;
align-items: center;
flex: 1;
margin-left: px2rem(4px);
min-width: 0;
&-label {
font-size: 12px;
color: #5c5f66;
text-align: center;
}
}
&-label {
border-radius: 4px;
overflow: hidden;
height: px2rem(32px);
width: px2rem(32px);
flex-shrink: 0;
flex-grow: 0;
display: flex;
cursor: pointer;
&-all {
background: #f7f7f9;
height: px2rem(32px);
display: inline-flex;
align-items: center;
justify-content: center;
width: px2rem(32px);
&:before {
content: '';
height: px2rem(14px);
width: px2rem(14px);
display: block;
border: 2px solid #5c5f66;
border-radius: 2px;
}
}
&-custom {
background: #f7f7f9;
height: px2rem(32px);
width: px2rem(32px);
position: relative;
border-left: 1px solid #e8e9eb;
> div {
height: px2rem(14px);
width: px2rem(14px);
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
&:before,
&:after {
position: absolute;
content: '';
display: block;
background: #5c5f66;
height: px2rem(2px);
width: px2rem(2px);
border-radius: px2rem(1px);
}
}
> div:first-child {
&:before {
width: px2rem(8px);
top: 0;
left: px2rem(3px);
}
&:after {
height: px2rem(8px);
top: px2rem(3px);
left: 0;
}
}
> div:last-child {
&:before {
width: px2rem(8px);
bottom: 0;
left: px2rem(3px);
}
&:after {
height: px2rem(8px);
bottom: px2rem(3px);
right: 0;
}
}
}
&-all--active {
&:before {
border-color: #2468f2;
}
}
&-custom--active > div {
&:before,
&:after {
background-color: #2468f2;
}
}
}
&-label--custom {
width: px2rem(64px);
}
.cxd-Form-item {
margin-bottom: 0;
}
&-custom {
height: px2rem(132px);
width: px2rem(256px);
margin: 0 auto;
margin-top: px2rem(8px);
background: $bg;
position: relative;
&::before,
&::after {
font-size: 10px;
color: #b8babf;
font-weight: 400;
position: absolute;
transform: scale(0.8);
}
& > div {
font-size: 12px;
color: #5c5f66;
position: absolute;
display: flex;
align-items: center;
justify-content: center;
padding: px2rem(2px);
cursor: pointer;
word-wrap: break-word;
line-height: 0.8;
min-width: px2rem(40px);
min-height: px2rem(14px);
border: 1px solid transparent;
div {
transform: scale(0.8);
transform-origin: left;
}
&:hover {
color: #2468f2;
border-color: #2468f2;
border-radius: px2rem(2px);
}
}
&-marginTop {
top: px2rem(4px);
left: 50%;
transform: translateX(-50%);
}
&-marginBottom {
bottom: px2rem(4px);
left: 50%;
transform: translateX(-50%);
}
&-marginLeft {
left: px2rem(4px);
top: 50%;
transform: translateY(-50%);
width: px2rem(40px);
}
&-marginRight {
right: px2rem(4px);
top: 50%;
transform: translateY(-50%);
width: px2rem(40px);
}
&-paddingTop {
top: px2rem(34px);
left: 50%;
transform: translateX(-50%);
}
&-paddingBottom {
bottom: px2rem(34px);
left: 50%;
transform: translateX(-50%);
}
&-paddingLeft {
left: px2rem(60px);
top: 50%;
transform: translateY(-50%);
width: px2rem(40px);
}
&-paddingRight {
right: px2rem(60px);
top: 50%;
transform: translateY(-50%);
width: px2rem(40px);
}
&-popover {
padding: px2rem(16px) px2rem(12px);
.cxd-Form-item {
margin-bottom: 0;
}
}
}
&-custom--padding {
&::after {
content: 'Padding';
top: px2rem(28px);
left: px2rem(56px);
}
}
&-custom--margin {
&::before {
content: 'Margin';
top: 0;
left: px2rem(2px);
}
}
}

View File

@ -0,0 +1,128 @@
.Theme-Radius {
&-label {
margin-bottom: px2rem(10px);
color: #5c5f66;
font-size: 12px;
}
.cxd-Form-item {
margin-bottom: 0;
}
&-inner {
display: flex;
}
&-item {
margin-right: px2rem(4px);
border-radius: 4px;
overflow: hidden;
height: px2rem(32px);
width: px2rem(32px);
flex-shrink: 0;
flex-grow: 0;
display: flex;
cursor: pointer;
&-all {
background: #f7f7f9;
height: px2rem(32px);
display: inline-flex;
align-items: center;
justify-content: center;
width: px2rem(32px);
&:before {
content: '';
height: px2rem(14px);
width: px2rem(14px);
display: block;
border: 2px solid #5c5f66;
border-radius: 2px;
}
}
&-custom {
background: #f7f7f9;
height: px2rem(32px);
position: relative;
width: px2rem(32px);
border-left: 1px solid #e8e9eb;
&:before {
content: '';
height: px2rem(14px);
width: px2rem(14px);
display: block;
border: 2px solid #5c5f66;
position: absolute;
left: 50%;
top: 50%;
transform: translate(-50%, -50%);
border-radius: 2px;
}
&:after {
content: '';
color: #f7f7f9;
display: block;
position: absolute;
left: 50%;
top: 50%;
transform: translate(-50%, -50%);
font-size: px2rem(30px);
font-weight: 900;
}
}
&-all--active,
&-custom--active {
&:before {
border-color: #2468f2;
}
}
}
&-item--custom {
width: px2rem(64px);
}
&-settings {
flex: 1;
}
&-settings-custom {
display: flex;
justify-content: space-between;
margin-top: px2rem(8px);
.arrow-icon {
display: none;
}
input {
padding: 0 !important;
}
.theme-select {
padding: 0 px2rem(4px) !important;
}
&-item:last-child {
margin-right: 0;
}
&-item {
flex: 1;
min-width: 0;
margin-right: px2rem(4px);
&-label {
height: px2rem(10px);
width: px2rem(10px);
border: 0 solid #5c5f66;
margin: px2rem(8px) auto;
border-radius: 2px;
}
&-top-left {
border-top-width: 2px;
border-left-width: 2px;
}
&-top-right {
border-top-width: 2px;
border-right-width: 2px;
}
&-bottom-left {
border-bottom-width: 2px;
border-left-width: 2px;
}
&-bottom-right {
border-bottom-width: 2px;
border-right-width: 2px;
}
}
}
}

View File

@ -0,0 +1,236 @@
$ns: cxd-;
.Theme-ShadowEditor {
.#{$ns}Theme-ShadowEditor-add {
color: #5c5f66;
width: px2rem(12px);
height: px2rem(12px);
padding: 0;
&:not(:disabled):not(.is-disabled):hover {
color: #5c5f66;
}
}
&-customContent {
background-color: #f7f7f9;
border-radius: 4px;
padding: px2rem(10px);
margin-top: px2rem(10px);
}
&-sub-header {
margin-bottom: 0;
.Theme-Wrapper-header-left {
color: #5c5f66;
}
}
&-line {
display: flex;
justify-content: space-between;
margin-top: px2rem(12px);
.#{$ns}Button {
padding: px2rem(6px) px2rem(8px);
}
}
&-item {
display: flex;
flex: 1;
margin-right: px2rem(4px);
align-items: top;
flex-direction: column;
&:last-child {
margin-right: 0;
}
&-label {
font-size: 12px;
color: #5c5f66;
line-height: px2rem(12px);
margin: px2rem(4px) 0 px2rem(8px);
text-align: center;
}
.#{$ns}Form-item {
flex: 1;
margin: 0;
}
.#{$ns}Select {
font-size: 12px;
}
.#{$ns}Select-popover {
min-width: px2rem(150px) !important;
}
.Theme-ShadowEditor-color-picker {
background: #fff;
border: 1px solid rgba($color: #979797, $alpha: 0.1);
border-radius: px2rem(4px);
padding: px2rem(6px) px2rem(12px);
height: px2rem(32px);
display: flex;
justify-content: center;
align-items: center;
.Theme-ColorPicker-arrow {
display: none;
}
.Theme-ColorPicker-label-out,
.Theme-ColorPicker-label {
height: px2rem(20px);
}
}
.#{$ns}Number {
.#{$ns}Select {
display: none;
}
.#{$ns}Number-handler-wrap {
display: none !important;
}
input {
padding: 0 px2rem(4px) !important;
}
}
}
.trash-icon {
font-size: px2rem(16px);
align-items: center;
margin-left: px2rem(4px);
flex-basis: px2rem(16px);
flex-grow: initial;
.common-icon {
margin-top: px2rem(8px);
cursor: pointer;
path {
fill: var(--colors-neutral-text-2);
}
&:hover {
path {
fill: var(--colors-brand-5);
}
}
}
.disabled-icon {
cursor: not-allowed;
path {
fill: var(--colors-neutral-text-5);
}
&:hover {
path {
fill: var(--colors-neutral-text-5);
}
}
}
}
&-view {
width: px2rem(42px);
height: px2rem(32px);
border: 1px solid rgba($color: #979797, $alpha: 0.1);
border-radius: px2rem(4px);
margin-right: px2rem(4px);
background-color: #fff;
background-image: linear-gradient(
45deg,
#f7f8fa 25%,
transparent 25%,
transparent 75%,
#f7f8fa 75%,
#f7f8fa
),
linear-gradient(
45deg,
#f7f8fa 25%,
transparent 25%,
transparent 75%,
#f7f8fa 75%,
#f7f8fa
);
background-size: 10px 10px;
background-position: 0 0, 5px 5px;
overflow: hidden;
display: flex;
justify-content: center;
align-items: center;
&-inner {
width: px2rem(28px);
height: px2rem(20px);
background: #fff;
}
}
}
.Theme-ShadowView {
width: px2rem(300px);
font-size: 12px;
padding: px2rem(12px);
&-header {
color: #050a10;
line-height: px2rem(20px);
font-weight: 500;
margin-bottom: px2rem(8px);
}
&-body {
border: 1px solid #e8e9eb;
border-radius: px2rem(4px);
padding: px2rem(12px);
&-shadow {
width: 100%;
height: px2rem(100px);
background-color: #fff;
background-image: linear-gradient(
45deg,
#f7f8fa 25%,
transparent 25%,
transparent 75%,
#f7f8fa 75%,
#f7f8fa
),
linear-gradient(
45deg,
#f7f8fa 25%,
transparent 25%,
transparent 75%,
#f7f8fa 75%,
#f7f8fa
);
background-size: 20px 20px;
background-position: 0 0, 10px 10px;
overflow: hidden;
display: flex;
justify-content: center;
align-items: center;
}
&-shadow-square {
width: px2rem(164px);
height: px2rem(70px);
background: #fff;
}
&-title {
font-size: 12px;
color: #050a10;
line-height: px2rem(20px);
font-weight: 500;
margin: px2rem(8px) 0 0;
}
&-value {
color: #83868c;
line-height: px2rem(20px);
}
}
}

View File

@ -0,0 +1,118 @@
$ns: cxd-;
.Theme-SizeEditor {
&-label {
margin-bottom: 0.625rem;
color: #5c5f66;
font-size: 12px;
}
&-line {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: px2rem(12px);
.#{$ns}Button {
padding: px2rem(6px) px2rem(8px);
width: px2rem(32px);
}
&-no-hide {
.Theme-SizeEditor-item {
width: px2rem(210px);
max-width: px2rem(210px);
.theme-select {
width: px2rem(174px);
max-width: px2rem(174px);
}
}
}
.Theme-SizeEditor-item-label {
width: px2rem(36px);
}
.Theme-SizeEditor-item:not(:last-child) {
margin-bottom: px2rem(8px);
}
}
&-lock {
position: relative;
&::before {
content: '';
display: block;
position: absolute;
top: px2rem(-10px);
left: px2rem(-10px);
width: px2rem(26px);
height: px2rem(10px);
border: none;
border-top: 1px solid #b8babf;
border-right: 1px solid #b8babf;
}
&::after {
content: '';
display: block;
position: absolute;
bottom: px2rem(-10px);
left: px2rem(-10px);
width: px2rem(26px);
height: px2rem(10px);
border: none;
border-bottom: 1px solid #b8babf;
border-right: 1px solid #b8babf;
}
}
&-item {
display: flex;
flex: 1;
align-items: center;
&-label {
padding: px2rem(6px) px2rem(12px);
font-size: 12px;
color: #b8babf;
line-height: 18px;
border: px2rem(1px) solid #e8e9eb;
border-right: 0;
border-top-left-radius: px2rem(4px);
border-bottom-left-radius: px2rem(4px);
}
.#{$ns}Form-item {
margin: 0;
}
.#{$ns}TextControl-input {
border-top-left-radius: 0;
border-bottom-left-radius: 0;
font-size: 12px;
}
.#{$ns}TextControl-sugs {
min-width: px2rem(150px) !important;
}
}
&-item-sigle {
display: block;
.#{$ns}Form-item {
width: auto;
}
.Theme-SizeEditor-item {
div {
flex-grow: 1;
}
.Theme-SizeEditor-item-label {
width: auto;
flex-grow: 0;
}
}
}
}

View File

@ -0,0 +1,88 @@
$ns: cxd-;
.theme-select {
position: relative;
flex: 1 0 px2rem(32px);
border: 1px solid #e8e9eb;
border-radius: 4px;
height: px2rem(32px);
padding: 0 px2rem(8px);
display: flex;
align-items: center;
.ThemeSelectContent-theme {
background-color: #f7f8fa;
border-radius: 2px;
padding: 0 px2rem(4px);
width: fit-content;
height: px2rem(24px);
display: flex;
align-items: center;
cursor: pointer;
overflow: hidden;
> div {
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
> .icon-close {
color: #b8babf;
margin-left: px2rem(4px);
top: 0;
flex: 1 0 1em;
&:hover {
color: #2468f2;
}
}
}
.ThemeSelectContent-input {
border: none;
outline: none;
width: 100%;
&::placeholder {
color: #b8babf;
}
}
&:hover,
&--active {
border-color: #2468f2;
}
}
.theme-select--disabled {
background-color: #f7f8fa;
cursor: not-allowed;
.ThemeSelectContent-theme {
cursor: not-allowed;
}
}
.ThemeSelectContent-input-select {
max-height: px2rem(200px);
max-width: px2rem(200px);
overflow: scroll;
& > div {
height: px2rem(32px);
line-height: px2rem(32px);
padding: 0 px2rem(8px);
cursor: pointer;
&:hover {
background-color: #e6f0ff;
}
}
&-item--active {
color: #2468f2;
}
}
.arrow-icon {
width: px2rem(10px);
height: px2rem(10px);
color: #84868c;
transform: rotate(90deg);
transition: transform 0.2s ease;
}
.arrow-icon-reverse {
transform: rotate(270deg);
}

View File

@ -0,0 +1,69 @@
$ns: cxd-;
.Theme-Wrapper {
.common-icon {
width: px2rem(16px);
height: px2rem(16px);
cursor: pointer;
color: #5c5f66;
}
&-header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: px2rem(8px);
&-left {
font-size: 12px;
color: #070c14;
line-height: px2rem(20px);
font-weight: 400;
}
&-right {
display: flex;
align-items: center;
.arrow-icon {
width: px2rem(10px);
height: px2rem(10px);
color: #84868c;
transform: rotate(90deg);
transition: transform 0.2s ease;
margin-left: px2rem(8px);
cursor: pointer;
}
.arrow-icon-reverse {
transform: rotate(270deg);
}
}
}
&-body {
.#{$ns}Form-item {
margin-bottom: px2rem(16px);
}
.theme-select .#{$ns}Form-item {
margin-bottom: 0;
}
.theme-select,
.#{$ns}IconSelectControl-input {
border-radius: 0 px2rem(4px) px2rem(4px) 0;
height: px2rem(32px);
}
.#{$ns}Form-label {
border: 1px solid #e8e9eb;
border-right: none;
border-radius: px2rem(4px) 0 0 px2rem(4px);
padding: 0 px2rem(12px);
width: auto !important;
flex-grow: 0;
height: px2rem(32px);
}
}
}

View File

@ -0,0 +1,15 @@
$remFactor: 16px;
@import '../../../../node_modules/amis-ui/scss/functions';
@import './padding-and-margin';
@import './border';
@import './radius';
@import './color-picker';
@import './size';
@import './theme-select';
@import './font';
@import './theme-wrapper';
@import './shadow';
.cxd-PopOver {
z-index: 1400 !important;
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,3 @@
import cxdData from './cxd';
import antdData from './antd';
export {cxdData, antdData};

View File

@ -0,0 +1,156 @@
import cloneDeep from 'lodash/cloneDeep';
/**
*
*/
export function getValueByPath(path: string | string[], data: any): any {
try {
if (!path || !data) {
return null;
}
let res = {};
const getValue = (p: string) => {
const keys = p.split('.');
let value = cloneDeep(data.themeConfig.component);
let defaultToken = '';
for (let i = 0; i < keys.length; i++) {
let key = keys[i];
const isVar = /\$\{(.*)\}/.exec(key) || [];
if (isVar[1]) {
key = data[isVar[1]] || 'default';
}
if (Array.isArray(value)) {
value = value.find(n => n.type === key);
} else {
if (key === 'hover' || key === 'active' || key === 'disabled') {
defaultToken = value['default'].token;
}
value = value[key];
}
}
if (defaultToken && value) {
// 继承default
if (typeof value === 'object') {
for (let key in value) {
if (value[key] === `var(${defaultToken}${key})`) {
value[key] = 'inherit';
}
}
} else {
if (value === `var(${defaultToken}${keys[keys.length - 1]})`) {
value = 'inherit';
}
}
}
return value;
};
if (Array.isArray(path)) {
path.forEach(p => {
let value = getValue(p);
if (typeof value === 'string') {
value = {color: value};
}
res = Object.assign(res, value);
});
} else {
res = getValue(path);
}
return res;
} catch (e) {
return null;
}
}
/**
*
*/
export function getInheritValue(path: string | string[], data: any): any {
try {
if (!path || !data) {
return null;
}
let res = {};
const getValue = (p: string) => {
const keys = p.split('.');
let value = cloneDeep(data.themeConfig.component);
let defaultToken = '';
for (let i = 0; i < keys.length; i++) {
let key = keys[i];
const isVar = /\$\{(.*)\}/.exec(key) || [];
if (isVar[1]) {
key = data[isVar[1]] || 'default';
}
if (Array.isArray(value)) {
value = value.find(n => n.type === key);
} else {
if (key === 'hover' || key === 'active' || key === 'disabled') {
defaultToken = value['default'].token;
value = value['default'];
} else {
value = value[key];
}
}
if (!value) {
break;
}
}
if (defaultToken && value) {
return value;
}
return null;
};
if (Array.isArray(path)) {
path.forEach(p => {
let value = getValue(p);
if (typeof value === 'string') {
value = {color: value};
}
res = Object.assign(res, value);
});
} else {
res = getValue(path);
}
return res;
} catch (e) {
return null;
}
}
// 处理传入的继承数据
export function formatInheritData(data: any) {
if (typeof data === 'string' && data.indexOf('inherit:') > -1) {
return 'inherit';
}
if (!data || typeof data !== 'object') {
return data;
}
data = cloneDeep(data);
for (let key in data) {
if (typeof data[key] === 'string' && data[key].indexOf('inherit:') > -1) {
data[key] = 'inherit';
}
}
return data;
}
// 设置继承数据
export function setInheritData(value: any, editorInheritValue: any) {
if (value && editorInheritValue) {
if (typeof value === 'string') {
if (value === 'inherit') {
value = 'inherit:' + (editorInheritValue || '');
}
} else {
value = cloneDeep(value);
for (let key in value) {
if (value[key] === 'inherit') {
value[key] = 'inherit:' + (editorInheritValue[key] || '');
}
}
}
}
return value;
}

View File

@ -0,0 +1,18 @@
{
"extends": "../../tsconfig.json",
"compilerOptions": {
"outDir": "lib",
"rootDir": "./src",
"typeRoots": [
"../../types",
"./node_modules/@types",
"../../node_modules/@types"
]
},
"include": ["src/**/*"],
"references": [
{"path": "../amis"},
{"path": "../amis-ui"},
{"path": "../amis-core"}
]
}

View File

@ -0,0 +1,5 @@
declare module '*.json' {
const value: any;
export default value;
}
declare module 'plugin-react-i18n';

View File

@ -109,6 +109,7 @@ export interface TooltipWrapperProps {
*/ */
onVisibleChange?: (visible: boolean) => void; onVisibleChange?: (visible: boolean) => void;
children?: React.ReactNode | Array<React.ReactNode>; children?: React.ReactNode | Array<React.ReactNode>;
disabled?: boolean;
} }
interface TooltipWrapperState { interface TooltipWrapperState {

93
publish-theme.sh Normal file
View File

@ -0,0 +1,93 @@
#!/bin/bash
set -e
source ./scripts/utils.sh
echo "请选择发布内网or外网"
publish_types=("internal" "external")
select_option "${publish_types[@]}"
publish_type=$selected_option
echo "请选择发布版本的类型:"
options=("latest" "beta" "alpha" "custom")
select_option "${options[@]}"
if [ "$selected_option" == "custom" ]; then
read -p "请自定义输入版本: " version
npm_get_tag $version
tag=$npm_tag
else
tag=$selected_option
if [ "$publish_type" == "internal" ]; then
current_version=`npm show @fex/amis-theme-editor-helper@${tag} version --registry=http://registry.npm.baidu-int.com`
else
current_version=`npm show amis-theme-editor-helper@${tag} version`
fi
if [ -z "${current_version}" ]; then
echo "没有找到的${tag}版本"
read -p "请自定义输入版本: " version
npm_get_tag $version
tag=$npm_tag
else
echo "当前版本:${current_version}"
npm_version $current_version $tag
version=$new_version
read -p "确认更新y or n: " confirm
if [ "$confirm" != "y" ]; then
read -p "请自定义输入版本: " version
npm_get_tag $version
tag=$npm_tag
fi
fi
fi
sed -i '' -e 's/\"version\": \".*\"/\"version\": \"'${version}'\"/g' ./packages/amis-theme-editor-helper/package.json
npm run build --workspace=amis-theme-editor-helper
rm -rf theme-npm
mkdir -p theme-npm/amis-theme-editor-helper
cp -rf packages/amis-theme-editor-helper/lib theme-npm/amis-theme-editor-helper
cp -rf packages/amis-theme-editor-helper/esm theme-npm/amis-theme-editor-helper
cp packages/amis-theme-editor-helper/package.json theme-npm/amis-theme-editor-helper
cd theme-npm/amis-theme-editor-helper
if [ "$publish_type" == "internal" ]; then
# package.json 里面把包名称换了
for f in $(find ./ -name "package.json"); do
sed -i '' -e 's/\"name\": \"amis/\"name\": \"@fex\/amis/g' $f
sed -i '' -e 's/\"amis-/\"@fex\/amis-/g' $f
sed -i '' -e 's/\"amis\":/\"@fex\/amis\":/g' $f
sed -i '' -e 's/\"i18n-runtime\":/\"@fex\/i18n-runtime\":/g' $f
done
# 把代码里面import的部分换成内部包名称
for f in $(find ./ -type f -name "*.[tj]s"); do
# 正则那个 | 用不了,还不知道为何
#sed -i '' -e "s#\('|\"\)\(amis|amis-formula|amis-core|amis-ui|amis-editor|amis-editor-core\)\('|\"|\/\)#\1@fex\/\2\3#g" $f
sed -i '' -e "s#'\(amis\)\(['\"/]\)#'@fex\/\1\2#g" $f
sed -i '' -e "s#\"\(amis\)\(['\"/]\)#\"@fex\/\1\2#g" $f
sed -i '' -e "s#'\(amis-core\)\(['\"/]\)#'@fex\/\1\2#g" $f
sed -i '' -e "s#\"\(amis-core\)\(['\"/]\)#\"@fex\/\1\2#g" $f
sed -i '' -e "s#'\(amis-ui\)\(['\"/]\)#'@fex\/\1\2#g" $f
sed -i '' -e "s#\"\(amis-ui\)\(['\"/]\)#\"@fex\/\1\2#g" $f
sed -i '' -e "s#'\(i18n-runtime\)\(['\"/]\)#'@fex\/\1\2#g" $f
sed -i '' -e "s#\"\(i18n-runtime\)\(['\"/]\)#\"@fex\/\1\2#g" $f
done
npm publish --tag=$tag --registry=http://registry.npm.baidu-int.com
else
npm publish --tag=$tag
fi

83
scripts/utils.sh Normal file
View File

@ -0,0 +1,83 @@
#!/bin/bash
render_option() {
for index in "${!choices[@]}"; do
if [ $index -eq $1 ]; then
printf "\033[31m> ${choices[$index]}\033[0m\n" # 高亮显示选中的选项
else
echo " ${choices[$index]}"
fi
done
}
clear_screen() {
local len=$1
echo "\033[${len}A\033[K"
for ((i=1;i<$len;i++)); do
echo "\033[K"
done
echo "\033[$((${len} + 1))A"
}
select_option() {
choices=("$@") # 将选项数组声明为全局变量
local selected=0 # 初始化选择索引
local choices_lenght=${#choices[@]} # 获取选项数组长度
render_option $selected
while true; do
read -n1 -s key # 读取单个按键并保持输入的隐私
case "$key" in
A) # 上箭头
if [ $selected -gt 0 ]; then
selected=$((selected - 1))
else
selected=$(($choices_lenght - 1))
fi
clear_screen $choices_lenght
render_option $selected
;;
B) # 下箭头
if [ $selected -lt $(($choices_lenght - 1)) ]; then
selected=$((selected + 1))
else
selected=0
fi
clear_screen $choices_lenght
render_option $selected
;;
"") # 回车键
break
;;
esac
done
# 打印最终结果日志
selected_option="${choices[$selected]}"
}
npm_version() {
local current_version=$1
local tag=$2
IFS='.-' read -r major minor patch pre_release pre_release_version <<< "$current_version"
if [ $tag = $pre_release ]; then
((pre_release_version++))
new_version="$major.$minor.$patch-$tag.$pre_release_version"
else
((patch++))
new_version="$major.$minor.$patch"
fi
echo "新版本为:$new_version"
}
npm_get_tag() {
IFS='.-' read -r major minor patch pre_release pre_release_version <<< "$1"
if [ "$pre_release" ]; then
npm_tag=$pre_release
else
npm_tag="latest"
fi
echo "发布tag为: $npm_tag"
}

View File

@ -29,7 +29,10 @@
"amis": ["./packages/amis/src/index.tsx"], "amis": ["./packages/amis/src/index.tsx"],
"office-viewer": ["./packages/office-viewer/src/index.ts"], "office-viewer": ["./packages/office-viewer/src/index.ts"],
"amis-editor-core": ["./packages/amis-editor-core/src/index.ts"], "amis-editor-core": ["./packages/amis-editor-core/src/index.ts"],
"amis-editor": ["./packages/amis-editor/src/index.tsx"] "amis-editor": ["./packages/amis-editor/src/index.tsx"],
"amis-theme-editor-helper": [
"./packages/amis-theme-editor-helper/src/index.ts"
]
} }
}, },
"watchOptions": { "watchOptions": {

View File

@ -14,25 +14,6 @@ import i18nConfig from './i18nConfig';
var I18N = process.env.I18N; var I18N = process.env.I18N;
var PROXY_THEME = process.env.PROXY_THEME
? [
{
find: 'amis-theme-editor/lib/renderers.css',
replacement: path.resolve(
__dirname,
'../editor/packages/amis-theme-editor/src/renderers/style/_index.scss'
)
},
{
find: 'amis-theme-editor/lib',
replacement: path.resolve(
__dirname,
'../editor/packages/amis-theme-editor/src'
)
}
]
: [];
// https://vitejs.dev/config/ // https://vitejs.dev/config/
export default defineConfig({ export default defineConfig({
plugins: [ plugins: [
@ -126,7 +107,14 @@ export default defineConfig({
{ {
find: 'office-viewer', find: 'office-viewer',
replacement: path.resolve(__dirname, './packages/office-viewer/src') replacement: path.resolve(__dirname, './packages/office-viewer/src')
},
{
find: 'amis-theme-editor-helper',
replacement: path.resolve(
__dirname,
'./packages/amis-theme-editor-helper/src'
)
} }
].concat(PROXY_THEME) ]
} }
}); });