feat: 主题编辑器渲染器开源 (#8820)
* feat: 主题编辑器渲染器开源 * 笔误 * 优化发布脚本 * 优化发布脚本 * 删除无用代码 * bugfix * bugfix * bugfix * bugfix --------- Co-authored-by: qinhaoyan <30946345+qinhaoyan@users.noreply.github.com>
3
.gitignore
vendored
@ -14,6 +14,8 @@ _site
|
||||
node_modules
|
||||
/dist
|
||||
/lib
|
||||
**/esm
|
||||
**/lib
|
||||
/sdk
|
||||
/public
|
||||
/gh-pages
|
||||
@ -26,6 +28,7 @@ node_modules
|
||||
/npm
|
||||
/mock/cfc/cfc.zip
|
||||
.rollup.cache
|
||||
/theme-npm
|
||||
|
||||
dist
|
||||
tsconfig.tsbuildinfo
|
||||
|
@ -6,7 +6,8 @@
|
||||
"packages/amis-ui",
|
||||
"packages/amis",
|
||||
"packages/amis-editor-core",
|
||||
"packages/amis-editor"
|
||||
"packages/amis-editor",
|
||||
"packages/amis-theme-editor-helper"
|
||||
],
|
||||
"scripts": {
|
||||
"fis3-serve": "fis3 server start --www ./public --port 8888 --no-daemon --no-browse",
|
||||
@ -86,7 +87,7 @@
|
||||
"magic-string": "^0.26.7",
|
||||
"marked": "^4.2.1",
|
||||
"monaco-editor": "0.30.1",
|
||||
"plugin-react-i18n": "1.0.1",
|
||||
"plugin-react-i18n": "1.0.4",
|
||||
"postcss-scss": "^4.0.6",
|
||||
"prismjs": "^1.29.0",
|
||||
"react": "^18.2.0",
|
||||
|
@ -47,6 +47,7 @@
|
||||
"static"
|
||||
],
|
||||
"dependencies": {
|
||||
"amis-theme-editor-helper": "*",
|
||||
"axios": "0.21.1",
|
||||
"deep-diff": "1.0.2",
|
||||
"json-ast-comments": "^1.1.0",
|
||||
|
@ -10,5 +10,5 @@
|
||||
]
|
||||
},
|
||||
"include": ["src/**/*"],
|
||||
"references": [{"path": "../amis"}]
|
||||
"references": [{"path": "../amis"}, {"path": "../amis-theme-editor-helper"}]
|
||||
}
|
||||
|
@ -6,7 +6,7 @@ import {currentLocale} from 'i18n-runtime';
|
||||
import {Portal} from 'react-overlays';
|
||||
import {Icon} from './icons/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';
|
||||
@ -14,7 +14,7 @@ import themeConfig from 'amis-theme-editor-helper/lib/systemTheme/cxd';
|
||||
// import './utils/overwriteSchemaTpl';
|
||||
// const i18nEnabled = true;
|
||||
const i18nEnabled = false;
|
||||
setThemeConfig(themeConfig);
|
||||
setThemeConfig(cxdData);
|
||||
|
||||
const schema = {
|
||||
type: 'page',
|
||||
|
@ -42,8 +42,8 @@
|
||||
"dependencies": {
|
||||
"@webcomponents/webcomponentsjs": "^2.6.0",
|
||||
"amis-editor-core": "*",
|
||||
"amis-theme-editor-helper": "*",
|
||||
"amis-postcss": "1.0.0",
|
||||
"amis-theme-editor": "*",
|
||||
"i18n-runtime": "*",
|
||||
"lodash": "^4.17.15",
|
||||
"mobx-state-tree": "^3.17.3"
|
||||
@ -102,8 +102,8 @@
|
||||
"amis": "*",
|
||||
"amis-core": "*",
|
||||
"amis-formula": "*",
|
||||
"amis-theme-editor": "*",
|
||||
"amis-ui": "*",
|
||||
"amis-theme-editor-helper": "*",
|
||||
"i18n-runtime": "*",
|
||||
"react": ">=16.8.6",
|
||||
"react-dom": ">=16.8.6"
|
||||
|
@ -51,16 +51,7 @@ import './renderer/InputRangeValueControl';
|
||||
import './renderer/FunctionEditorControl';
|
||||
import './renderer/ListItemControl';
|
||||
|
||||
import 'amis-theme-editor/lib/locale/zh-CN';
|
||||
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';
|
||||
import 'amis-theme-editor-helper';
|
||||
|
||||
export * from './component/BaseControl';
|
||||
export * from './icons/index';
|
||||
|
@ -10,5 +10,9 @@
|
||||
]
|
||||
},
|
||||
"include": ["src/**/*"],
|
||||
"references": [{"path": "../amis"}, {"path": "../amis-editor-core"}]
|
||||
"references": [
|
||||
{"path": "../amis"},
|
||||
{"path": "../amis-editor-core"},
|
||||
{"path": "../amis-theme-editor-helper"}
|
||||
]
|
||||
}
|
||||
|
35
packages/amis-theme-editor-helper/i18nConfig.js
Normal 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'
|
||||
}
|
||||
};
|
69
packages/amis-theme-editor-helper/package.json
Normal 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": "*"
|
||||
}
|
||||
}
|
149
packages/amis-theme-editor-helper/rollup.config.js
Normal 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}
|
||||
`
|
||||
})
|
||||
];
|
||||
}
|
458
packages/amis-theme-editor-helper/src/helper/ColorGenerator.ts
Normal 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;
|
||||
}
|
||||
}
|
299
packages/amis-theme-editor-helper/src/helper/ParseThemeData.ts
Normal 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]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
163
packages/amis-theme-editor-helper/src/helper/declares.ts
Normal 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;
|
||||
}
|
202
packages/amis-theme-editor-helper/src/helper/getGlobalData.ts
Normal 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
|
||||
};
|
||||
}
|
72
packages/amis-theme-editor-helper/src/helper/styleHelper.ts
Normal 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 '';
|
||||
}
|
||||
}
|
@ -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;
|
||||
}
|
@ -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 |
@ -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 |
10
packages/amis-theme-editor-helper/src/icons/checkbox.svg
Normal 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 |
18
packages/amis-theme-editor-helper/src/icons/code.svg
Normal 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 |
@ -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 |
@ -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 |
20
packages/amis-theme-editor-helper/src/icons/component.svg
Normal 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 |
18
packages/amis-theme-editor-helper/src/icons/custom.svg
Normal 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 |
@ -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 |
18
packages/amis-theme-editor-helper/src/icons/global.svg
Normal 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 |
54
packages/amis-theme-editor-helper/src/icons/index.tsx
Normal 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};
|
15
packages/amis-theme-editor-helper/src/icons/italic.svg
Normal 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 |
16
packages/amis-theme-editor-helper/src/icons/line-through.svg
Normal 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 |
15
packages/amis-theme-editor-helper/src/icons/lock.svg
Normal 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 |
15
packages/amis-theme-editor-helper/src/icons/text-center.svg
Normal 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 |
15
packages/amis-theme-editor-helper/src/icons/text-justify.svg
Normal 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 |
13
packages/amis-theme-editor-helper/src/icons/text-left.svg
Normal 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 |
15
packages/amis-theme-editor-helper/src/icons/text-right.svg
Normal 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 |
12
packages/amis-theme-editor-helper/src/icons/underline.svg
Normal 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 |
15
packages/amis-theme-editor-helper/src/icons/unlock.svg
Normal 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 |
@ -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 |
@ -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 |
12
packages/amis-theme-editor-helper/src/icons/vertical-top.svg
Normal 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 |
10
packages/amis-theme-editor-helper/src/index.ts
Normal 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';
|
233
packages/amis-theme-editor-helper/src/locale/en-US.ts
Normal 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'
|
||||
});
|
2
packages/amis-theme-editor-helper/src/locale/index.ts
Normal file
@ -0,0 +1,2 @@
|
||||
import './en-US';
|
||||
import './zh-CN';
|
232
packages/amis-theme-editor-helper/src/locale/zh-CN.ts
Normal 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': '系统预设主题'
|
||||
});
|
343
packages/amis-theme-editor-helper/src/renderers/Border.tsx
Normal 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} />;
|
||||
}
|
||||
}
|
1517
packages/amis-theme-editor-helper/src/renderers/ColorPicker.tsx
Normal file
1150
packages/amis-theme-editor-helper/src/renderers/Font.tsx
Normal 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}
|
||||
/>
|
||||
);
|
||||
}
|
||||
}
|
248
packages/amis-theme-editor-helper/src/renderers/Radius.tsx
Normal 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} />;
|
||||
}
|
||||
}
|
447
packages/amis-theme-editor-helper/src/renderers/Shadow.tsx
Normal 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} />;
|
||||
}
|
||||
}
|
260
packages/amis-theme-editor-helper/src/renderers/Size.tsx
Normal 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} />;
|
||||
}
|
||||
}
|
345
packages/amis-theme-editor-helper/src/renderers/ThemeSelect.tsx
Normal 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} />;
|
||||
}
|
||||
}
|
115
packages/amis-theme-editor-helper/src/renderers/ThemeWrapper.tsx
Normal 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} />;
|
||||
}
|
||||
}
|
@ -0,0 +1,8 @@
|
||||
import './PaddingAndMargin';
|
||||
import './Border';
|
||||
import './Radius';
|
||||
import './ColorPicker';
|
||||
import './Size';
|
||||
import './Font';
|
||||
import './Shadow';
|
||||
import './ThemeWrapper';
|
181
packages/amis-theme-editor-helper/src/style/_border.scss
Normal 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;
|
||||
}
|
||||
}
|
||||
}
|
600
packages/amis-theme-editor-helper/src/style/_color-picker.scss
Normal 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;
|
||||
}
|
||||
}
|
97
packages/amis-theme-editor-helper/src/style/_font.scss
Normal 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
128
packages/amis-theme-editor-helper/src/style/_radius.scss
Normal 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
236
packages/amis-theme-editor-helper/src/style/_shadow.scss
Normal 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);
|
||||
}
|
||||
}
|
||||
}
|
118
packages/amis-theme-editor-helper/src/style/_size.scss
Normal 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -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);
|
||||
}
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
15
packages/amis-theme-editor-helper/src/style/index.scss
Normal 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;
|
||||
}
|
1187
packages/amis-theme-editor-helper/src/systemTheme/antd.ts
Normal file
6157
packages/amis-theme-editor-helper/src/systemTheme/component.ts
Normal file
1513
packages/amis-theme-editor-helper/src/systemTheme/cxd.ts
Normal file
@ -0,0 +1,3 @@
|
||||
import cxdData from './cxd';
|
||||
import antdData from './antd';
|
||||
export {cxdData, antdData};
|
156
packages/amis-theme-editor-helper/src/util.ts
Normal 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;
|
||||
}
|
18
packages/amis-theme-editor-helper/tsconfig.json
Normal 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"}
|
||||
]
|
||||
}
|
5
packages/amis-theme-editor-helper/typings.ts
Normal file
@ -0,0 +1,5 @@
|
||||
declare module '*.json' {
|
||||
const value: any;
|
||||
export default value;
|
||||
}
|
||||
declare module 'plugin-react-i18n';
|
@ -109,6 +109,7 @@ export interface TooltipWrapperProps {
|
||||
*/
|
||||
onVisibleChange?: (visible: boolean) => void;
|
||||
children?: React.ReactNode | Array<React.ReactNode>;
|
||||
disabled?: boolean;
|
||||
}
|
||||
|
||||
interface TooltipWrapperState {
|
||||
|
93
publish-theme.sh
Normal 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
@ -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"
|
||||
}
|
||||
|
@ -29,7 +29,10 @@
|
||||
"amis": ["./packages/amis/src/index.tsx"],
|
||||
"office-viewer": ["./packages/office-viewer/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": {
|
||||
|
@ -14,25 +14,6 @@ import i18nConfig from './i18nConfig';
|
||||
|
||||
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/
|
||||
export default defineConfig({
|
||||
plugins: [
|
||||
@ -126,7 +107,14 @@ export default defineConfig({
|
||||
{
|
||||
find: 'office-viewer',
|
||||
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)
|
||||
]
|
||||
}
|
||||
});
|
||||
|