Skip to content

Commit

Permalink
work for #6349
Browse files Browse the repository at this point in the history
  • Loading branch information
OlgaLarina committed Dec 30, 2024
1 parent 33b4ead commit b472c45
Show file tree
Hide file tree
Showing 6 changed files with 104 additions and 131 deletions.
26 changes: 13 additions & 13 deletions packages/survey-creator-core/src/components/tabs/theme-model.ts
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,7 @@ export class ThemeModel extends Base implements ITheme {
public undoRedoManager: UndoRedoManager;
private themeCssVariablesChanges: { [index: string]: string } = {};
private colorCalculator = new ColorCalculator();
private dependentColorNames = ["--sjs-primary-backcolor-light", "--sjs-primary-backcolor-dark"];

@property() backgroundImage: string;
@property() backgroundImageFit: "auto" | "contain" | "cover";
Expand Down Expand Up @@ -198,25 +199,24 @@ export class ThemeModel extends Base implements ITheme {
}

private initializeColorCalculator(cssVariables: { [index: string]: string }) {
if (!cssVariables["--sjs-primary-backcolor"] ||
!cssVariables["--sjs-primary-backcolor-light"] ||
!cssVariables["--sjs-primary-backcolor-dark"]) {
const baseColorName = "--sjs-primary-backcolor";
const cssValuesExists = this.dependentColorNames.every(name => !!cssVariables[name]);
if (!cssVariables[baseColorName] || !cssValuesExists) {
return;
}

this.colorCalculator.initialize(
cssVariables["--sjs-primary-backcolor"],
cssVariables["--sjs-primary-backcolor-light"],
cssVariables["--sjs-primary-backcolor-dark"]
);
const dependentColorValues = this.dependentColorNames.map(name => { return cssVariables[name]; });
this.colorCalculator.initializeColorSettings(cssVariables[baseColorName], dependentColorValues);
}

private updatePropertiesDependentOnPrimaryColor(value: string) {
this.colorCalculator.calculateColors(value);
this.setPropertyValue("--sjs-primary-backcolor-light", this.colorCalculator.colorSettings.newColorLight);
this.setPropertyValue("--sjs-primary-backcolor-dark", this.colorCalculator.colorSettings.newColorDark);
this.setThemeCssVariablesChanges("--sjs-primary-backcolor-light", this.colorCalculator.colorSettings.newColorLight);
this.setThemeCssVariablesChanges("--sjs-primary-backcolor-dark", this.colorCalculator.colorSettings.newColorDark);
if (!this.colorCalculator.isInitialized) return;

const newDependentColors = this.colorCalculator.calculateDependentColorValues(value);
this.dependentColorNames.forEach((name, index) => {
this.setPropertyValue(name, newDependentColors[index]);
this.setThemeCssVariablesChanges(name, newDependentColors[index]);
});
}
private cssVariablePropertiesChanged(name: string, value: any, property: JsonObjectProperty) {
let nameProcessed = true;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ export class CreatorThemeModel extends Base implements ICreatorTheme {

private initializeColorCalculators(cssVariables: { [index: string]: string }) {
this.initializeColorCalculator(this.primaryColorCalculator, cssVariables, "--sjs-primary-background-500", "--sjs-primary-background-10", "--sjs-primary-background-400");
this.initializeColorCalculator(this.secondaryColorCalculator, cssVariables, "--sjs-secondary-background-500", "--sjs-secondary-background-10", "--sjs-secondary-background-25");
this.initializeColorCalculator(this.secondaryColorCalculator, cssVariables, "--sjs-secondary-background-500", "--sjs-secondary-background-10", "--sjs-secondary-background-25", "--sjs-secondary-background-400");

if (!!cssVariables["--sjs-special-haze"]) {
this.specialHazeColorCalculator.initialize(cssVariables["--sjs-special-haze"]);
Expand All @@ -52,39 +52,41 @@ export class CreatorThemeModel extends Base implements ICreatorTheme {
this.specialGlowColorCalculator.initialize(cssVariables["--sjs-special-glow"]);
}
}
private initializeColorCalculator(calculator: ColorCalculator, cssVariables: { [index: string]: string }, baseColorName: string, lightColorName: string, darkColorName: string) {
if (!cssVariables[baseColorName] ||
!cssVariables[lightColorName] ||
!cssVariables[darkColorName]) {
private initializeColorCalculator(calculator: ColorCalculator, cssVariables: { [index: string]: string }, baseColorName: string, ...dependentColorNames: Array<string>) {
const cssValuesExist = dependentColorNames.every(name => !!cssVariables[name]);
if (!cssVariables[baseColorName] || !cssValuesExist) {
return;
}

calculator.initialize(
cssVariables[baseColorName],
cssVariables[lightColorName],
cssVariables[darkColorName]
);
const dependentColorValues = dependentColorNames.map(name => { return cssVariables[name]; });
calculator.initializeColorSettings(cssVariables[baseColorName], dependentColorValues);
}

private updateColorPropertiesDependentOnBaseColor(calculator: ColorCalculator, value: string, baseColorName: string, lightColorName: string, darkColorName: string) {
private updateColorPropertiesDependentOnBaseColor(calculator: ColorCalculator, value: string, baseColorName: string, ...dependentColorNames: Array<string>) {
this.setPropertyValue(baseColorName, value);
this.setThemeCssVariablesChanges(baseColorName, value);
calculator.calculateColors(value);
this.setPropertyValue(lightColorName, calculator.colorSettings.newColorLight);
this.setPropertyValue(darkColorName, calculator.colorSettings.newColorDark);
this.setThemeCssVariablesChanges(lightColorName, calculator.colorSettings.newColorLight);
this.setThemeCssVariablesChanges(darkColorName, calculator.colorSettings.newColorDark);

if (!calculator.isInitialized) return;
const newDependentColorsValues = calculator.calculateDependentColorValues(value);
dependentColorNames.forEach((name, index) => {
this.setPropertyValue(name, newDependentColorsValues[index]);
this.setThemeCssVariablesChanges(name, newDependentColorsValues[index]);
});
}
private updateHueColorPropertiesDependentOnBackgroundColor(value: string, baseColorName: string, hazeColorName: string, glowColorName: string) {
this.setPropertyValue(baseColorName, value);
this.setThemeCssVariablesChanges(baseColorName, value);

const newSpecialHazeColor = this.specialHazeColorCalculator.calculateNewColor(value);
const newSpecialGlowColor = this.specialGlowColorCalculator.calculateNewColor(value);
this.setPropertyValue(hazeColorName, newSpecialHazeColor);
this.setPropertyValue(glowColorName, newSpecialGlowColor);
this.setThemeCssVariablesChanges(hazeColorName, newSpecialHazeColor);
this.setThemeCssVariablesChanges(glowColorName, newSpecialGlowColor);
if (this.specialHazeColorCalculator.isInitialized) {
const newSpecialHazeColor = this.specialHazeColorCalculator.calculateDependentColorValue(value);
this.setPropertyValue(hazeColorName, newSpecialHazeColor);
this.setThemeCssVariablesChanges(hazeColorName, newSpecialHazeColor);
}
if (this.specialGlowColorCalculator.isInitialized) {
const newSpecialGlowColor = this.specialGlowColorCalculator.calculateDependentColorValue(value);
this.setPropertyValue(glowColorName, newSpecialGlowColor);
this.setThemeCssVariablesChanges(glowColorName, newSpecialGlowColor);
}
}
private isSpecialBackgroundFromCurrentTheme() {
const currentTheme = CreatorThemes[this.themeName];
Expand Down Expand Up @@ -168,7 +170,7 @@ export class CreatorThemeModel extends Base implements ICreatorTheme {
this.updateColorPropertiesDependentOnBaseColor(this.primaryColorCalculator, newValue, "--sjs-primary-background-500", "--sjs-primary-background-10", "--sjs-primary-background-400");
this.updateBackgroundColor(newValue, oldValue);
} else if (name === "--sjs-secondary-background-500") {
this.updateColorPropertiesDependentOnBaseColor(this.secondaryColorCalculator, newValue, "--sjs-secondary-background-500", "--sjs-secondary-background-10", "--sjs-secondary-background-25");
this.updateColorPropertiesDependentOnBaseColor(this.secondaryColorCalculator, newValue, "--sjs-secondary-background-500", "--sjs-secondary-background-10", "--sjs-secondary-background-25", "--sjs-secondary-background-400");
} else if (name === "--sjs-special-background") {
this.updateHueColorPropertiesDependentOnBackgroundColor(newValue, "--sjs-special-background", "--sjs-special-haze", "--sjs-special-glow");
} else if (name.indexOf("--") === 0) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,13 @@ export const PredefinedCreatorThemes: string[] = ["sc2020"];
const sc2020CssVariables = {};
assign(sc2020CssVariables, designTabSurveyThemeJSON.cssVariables, {
"--sjs-special-background": "#F3F3F3FF",
"--sjs-special-glow": "#0000001a",
"--sjs-special-haze": "#90909080",
"--sjs-primary-background-500": "#19B394FF",
"--sjs-primary-background-10": "#19B3941A",
"--sjs-primary-background-400": "#14A48BFF",
"--sjs-secondary-background-500": "#FF9814FF",
"--sjs-secondary-background-400": "#F78A00",
"--sjs-secondary-background-25": "#FF981440",
"--sjs-secondary-background-10": "#FF98141A",
"--ctr-surface-background-color": "var(--sjs-special-background)",
Expand Down
74 changes: 28 additions & 46 deletions packages/survey-creator-core/src/utils/color-utils.ts
Original file line number Diff line number Diff line change
@@ -1,67 +1,49 @@
import { roundTo2Decimals } from "./utils";

export class ColorCalculator {
colorSetting = { colorAlpha: 1, deltaColor: 0 };
colorSettings = { baseColorAlpha: 1, darkColorAlpha: 1, lightColorAlpha: 1, deltaDarkColor: 0, deltaLightColor: 0, newColorLight: "", newColorDark: "" };
colorSettings: Array<{ colorAlpha: number, colorDelta: number }> = [];
isInitialized = false;

initialize(baseColor: string, lightColor: string, darkColor: string) {
const primaryColorRgba = getRGBaChannelValues(baseColor);
const primaryColorDarkRgba = getRGBaChannelValues(darkColor);
const primaryColorLightRgba = getRGBaChannelValues(lightColor);

this.colorSettings.baseColorAlpha = primaryColorRgba[3];
this.colorSettings.darkColorAlpha = primaryColorDarkRgba[3];
this.colorSettings.lightColorAlpha = primaryColorLightRgba[3];

const primaryColorHSB = RGBToHSB(primaryColorRgba[0], primaryColorRgba[1], primaryColorRgba[2]);
const primaryColorDarkHSB = RGBToHSB(primaryColorDarkRgba[0], primaryColorDarkRgba[1], primaryColorDarkRgba[2]);
const primaryColorLightHSB = RGBToHSB(primaryColorLightRgba[0], primaryColorLightRgba[1], primaryColorLightRgba[2]);

this.colorSettings.deltaDarkColor = primaryColorHSB[2] - primaryColorDarkHSB[2];
this.colorSettings.deltaLightColor = primaryColorHSB[2] - primaryColorLightHSB[2];
}

calculateColors(newColor: string) {
const newColorRbg = getRGBaChannelValues(newColor);
const newColorHsb = RGBToHSB(newColorRbg[0], newColorRbg[1], newColorRbg[2]);
const newPrimaryColorDarkRGB = HSBToRGB(newColorHsb[0], newColorHsb[1], newColorHsb[2] - this.colorSettings.deltaDarkColor);
const newPrimaryColorLightRGB = HSBToRGB(newColorHsb[0], newColorHsb[1], newColorHsb[2] - this.colorSettings.deltaLightColor);

this.colorSettings.newColorLight = convertRgbaToString(newPrimaryColorLightRGB, this.colorSettings.lightColorAlpha);
this.colorSettings.newColorDark = convertRgbaToString(newPrimaryColorDarkRGB, this.colorSettings.darkColorAlpha);
}

initializeColorSetting(baseColor: string, dependentСolor: string) {
initializeColorSettings(baseColor: string, dependentСolorValues: Array<string>) {
const baseColorRgba = getRGBaChannelValues(baseColor);
const dependentСolorRgba = getRGBaChannelValues(dependentСolor);
this.colorSetting.colorAlpha = dependentСolorRgba[3];

const baseColorHSB = RGBToHSB(baseColorRgba[0], baseColorRgba[1], baseColorRgba[2]);
const colorHSB = RGBToHSB(dependentСolorRgba[0], dependentСolorRgba[1], dependentСolorRgba[2]);

this.colorSetting.deltaColor = baseColorHSB[2] - colorHSB[2];
dependentСolorValues.forEach((dependentСolor: string) => {
const dependentСolorRgba = getRGBaChannelValues(dependentСolor);
const colorAlpha = dependentСolorRgba[3];

const baseColorHSB = RGBToHSB(baseColorRgba[0], baseColorRgba[1], baseColorRgba[2]);
const colorHSB = RGBToHSB(dependentСolorRgba[0], dependentСolorRgba[1], dependentСolorRgba[2]);
const colorDelta = baseColorHSB[2] - colorHSB[2];
this.colorSettings.push({ colorAlpha, colorDelta });
});
this.isInitialized = !!this.colorSettings.length;
}

calculateNewColor(newColor: string): string {
let newColorRbg = getRGBaChannelValues(newColor);
const newColorHsb = RGBToHSB(newColorRbg[0], newColorRbg[1], newColorRbg[2]);
const newColorLightRGB = HSBToRGB(newColorHsb[0], newColorHsb[1], newColorHsb[2] - this.colorSetting.deltaColor);
const resultColor = convertRgbaToString(newColorLightRGB, this.colorSetting.colorAlpha);
return resultColor;
calculateDependentColorValues(newBaseColor: string): Array<string> {
let newBaseColorRbg = getRGBaChannelValues(newBaseColor);
const newBaseColorHsb = RGBToHSB(newBaseColorRbg[0], newBaseColorRbg[1], newBaseColorRbg[2]);
const result = this.colorSettings.map(setting => {
const newColorLightRGB = HSBToRGB(newBaseColorHsb[0], newBaseColorHsb[1], newBaseColorHsb[2] - setting.colorDelta);
return convertRgbaToString(newColorLightRGB, setting.colorAlpha);
});
return result;
}
}

export class HueColorCalculator {
colorHsb: Array<number>;
colorAlpha: number;
isInitialized = false;

initialize(baseColor: string): void {
const colorRbg = getRGBaChannelValues(baseColor);
this.colorHsb = RGBToHSB(colorRbg[0], colorRbg[1], colorRbg[2]);
this.colorAlpha = colorRbg[3];
this.isInitialized = !!colorRbg.length;
if (this.isInitialized) {
this.colorHsb = RGBToHSB(colorRbg[0], colorRbg[1], colorRbg[2]);
this.colorAlpha = colorRbg[3];
}
}

calculateNewColor(baseColor: string): string {
calculateDependentColorValue(baseColor: string): string {
const baseColorRbg = getRGBaChannelValues(baseColor);
const baseColorHsb = RGBToHSB(baseColorRbg[0], baseColorRbg[1], baseColorRbg[2]);
const newColorRGB = HSBToRGB(baseColorHsb[0], this.colorHsb[1], this.colorHsb[2]);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,7 @@ test("Creator theme: reset color variables after change theme", (): any => {
"--sjs-primary-background-10": "#3EDFD51A",
"--sjs-primary-background-400": "#29DCD1FF",
"--sjs-secondary-background-500": "#EDA925FF",
"--sjs-secondary-background-400": "#EDBE1E",
"--sjs-secondary-background-25": "#EDA92540",
"--sjs-secondary-background-10": "#EDA9251A",
}
Expand Down Expand Up @@ -111,10 +112,11 @@ test("Creator theme: reset color variables after change theme", (): any => {
"--sjs-primary-background-500": "#141414",
"--sjs-secondary-background-10": "rgba(30, 30, 30, 0.1)",
"--sjs-secondary-background-25": "rgba(30, 30, 30, 0.25)",
"--sjs-secondary-background-400": "rgba(22, 22, 22, 1)",
"--sjs-secondary-background-500": "#1e1e1e",
"--sjs-special-background": "#0a0a0a",
"--sjs-special-glow": "rgba(10, 10, 10, 1)",
"--sjs-special-haze": "rgba(10, 10, 10, 1)",
"--sjs-special-glow": "rgba(0, 0, 0, 0.1)",
"--sjs-special-haze": "rgba(144, 144, 144, 0.5)",
});

themeName.value = "dark";
Expand Down Expand Up @@ -216,13 +218,14 @@ test("Update --sjs-primary-background-10 && --sjs-primary-background-400", (): a
});
});

test("Update --sjs-secondary-background-25 && --sjs-secondary-background-10", (): any => {
test("Update --sjs-secondary-background-500 dependent properties", (): any => {
const fefefeColor = "#fefefe"; // rgba(254, 254, 254, 1)
const themeModel = new CreatorThemeModel();
themeModel.loadTheme({
themeName: "custom",
cssVariables: {
"--sjs-secondary-background-500": "#FF9814FF",
"--sjs-secondary-background-400": "#F78A00",
"--sjs-secondary-background-25": "#FF981440",
"--sjs-secondary-background-10": "#FF98141A",
}
Expand All @@ -236,6 +239,7 @@ test("Update --sjs-secondary-background-25 && --sjs-secondary-background-10", ()
themeModel["--sjs-secondary-background-500"] = fefefeColor;
expect(themeModel.themeCssVariablesChanges).toStrictEqual({
"--sjs-secondary-background-500": fefefeColor,
"--sjs-secondary-background-400": "rgba(246, 246, 246, 1)",
"--sjs-secondary-background-25": "rgba(254, 254, 254, 0.25)",
"--sjs-secondary-background-10": "rgba(254, 254, 254, 0.1)",
});
Expand All @@ -261,8 +265,8 @@ test("Update --sjs-special-haze && --sjs-special-glow", (): any => {
themeModel["--sjs-special-background"] = fefefeColor;
expect(themeModel.themeCssVariablesChanges).toStrictEqual({
"--sjs-special-background": fefefeColor,
"--sjs-special-haze": "rgba(243, 243, 243, 0.35)",
"--sjs-special-glow": "rgba(81, 81, 81, 0.1)",
"--sjs-special-haze": "rgba(238, 204, 204, 0.35)",
"--sjs-special-glow": "rgba(76, 0, 0, 0.1)",
});
});

Expand Down
70 changes: 26 additions & 44 deletions packages/survey-creator-core/tests/utils.tests.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,29 +33,19 @@ test("ColorCalculator rgba", (): any => {
const primaryColorDark = "rgba(20, 164, 139, 1)";
const colorCalculator = new ColorCalculator();

colorCalculator.initialize(primaryColor, primaryColorLight, primaryColorDark);
expect(colorCalculator.colorSettings).toEqual({
baseColorAlpha: 1,
darkColorAlpha: 1,
lightColorAlpha: 0.1,
deltaDarkColor: 5.882352941176464,
deltaLightColor: 0,
newColorDark: "",
newColorLight: ""
}
colorCalculator.initializeColorSettings(primaryColor, [primaryColorLight, primaryColorDark]);
expect(colorCalculator.colorSettings).toStrictEqual([
{
colorAlpha: 0.1,
colorDelta: 0,
}, {
colorAlpha: 1,
colorDelta: 5.882352941176464,
}]
);

colorCalculator.calculateColors(primaryColor);
expect(colorCalculator.colorSettings).toEqual({
baseColorAlpha: 1,
darkColorAlpha: 1,
lightColorAlpha: 0.1,
deltaDarkColor: 5.882352941176464,
deltaLightColor: 0,
newColorDark: "rgba(23, 164, 136, 1)",
newColorLight: "rgba(25, 179, 148, 0.1)"
}
);
const newDependentColors = colorCalculator.calculateDependentColorValues(primaryColor);
expect(newDependentColors).toStrictEqual(["rgba(25, 179, 148, 0.1)", "rgba(23, 164, 136, 1)"]);
});

test("ColorCalculator hex", (): any => {
Expand All @@ -64,36 +54,28 @@ test("ColorCalculator hex", (): any => {
const primaryColorDark = "#14A48BFF";
const colorCalculator = new ColorCalculator();

colorCalculator.initialize(primaryColor, primaryColorLight, primaryColorDark);
expect(colorCalculator.colorSettings).toEqual({
baseColorAlpha: 1,
darkColorAlpha: 1,
lightColorAlpha: 0.1,
deltaDarkColor: 5.882352941176464,
deltaLightColor: 0,
newColorDark: "",
newColorLight: ""
});
colorCalculator.initializeColorSettings(primaryColor, [primaryColorLight, primaryColorDark]);
expect(colorCalculator.colorSettings).toStrictEqual([
{
colorAlpha: 0.1,
colorDelta: 0,
}, {
colorAlpha: 1,
colorDelta: 5.882352941176464,
}
]);

colorCalculator.calculateColors(primaryColor);
expect(colorCalculator.colorSettings).toEqual({
baseColorAlpha: 1,
darkColorAlpha: 1,
lightColorAlpha: 0.1,
deltaDarkColor: 5.882352941176464,
deltaLightColor: 0,
newColorDark: "rgba(23, 164, 136, 1)",
newColorLight: "rgba(25, 179, 148, 0.1)"
});
const newDependentColors = colorCalculator.calculateDependentColorValues(primaryColor);
expect(newDependentColors).toStrictEqual(["rgba(25, 179, 148, 0.1)", "rgba(23, 164, 136, 1)"]);
});

test("HueColorCalculator hex", (): any => {
const glowColor = "#004C441A"; // HSB 174, 100, 30
const glowColor = "#004C441A";
const tealColor = "#EFF9F9";
const purpleColor = "#F8F4FE";
const colorCalculator = new HueColorCalculator();

colorCalculator.initialize(glowColor);
expect(colorCalculator.calculateNewColor(purpleColor)).toEqual("rgba(30, 0, 76, 0.1)");
expect(colorCalculator.calculateNewColor(tealColor)).toEqual("rgba(0, 76, 76, 0.1)");
expect(colorCalculator.calculateDependentColorValue(purpleColor)).toEqual("rgba(30, 0, 76, 0.1)");
expect(colorCalculator.calculateDependentColorValue(tealColor)).toEqual("rgba(0, 76, 76, 0.1)");
});

0 comments on commit b472c45

Please sign in to comment.