Skip to content

Commit 23ba36e

Browse files
authored
Merge pull request #1247 from lowcoder-org/theme_canvas_settings
Theme canvas settings
2 parents 1ff153e + dd50f07 commit 23ba36e

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

60 files changed

+1667
-506
lines changed

client/packages/lowcoder-design/src/components/colorSelect/colorUtils.ts

+40-12
Original file line numberDiff line numberDiff line change
@@ -4,18 +4,36 @@ import { generate } from "@ant-design/colors/es";
44

55
extend([namesPlugin]);
66

7+
export const gradientColors = [
8+
"linear-gradient(90deg, #1CB5E0 0%, #000851 100%)",
9+
"linear-gradient(90deg, #00C9FF 0%, #92FE9D 100%)",
10+
"linear-gradient(90deg, #FC466B 0%, #3F5EFB 100%)",
11+
"linear-gradient(90deg, #3F2B96 0%, #A8C0FF 100%)",
12+
"linear-gradient(90deg, #FDBB2D 0%, #22C1C3 100%)",
13+
"linear-gradient(90deg, #FDBB2D 0%, #3A1C71 100%)",
14+
"linear-gradient(90deg, #e3ffe7 0%, #d9e7ff 100%)",
15+
"linear-gradient(90deg, #4b6cb7 0%, #182848 100%)",
16+
"linear-gradient(90deg, #9ebd13 0%, #008552 100%)",
17+
"linear-gradient(90deg, #0700b8 0%, #00ff88 100%)",
18+
"linear-gradient(90deg, #d53369 0%, #daae51 100%)",
19+
"linear-gradient(90deg, #efd5ff 0%, #515ada 100%)",
20+
"linear-gradient(90deg, #00d2ff 0%, #3a47d5 100%)",
21+
"linear-gradient(90deg, #f8ff00 0%, #3ad59f 100%)",
22+
"linear-gradient(90deg, #fcff9e 0%, #c67700 100%)",
23+
];
24+
725
// Color Palette
826
export const constantColors = [
9-
{ id: 1, color: "#6D83F2" },
10-
{ id: 2, color: "#5589F2" },
11-
{ id: 3, color: "#36B389" },
12-
{ id: 4, color: "#E68E50" },
13-
{ id: 5, color: "#E67373" },
14-
{ id: 6, color: "#F5FFF7" },
15-
{ id: 7, color: "#F3FAFF" },
16-
{ id: 8, color: "#FFF6E6" },
17-
{ id: 9, color: "#F5F5F6" },
18-
{ id: 10, color: "#FFFFFF" },
27+
"#6D83F2",
28+
"#5589F2",
29+
"#36B389",
30+
"#E68E50",
31+
"#E67373",
32+
"#F5FFF7",
33+
"#F3FAFF",
34+
"#FFF6E6",
35+
"#F5F5F6",
36+
"#FFFFFF",
1937
];
2038

