diff --git a/packages/survey-creator-core/src/components/tabs/theme-custom-questions/shadow-effects.ts b/packages/survey-creator-core/src/components/tabs/theme-custom-questions/shadow-effects.ts index 283333dba..6b877ec83 100644 --- a/packages/survey-creator-core/src/components/tabs/theme-custom-questions/shadow-effects.ts +++ b/packages/survey-creator-core/src/components/tabs/theme-custom-questions/shadow-effects.ts @@ -68,7 +68,14 @@ if (!ComponentCollection.Instance.getCustomQuestionByName("shadoweffects")) { if (typeof value == "undefined") return [{}]; return typeof value == "string" ? parseBoxShadow(value) : value; }; - question.valueToDataCallback = (value: string | Array): string => !!value ? (typeof value == "string" ? value : createBoxShadow(Array.isArray(value) ? value : [value])) : ""; + question.valueToDataCallback = (value: string | Array): string => { + if (!value) return ""; + if (typeof value == "string") { + return value; + } else { + return createBoxShadow(Array.isArray(value) ? value : [value]); + } + }; (question.contentQuestion).panels.forEach(p => p.questions.forEach(q => q.allowRootStyle = false)); }, }); @@ -120,4 +127,9 @@ export function parseBoxShadow(value: string = ""): Array { res["isInset"] = isInset; return res; }); +} + +export function trimBoxShadowValue(value: string): string { + if (!value) return value; + return value.replace(/\)\,\s/g, "),"); } \ No newline at end of file diff --git a/packages/survey-creator-core/src/components/tabs/theme-model.ts b/packages/survey-creator-core/src/components/tabs/theme-model.ts index abd4755da..3bd518b51 100644 --- a/packages/survey-creator-core/src/components/tabs/theme-model.ts +++ b/packages/survey-creator-core/src/components/tabs/theme-model.ts @@ -5,7 +5,7 @@ import { settings } from "../../creator-settings"; import { DefaultFonts, fontsettingsFromCssVariable, fontsettingsToCssVariable } from "./theme-custom-questions/font-settings"; import { backgroundCornerRadiusFromCssVariable, backgroundCornerRadiusToCssVariable } from "./theme-custom-questions/background-corner-radius"; -import { createBoxShadowReset } from "./theme-custom-questions/shadow-effects"; +import { createBoxShadowReset, trimBoxShadowValue } from "./theme-custom-questions/shadow-effects"; import { HeaderModel } from "./header-model"; import * as LibraryThemes from "survey-core/themes"; import { ColorCalculator, assign, ingectAlpha, parseColor, roundTo2Decimals } from "../../utils/utils"; @@ -777,6 +777,9 @@ Serializer.addProperties("theme", }, { type: "shadoweffects", name: "--sjs-shadow-small", + onSetValue: function (obj: any, value: any) { + obj.setPropertyValue("--sjs-shadow-small", trimBoxShadowValue(value)); + }, }, { type: "font", name: "questionTitle", @@ -797,6 +800,9 @@ Serializer.addProperties("theme", { type: "shadoweffects", name: "--sjs-shadow-inner", + onSetValue: function (obj: any, value: any) { + obj.setPropertyValue("--sjs-shadow-inner", trimBoxShadowValue(value)); + }, }, { type: "font", name: "editorFont", @@ -842,10 +848,34 @@ Serializer.addProperties("theme", { name: "--sjs-secondary-backcolor-semi-light", visible: false }, { name: "--sjs-secondary-forecolor", visible: false }, { name: "--sjs-secondary-forecolor-light", visible: false }, - { name: "--sjs-shadow-small-reset", visible: false }, - { name: "--sjs-shadow-medium", visible: false }, - { name: "--sjs-shadow-large", visible: false }, - { name: "--sjs-shadow-inner-reset", visible: false }, + { + name: "--sjs-shadow-small-reset", + visible: false, + onSetValue: function (obj: any, value: any) { + obj.setPropertyValue("--sjs-shadow-small-reset", trimBoxShadowValue(value)); + }, + }, + { + name: "--sjs-shadow-medium", + visible: false, + onSetValue: function (obj: any, value: any) { + obj.setPropertyValue("--sjs-shadow-medium", trimBoxShadowValue(value)); + }, + }, + { + name: "--sjs-shadow-large", + visible: false, + onSetValue: function (obj: any, value: any) { + obj.setPropertyValue("--sjs-shadow-large", trimBoxShadowValue(value)); + }, + }, + { + name: "--sjs-shadow-inner-reset", + visible: false, + onSetValue: function (obj: any, value: any) { + obj.setPropertyValue("--sjs-shadow-inner-reset", trimBoxShadowValue(value)); + }, + }, { name: "--sjs-border-light", visible: false }, { name: "--sjs-border-default", visible: false }, { name: "--sjs-border-inside", visible: false }, diff --git a/packages/survey-creator-core/tests/tabs/theme-tab-plugin.tests.ts b/packages/survey-creator-core/tests/tabs/theme-tab-plugin.tests.ts index ce90e8535..1ebba168a 100644 --- a/packages/survey-creator-core/tests/tabs/theme-tab-plugin.tests.ts +++ b/packages/survey-creator-core/tests/tabs/theme-tab-plugin.tests.ts @@ -1265,6 +1265,94 @@ test("Theme builder switch themes with reset of previous values", (): any => { expect(themeModel.cssVariables["--sjs-shadow-inner-reset"]).toEqual("inset 0px 0px 0px 0px rgba(0, 0, 0, 0.15)"); }); +test("Theme builder switch custom theme", (): any => { + const customTheme = { + "isPanelless": true, + "cssVariables": { + "--sjs-general-backcolor": "rgba(246, 248, 250, 1)", + "--sjs-general-backcolor-dark": "rgba(248, 248, 248, 1)", + "--sjs-general-backcolor-dim": "rgba(255, 255, 255, 1)", + "--sjs-general-backcolor-dim-light": "rgba(246, 248, 250, 1)", + "--sjs-general-backcolor-dim-dark": "rgba(243, 243, 243, 1)", + "--sjs-general-forecolor": "rgba(0, 0, 0, 0.91)", + "--sjs-general-forecolor-light": "rgba(0, 0, 0, 0.45)", + "--sjs-general-dim-forecolor": "rgba(0, 0, 0, 0.91)", + "--sjs-general-dim-forecolor-light": "rgba(0, 0, 0, 0.45)", + "--sjs-primary-backcolor": "rgba(9, 105, 218, 1)", + "--sjs-primary-backcolor-light": "rgba(9, 105, 218, 0.1)", + "--sjs-primary-backcolor-dark": "rgba(8, 98, 203, 1)", + "--sjs-primary-forecolor": "rgba(255, 255, 255, 1)", + "--sjs-primary-forecolor-light": "rgba(255, 255, 255, 0.25)", + "--sjs-base-unit": "6px", + "--sjs-corner-radius": "4px", + "--sjs-secondary-backcolor": "rgba(255, 152, 20, 1)", + "--sjs-secondary-backcolor-light": "rgba(255, 152, 20, 0.1)", + "--sjs-secondary-backcolor-semi-light": "rgba(255, 152, 20, 0.25)", + "--sjs-secondary-forecolor": "rgba(255, 255, 255, 1)", + "--sjs-secondary-forecolor-light": "rgba(255, 255, 255, 0.25)", + "--sjs-shadow-small": "0px 0px 0px 1px rgba(101, 109, 118, 0.25), 0px 2px 0px 0px rgba(101, 109, 118, 0.05), inset 0px 1px 0px 0px rgba(255, 255, 255, 0.5)", + "--sjs-shadow-small-reset": "0px 0px 0px 0px rgba(0, 0, 0, 0.15)", + "--sjs-shadow-medium": "0px 2px 6px 0px rgba(0, 0, 0, 0.1)", + "--sjs-shadow-large": "0px 8px 16px 0px rgba(0, 0, 0, 0.1)", + "--sjs-shadow-inner": "inset 0px 0px 0px 1px rgba(101, 109, 118, 0.25), inset 0px 2px 0px 0px rgba(101, 109, 118, 0.05)", + "--sjs-shadow-inner-reset": "inset 0px 0px 0px 0px rgba(0, 0, 0, 0.15)", + "--sjs-border-light": "rgba(216, 222, 228, 1)", + "--sjs-border-default": "rgba(216, 222, 228, 1)", + "--sjs-border-inside": "rgba(0, 0, 0, 0.16)", + "--sjs-font-pagetitle-color": "rgba(31, 35, 40, 1)", + "--sjs-font-pagedescription-color": "rgba(101, 109, 118, 1)", + "--sjs-question-background": "rgba(246, 248, 250, 1)", + "--sjs-questionpanel-backcolor": "rgba(246, 248, 250, 1)", + "--sjs-questionpanel-hovercolor": "rgba(243, 244, 246, 1)", + "--sjs-questionpanel-cornerRadius": "6px", + "--sjs-font-questiondescription-color": "rgba(101, 109, 118, 1)", + "--sjs-editor-background": "rgba(246, 248, 250, 1)", + "--sjs-editorpanel-backcolor": "rgba(246, 248, 250, 1)", + "--sjs-editorpanel-hovercolor": "rgba(243, 244, 246, 1)", + "--sjs-editorpanel-cornerRadius": "6px", + "--sjs-font-editorfont-color": "rgba(33, 37, 42, 1)", + "--sjs-font-editorfont-placeholdercolor": "rgba(110, 119, 129, 1)", + "--sjs-font-pagetitle-weight": "600", + "--sjs-font-pagetitle-family": "Arial, sans-serif", + "--sjs-font-family": "Open Sans", + "--sjs-font-pagedescription-family": "Arial, sans-serif", + "--sjs-font-questiontitle-family": "Arial, sans-serif", + "--sjs-font-questiontitle-color": "rgba(31, 35, 40, 1)", + "--sjs-font-questiontitle-size": "14px", + "--sjs-font-pagetitle-size": "22px", + "--sjs-font-pagedescription-size": "13px", + "--sjs-font-questiondescription-family": "Arial, sans-serif", + "--sjs-font-questiondescription-size": "13px", + "--sjs-font-editorfont-size": "14px", + "--sjs-font-editorfont-family": "Arial, sans-serif", + "--sjs-font-headertitle-color": "rgba(255, 255, 255, 1)", + "--sjs-font-headerdescription-color": "rgba(255, 255, 255, 1)" + }, + "themeName": "custom", + "colorPalette": "light", + }; + const creator: CreatorTester = new CreatorTester({ showThemeTab: true }); + + const themePlugin: ThemeTabPlugin = creator.getPlugin("theme"); + themePlugin.addTheme(customTheme); + themePlugin.activate(); + const themeModel = themePlugin.themeModel as ThemeModel; + const propertyGridSurvey = themePlugin.propertyGrid.survey; + const themeChooser = propertyGridSurvey.getQuestionByName("themeName") as QuestionDropdownModel; + + expect(themeChooser.value).toEqual("default"); + expect(themeModel.cssVariables["--sjs-shadow-inner"]).toEqual("inset 0px 1px 2px 0px rgba(0, 0, 0, 0.15)"); + expect(themeModel.cssVariables["--sjs-shadow-small"]).toEqual("0px 1px 2px 0px rgba(0, 0, 0, 0.15)"); + + themeChooser.value = "custom"; + expect(themeModel.cssVariables["--sjs-shadow-inner"]).toEqual("inset 0px 0px 0px 1px rgba(101, 109, 118, 0.25),inset 0px 2px 0px 0px rgba(101, 109, 118, 0.05)"); + expect(themeModel.cssVariables["--sjs-shadow-small"]).toEqual("0px 0px 0px 1px rgba(101, 109, 118, 0.25),0px 2px 0px 0px rgba(101, 109, 118, 0.05),inset 0px 1px 0px 0px rgba(255, 255, 255, 0.5)"); + + themeChooser.value = "default"; + expect(themeModel.cssVariables["--sjs-shadow-inner"]).toEqual("inset 0px 1px 2px 0px rgba(0, 0, 0, 0.15)"); + expect(themeModel.cssVariables["--sjs-shadow-small"]).toEqual("0px 1px 2px 0px rgba(0, 0, 0, 0.15)"); +}); + test("onThemePropertyChanged event for a custom property", (): any => { Serializer.addProperty("theme", { name: "paddingTopScale",