2139
export const chartColorPalette = [
@@ -40,7 +58,17 @@ const alphaOfRgba = (rgba: string) => {
4058
return colord(rgba).alpha().toString();
4159
};
4260

43-
const isValidColor = (str: string) => {
61+
const isValidGradient = (color?: string) => {
62+
if (!color) return false;
63+
64+
const linearGradientRegex = /^linear-gradient\((\d+deg|to\s+(top|right|bottom|left)(\s+(top|right|bottom|left))?)\s*,\s*((#[0-9a-fA-F]{3,6}|rgba?\(\d+,\s*\d+,\s*\d+(,\s*\d+(\.\d+)?)?\)|[a-zA-Z]+)(\s+\d+%?)?,?\s*)+\)$/i;
65+
const radialGradientRegex = /^radial-gradient\(\s*(circle|ellipse)?\s*,\s*((#[0-9a-fA-F]{3,6}|rgba?\(\d+,\s*\d+,\s*\d+(,\s*\d+(\.\d+)?)?\)|[a-zA-Z]+)(\s+\d+%?)?,?\s*)+\)$/i;
66+
67+
return linearGradientRegex.test(color) || radialGradientRegex.test(color);
68+
}
69+
70+
const isValidColor = (str?: string) => {
71+
if (!str) return false;
4472
return colord(str).isValid();
4573
};
4674

@@ -91,4 +119,4 @@ export const darkenColor = (colorStr: string, intensity: number) => {
91119
return color.darken(intensity).toHex().toUpperCase();
92120
};
93121

94-
export { toRGBA, toHex, alphaOfRgba, isValidColor };
122+
export { toRGBA, toHex, alphaOfRgba, isValidColor, isValidGradient };

client/packages/lowcoder-design/src/components/colorSelect/index.tsx

+60-30
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,17 @@
1-
import { RgbaStringColorPicker } from "react-colorful";
21
import { default as Popover } from "antd/es/popover";
2+
import ColorPicker, {useColorPicker} from 'react-best-gradient-color-picker';
33
import { ActionType } from '@rc-component/trigger/lib/interface';
44
import {
55
alphaOfRgba,
66
toRGBA,
77
toHex,
88
constantColors,
99
isValidColor,
10+
isValidGradient,
11+
gradientColors,
1012
} from "components/colorSelect/colorUtils";
1113
import styled, { css } from "styled-components";
12-
import { useCallback, useRef, useState } from "react";
14+
import { useCallback, useRef, useState, useEffect, useMemo, } from "react";
1315
import { throttle } from "lodash";
1416
import { changeValueAction } from "lowcoder-core";
1517

@@ -18,54 +20,65 @@ interface ColorSelectProps {
1820
trigger?: ActionType;
1921
dispatch?: (value: any) => void;
2022
changeColor?: (value: any) => void;
23+
presetColors?: string[];
24+
allowGradient?: boolean;
2125
}
2226

2327
export const ColorSelect = (props: ColorSelectProps) => {
2428
const { color, trigger = "click", dispatch, changeColor } = props;
25-
let pickerColor = useRef(toRGBA(color));
2629
const [visible, setVisible] = useState(false);
30+
const [ selectedColor, setSelectedColor ] = useState(color);
31+
const { getGradientObject } = useColorPicker(selectedColor, setSelectedColor);
32+
33+
const presetColors = useMemo(() => {
34+
let colors = props.presetColors || [];
35+
if (props.allowGradient) {
36+
colors = colors.concat(gradientColors.slice(0, 16 - colors.length));
37+
}
38+
return colors;
39+
}, [props.presetColors, selectedColor, props.allowGradient]);
40+
2741
const throttleChange = useCallback(
2842
throttle((rgbaColor: string) => {
29-
dispatch && dispatch(changeValueAction(toHex(rgbaColor), true));
30-
changeColor && changeColor(toHex(rgbaColor));
43+
dispatch && dispatch(changeValueAction(rgbaColor, true));
44+
changeColor && changeColor(rgbaColor);
3145
}, 200),
3246
[dispatch,changeColor]
3347
);
48+
49+
useEffect(() => {
50+
if (color !== selectedColor) {
51+
const value = getGradientObject();
52+
if (!value?.isGradient) {
53+
return throttleChange(toHex(selectedColor));
54+
}
55+
throttleChange(selectedColor);
56+
}
57+
}, [selectedColor])
58+
3459
return (
3560
<Popover
3661
trigger={trigger}
62+
placement="left"
3763
destroyTooltipOnHide={true}
3864
onOpenChange={(value) => {
39-
pickerColor.current = toRGBA(color);
4065
setVisible(value);
4166
}}
4267
content={
4368
<PopoverContainer>
44-
<div style={{ position: "relative" }}>
45-
<RgbaStringColorPicker color={pickerColor.current} onChange={throttleChange} />
46-
<AlphaDiv color={color?.substring(0, 7)}>
47-
<BackDiv $color={alphaOfRgba(toRGBA(color))}></BackDiv>
48-
</AlphaDiv>
49-
</div>
50-
<ConstantDiv>
51-
{constantColors.map((item) => {
52-
return (
53-
<ConstantBlock
54-
color={item.color}
55-
key={item.id}
56-
onClick={() => {
57-
throttleChange(item.color);
58-
pickerColor.current = toRGBA(item.color);
59-
}}
60-
/>
61-
);
62-
})}
63-
</ConstantDiv>
69+
<StyledColorPicker
70+
disableDarkMode
71+
value={color}
72+
onChange={setSelectedColor}
73+
width={250}
74+
height={160}
75+
presets={presetColors}
76+
$allowGradient={props.allowGradient}
77+
/>
6478
</PopoverContainer>
6579
}
6680
>
67-
<ColorBlock $color={color?.substring(0, 7)}>
68-
<BackDiv $color={alphaOfRgba(toRGBA(color))}></BackDiv>
81+
<ColorBlock $color={color}>
6982
</ColorBlock>
7083
</Popover>
7184
);
@@ -139,7 +152,6 @@ const PopoverContainer = styled.div`
139152
display: flex;
140153
flex-direction: column;
141154
gap: 12px;
142-
padding: 16px;
143155
`;
144156
// contrast block
145157
const AlphaDiv = styled.div.attrs((props) => ({
@@ -169,12 +181,30 @@ const BackDiv = styled.div.attrs<{ $color: string }>((props: { $color: string })
169181
`;
170182
// main block
171183
const ColorBlock = styled.div<{ $color: string }>`
172-
background-color: ${(props) => (isValidColor(props.$color) ? props.$color : "#FFFFFF")};
184+
background: ${(props) => (
185+
isValidColor(props.$color) || isValidGradient(props.$color)
186+
? props.$color
187+
: "#FFFFFF"
188+
)};
173189
border: 1px solid rgba(0, 0, 0, 0.1);
174190
border-radius: 4px;
175191
height: 24px;
176192
width: 24px;
177193
cursor: pointer;
178194
background-clip: content-box;
179195
overflow: hidden;
196+
`;
197+
198+
const StyledColorPicker = styled(ColorPicker)<{$allowGradient?: boolean}>`
199+
#rbgcp-wrapper > div:nth-child(2) > div:first-child > div:first-child {
200+
${props => !props.$allowGradient && `visibility: hidden`};
201+
}
202+
#rbgcp-wrapper > div:last-child > div:last-child {
203+
justify-content: flex-start !important;
204+
gap: 3px;
205+
206+
> div {
207+
border: 1px solid lightgray;
208+
}
209+
}
180210
`;

client/packages/lowcoder-design/src/icons/index.tsx

+2
Original file line numberDiff line numberDiff line change
@@ -172,6 +172,8 @@ export { ReactComponent as LeftSettingIcon } from "./remix/tools-fill.svg";
172172
export { ReactComponent as LeftLayersIcon } from "./remix/stack-line.svg";
173173
export { ReactComponent as LeftHelpIcon } from "./v1/icon-left-help.svg";
174174
export { ReactComponent as LeftPreloadIcon } from "./v1/icon-left-preload.svg";
175+
export { ReactComponent as LeftColorPaletteIcon } from "./remix/palette-line.svg";
176+
export { ReactComponent as LeftJSSettingIcon } from "./remix/javascript-line.svg";
175177

176178

177179
export { ReactComponent as HomeSettingsIcon } from "./v1/icon-home-settings.svg";

client/packages/lowcoder/package.json

+1
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,7 @@
6464
"qrcode.react": "^3.1.0",
6565
"rc-trigger": "^5.3.1",
6666
"react": "^18.2.0",
67+
"react-best-gradient-color-picker": "^3.0.10",
6768
"react-colorful": "^5.5.1",
6869
"react-documents": "^1.2.1",
6970
"react-dom": "^18.2.0",

client/packages/lowcoder/src/api/commonSettingApi.ts

+10-1
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,16 @@ export interface ThemeDetail {
5353
chart?: string;
5454
margin?: string;
5555
padding?: string;
56-
gridColumns?: string; //Added By Aqib Mirza
56+
gridPaddingX?: number;
57+
gridPaddingY?: number;
58+
gridColumns?: string;
59+
gridRowHeight?: string;
60+
gridRowCount?: number;
61+
gridBgImage?: string;
62+
gridBgImageRepeat?: string;
63+
gridBgImageSize?: string;
64+
gridBgImagePosition?: string;
65+
gridBgImageOrigin?: string;
5766
text?: string;
5867
textSize?: string;
5968
fontFamily?: string;

0 commit comments

Comments
 (0)