diff --git a/packages/survey-creator-angular/src/angular-ui.module.ts b/packages/survey-creator-angular/src/angular-ui.module.ts index 6edb24ece1..3af1df0d09 100644 --- a/packages/survey-creator-angular/src/angular-ui.module.ts +++ b/packages/survey-creator-angular/src/angular-ui.module.ts @@ -18,6 +18,7 @@ import { AceJsonEditorComponent } from "./tabs/json/json-editor-ace.component"; import { LogicTabComponent } from "./tabs/logic/logic.component"; import { LogicAddButtonComponent } from "./tabs/logic/logic-add-btn.component"; import { ActionButtonComponent } from "./components/action-button.component"; +import { SwitcherComponent } from "./components/switcher.component"; import { LinkValueQuestionComponent } from "./questions/question-link-value.component"; import { EmbeddedSurveyQuestionComponent } from "./questions/question-embedded-survey.component"; import { TranslationTabComponent } from "./tabs/translation/translation.component"; @@ -64,7 +65,7 @@ import { QuestionBannerComponent } from "./question-banner.component"; import { JsonErrorItemComponent } from "./tabs/json/json-error-item.component"; @NgModule({ - declarations: [CreatorComponent, DesignerTabComponent, PageDesignerComponent, QuestionDesignerComponent, PanelDesignerComponent, TabbledMenuComponent, TabbedMenuItemComponent, TabbedMenuItemWrapperComponent, SidebarComponent, SidebarTabComponent, ObjectSelectorComponent, PropertyGridComponent, SearchComponent, TextareaJsonEditorComponent, AceJsonEditorComponent, LogicTabComponent, LogicAddButtonComponent, ActionButtonComponent, LinkValueQuestionComponent, EmbeddedSurveyQuestionComponent, TranslationTabComponent, TranslationSkeletonComponent, SimulatorComponent, TestTabComponent, TestAgainActionComponent, SurveyResultsComponent, SurveyResultsTableRowComponent, ThemeTabComponent, + declarations: [CreatorComponent, DesignerTabComponent, PageDesignerComponent, QuestionDesignerComponent, PanelDesignerComponent, TabbledMenuComponent, TabbedMenuItemComponent, TabbedMenuItemWrapperComponent, SidebarComponent, SidebarTabComponent, ObjectSelectorComponent, PropertyGridComponent, SearchComponent, TextareaJsonEditorComponent, AceJsonEditorComponent, LogicTabComponent, LogicAddButtonComponent, ActionButtonComponent, SwitcherComponent, LinkValueQuestionComponent, EmbeddedSurveyQuestionComponent, TranslationTabComponent, TranslationSkeletonComponent, SimulatorComponent, TestTabComponent, TestAgainActionComponent, SurveyResultsComponent, SurveyResultsTableRowComponent, ThemeTabComponent, AdaptiveToolboxComponent, ToolboxToolComponent, ToolboxItemComponent, ToolboxCategoryComponent, StringEditorComponent, PageNavigatorComponent, PageNavigatorItemComponent, QuestionDropdownDesignerComponent, QuestionDropdownAdornerDesignerComponent, QuestionImageDesignerComponent, QuestionImageAdornerDesignerComponent, ItemValueDesignerComponent, ImageItemValueDesignerComponent, LogicOperatorComponent, MatrixCellComponent, QuestionEditorComponent, CellQuestionDropdownComponent, CreatorRowComponent, DesignerPagesComponent, DesignerSurveyComponent, CellQuestionComponent, QuestionWidgetDesignerComponent, ToolboxComponent, CreatorLogoImageComponent, @@ -74,7 +75,7 @@ import { JsonErrorItemComponent } from "./tabs/json/json-error-item.component"; CommonModule, FormsModule, SurveyModule ], exports: [ - CreatorComponent, DesignerTabComponent, PageDesignerComponent, QuestionDesignerComponent, PanelDesignerComponent, TabbledMenuComponent, TabbedMenuItemComponent, TabbedMenuItemWrapperComponent, SidebarComponent, SidebarTabComponent, ObjectSelectorComponent, PropertyGridComponent, SearchComponent, TextareaJsonEditorComponent, AceJsonEditorComponent, LogicTabComponent, LogicAddButtonComponent, ActionButtonComponent, LinkValueQuestionComponent, EmbeddedSurveyQuestionComponent, TranslationTabComponent, TranslationSkeletonComponent, SimulatorComponent, TestTabComponent, TestAgainActionComponent, SurveyResultsComponent, SurveyResultsTableRowComponent, ThemeTabComponent, + CreatorComponent, DesignerTabComponent, PageDesignerComponent, QuestionDesignerComponent, PanelDesignerComponent, TabbledMenuComponent, TabbedMenuItemComponent, TabbedMenuItemWrapperComponent, SidebarComponent, SidebarTabComponent, ObjectSelectorComponent, PropertyGridComponent, SearchComponent, TextareaJsonEditorComponent, AceJsonEditorComponent, LogicTabComponent, LogicAddButtonComponent, ActionButtonComponent, SwitcherComponent, LinkValueQuestionComponent, EmbeddedSurveyQuestionComponent, TranslationTabComponent, TranslationSkeletonComponent, SimulatorComponent, TestTabComponent, TestAgainActionComponent, SurveyResultsComponent, SurveyResultsTableRowComponent, ThemeTabComponent, AdaptiveToolboxComponent, ToolboxToolComponent, ToolboxItemComponent, ToolboxCategoryComponent, StringEditorComponent, PageNavigatorComponent, PageNavigatorItemComponent, QuestionDropdownDesignerComponent, QuestionDropdownAdornerDesignerComponent, QuestionImageDesignerComponent, QuestionImageAdornerDesignerComponent, ItemValueDesignerComponent, ImageItemValueDesignerComponent, LogicOperatorComponent, MatrixCellComponent, QuestionEditorComponent, CellQuestionDropdownComponent, CreatorRowComponent, DesignerPagesComponent, DesignerSurveyComponent, CellQuestionComponent, QuestionWidgetDesignerComponent, ToolboxComponent, CreatorLogoImageComponent, diff --git a/packages/survey-creator-angular/src/angular-ui.ts b/packages/survey-creator-angular/src/angular-ui.ts index 25295192b4..842553f358 100644 --- a/packages/survey-creator-angular/src/angular-ui.ts +++ b/packages/survey-creator-angular/src/angular-ui.ts @@ -15,6 +15,7 @@ export * from "./tabs/json/json-editor-ace.component"; export * from "./tabs/logic/logic.component"; export * from "./tabs/logic/logic-add-btn.component"; export * from "./components/action-button.component"; +export * from "./components/switcher.component"; export * from "./questions/question-link-value.component"; export * from "./questions/question-embedded-survey.component"; export * from "./tabs/translation/translation.component"; diff --git a/packages/survey-creator-angular/src/components/switcher.component.html b/packages/survey-creator-angular/src/components/switcher.component.html new file mode 100644 index 0000000000..22a8d5d5b3 --- /dev/null +++ b/packages/survey-creator-angular/src/components/switcher.component.html @@ -0,0 +1,11 @@ + + + \ No newline at end of file diff --git a/packages/survey-creator-angular/src/components/switcher.component.ts b/packages/survey-creator-angular/src/components/switcher.component.ts new file mode 100644 index 0000000000..1034553209 --- /dev/null +++ b/packages/survey-creator-angular/src/components/switcher.component.ts @@ -0,0 +1,18 @@ +import { Component, Input } from "@angular/core"; +import { AngularComponentFactory, BaseAngular } from "survey-angular-ui"; + +@Component({ + selector: "svc-switcher", + templateUrl: "./switcher.component.html", + styles: [":host { display: none; }"] +}) +export class SwitcherComponent extends BaseAngular { + @Input() model: any; + + getModel() { + return this.model; + } +} + +AngularComponentFactory.Instance.registerComponent("svc-switcher", SwitcherComponent); + diff --git a/packages/survey-creator-core/CHANGELOG.md b/packages/survey-creator-core/CHANGELOG.md index 092c0eeb11..67ce1f004e 100644 --- a/packages/survey-creator-core/CHANGELOG.md +++ b/packages/survey-creator-core/CHANGELOG.md @@ -2,6 +2,13 @@ All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines. +### [1.9.125](https://github.com/surveyjs/survey-creator/compare/v1.9.109...v1.9.125) (2024-01-09) + + +### Bug Fixes + +* change german translation of "header" ([#5013](https://github.com/surveyjs/survey-creator/issues/5013)) ([a004c08](https://github.com/surveyjs/survey-creator/commit/a004c08f3a576450023f163a8d902e469afb2bf1)) + ### [1.9.124](https://github.com/surveyjs/survey-creator/compare/v1.9.123...v1.9.124) (2024-01-05) ### [1.9.123](https://github.com/surveyjs/survey-creator/compare/v1.9.122...v1.9.123) (2023-12-27) diff --git a/packages/survey-creator-core/package.json b/packages/survey-creator-core/package.json index d18a413f29..8fc371d790 100644 --- a/packages/survey-creator-core/package.json +++ b/packages/survey-creator-core/package.json @@ -1,5 +1,5 @@ { - "version": "1.9.124", + "version": "1.9.125", "name": "survey-creator-core", "homepage": "https://surveyjs.io/Overview/Survey-Creator", "license": "SEE LICENSE IN LICENSE", diff --git a/packages/survey-creator-core/src/components/switcher/switcher.scss b/packages/survey-creator-core/src/components/switcher/switcher.scss new file mode 100644 index 0000000000..8ba82571d8 --- /dev/null +++ b/packages/survey-creator-core/src/components/switcher/switcher.scss @@ -0,0 +1,90 @@ +@import "../../variables.scss"; + +.svc-switcher.spg-action-button { + align-items: center; + gap: calcSize(1); + pointer-events: auto; +} + +.svc-switcher__title { + color: $foreground-light; + + font-family: $font-family; + font-size: calcSize(1.5); + font-style: normal; + font-weight: 600; + line-height: calcSize(1); +} + +.svc-switcher__icon { + width: calcSize(2.5); + padding: calcSize(0.5); + justify-content: center; + align-items: center; + border-radius: 100px; + border: 1px solid $border; + background: $background-dim; + + transition-duration: 0.2s; + transition-property: background; + transition-timing-function: linear; +} + +.svc-switcher__icon:hover { + background: $background; +} + +.svc-switcher__icon:focus { + border: calcSize(0.25) solid $primary; + background: $background-dim; +} + +.svc-switcher__icon:hover:focus { + border: calcSize(0.25) solid $primary; + background: $background; +} + +.svc-switcher__icon--checked, +.svc-switcher__icon--checked:hover { + justify-content: center; + align-items: center; + border: unset; + + border-radius: 100px; + background-color: $primary; +} + +.svc-switcher__icon--checked:focus { + border: calcSize(0.25) solid $primary; + background-color: $primary-foreground; +} + +.svc-switcher__icon-thumb { + width: calcSize(1); + height: calcSize(1); + justify-content: center; + align-items: center; + + border-radius: 100px; + background-color: $foreground-dim-light; + + transform: translateX(0); + margin-left: 0%; + transition-duration: 0.2s; + transition-property: margin-left, transform, background-color; + transition-timing-function: linear; +} + +.svc-switcher__icon--checked .svc-switcher__icon-thumb { + background-color: $primary-foreground; + margin-left: 100%; + transform: translateX(-100%); +} + +.svc-switcher__icon:focus, +.svc-switcher__icon:hover:focus, +.svc-switcher__icon--checked:focus { + .svc-switcher__icon-thumb { + background-color: $primary; + } +} diff --git a/packages/survey-creator-core/src/components/switcher/switcher.ts b/packages/survey-creator-core/src/components/switcher/switcher.ts new file mode 100644 index 0000000000..9f074d018b --- /dev/null +++ b/packages/survey-creator-core/src/components/switcher/switcher.ts @@ -0,0 +1,14 @@ +import { Action, CssClassBuilder, property } from "survey-core"; + +require("./switcher.scss"); + +export class Switcher extends Action { + @property() checked: boolean; + + public getSwitcherIconCss(): string { + return new CssClassBuilder() + .append("svc-switcher__icon") + .append("svc-switcher__icon--checked", this.checked) + .toString(); + } +} \ No newline at end of file diff --git a/packages/survey-creator-core/src/components/tabs/theme-builder.ts b/packages/survey-creator-core/src/components/tabs/theme-builder.ts index f1a9cb241c..460e3e0b9b 100644 --- a/packages/survey-creator-core/src/components/tabs/theme-builder.ts +++ b/packages/survey-creator-core/src/components/tabs/theme-builder.ts @@ -1,5 +1,5 @@ import { SurveySimulatorModel } from "../simulator"; -import { surveyLocalization, Base, propertyArray, property, PageModel, SurveyModel, Action, IAction, ActionContainer, ComputedUpdater, defaultV2Css, createDropdownActionModel, ComponentCollection, ITheme, ItemValue, ImageFit, ImageAttachment, QuestionDropdownModel, ValueChangingEvent, ValueChangedEvent, EventBase, Cover, Serializer, Question, IHeader } from "survey-core"; +import { surveyLocalization, Base, propertyArray, property, PageModel, SurveyModel, Action, IAction, ActionContainer, ComputedUpdater, defaultV2Css, createDropdownActionModel, ComponentCollection, ITheme, ItemValue, ImageFit, ImageAttachment, QuestionDropdownModel, ValueChangingEvent, ValueChangedEvent, EventBase, Cover, Serializer, Question, IHeader, PanelModelBase } from "survey-core"; import { CreatorBase } from "../../creator-base"; import { editorLocalization, getLocString } from "../../editorLocalization"; import { setSurveyJSONForPropertyGrid } from "../../property-grid"; @@ -10,10 +10,11 @@ import { DefaultFonts, fontsettingsFromCssVariable, fontsettingsToCssVariable } import { elementSettingsFromCssVariable, elementSettingsToCssVariable } from "./theme-custom-questions/element-settings"; import { UndoRedoManager } from "../../plugins/undo-redo/undo-redo-manager"; import { PredefinedColors, PredefinedThemes, Themes } from "./themes"; -import { QuestionFileEditorModel } from "src/entries"; +import { QuestionFileEditorModel } from "../../custom-questions/question-file"; import { updateCustomQuestionJSONs } from "./theme-custom-questions"; import * as LibraryThemes from "survey-core/themes"; import { createBoxShadowReset } from "./theme-custom-questions/boxshadow-settings"; +import { Switcher } from "../switcher/switcher"; require("./theme-builder.scss"); @@ -173,6 +174,7 @@ export class ThemeBuilder extends Base { @property({ defaultValue: "default" }) themeName; @property({ defaultValue: "light" }) themePalette; @property({ defaultValue: "panels" }) themeMode; + @property() groupAppearanceAdvancedMode: boolean; getFullThemeName(_themeName?: string) { if (this.themePalette === "light") { @@ -617,14 +619,6 @@ export class ThemeBuilder extends Base { } } private updateDependentQuestionValues(options: ValueChangedEvent) { - if (options.name === "generalBackcolorDimColor") { - this.themeEditorSurvey.setValue("--sjs-general-backcolor-dim", options.value); - return true; - } - if (options.name === "--sjs-general-backcolor-dim") { - this.themeEditorSurvey.getQuestionByName("generalBackcolorDimColor").value = options.value; - return false; - } if (options.name === "generalPrimaryColor") { this.themeEditorSurvey.setValue("--sjs-primary-backcolor", options.value); return true; @@ -718,6 +712,13 @@ export class ThemeBuilder extends Base { opt.actions = []; } }); + themeEditorSurvey.onGetPanelTitleActions.add((sender, opt) => { + if (this.surveyProvider.isMobileView) return; + + if (opt.panel && opt.panel.name == "groupAppearance") { + opt.titleActions.push(this.createAppearanceAdvancedModeAction(opt.panel)); + } + }); themeEditorSurvey.onUpdatePanelCssClasses.add((sender, options) => { if (options.panel.hasParent) { const parent = (options.panel.parent ?? options.panel.parentQuestion); @@ -735,6 +736,31 @@ export class ThemeBuilder extends Base { }); return themeEditorSurvey; } + + private createAppearanceAdvancedModeAction(panel: PanelModelBase) { + const advancedMode = new Switcher({ + id: "advancedMode", + component: "svc-switcher", + ariaChecked: new ComputedUpdater(() => this.groupAppearanceAdvancedMode), + ariaRole: "checkbox", + css: "sv-theme-group_title-action", + title: getLocString("theme.advancedMode"), + iconSize: 16, + action: () => { + this.groupAppearanceAdvancedMode = !this.groupAppearanceAdvancedMode; + panel.getQuestionByName("advancedMode").value = this.groupAppearanceAdvancedMode; + } + }); + this.registerFunctionOnPropertyValueChanged("groupAppearanceAdvancedMode", + () => { + advancedMode.checked = !advancedMode.checked; + }, + "groupAppearanceAdvancedMode" + ); + advancedMode.checked = false; + return advancedMode; + } + findSuitableTheme(themeName: string): ITheme { let probeThemeFullName = getThemeFullName({ themeName: themeName, colorPalette: this.themePalette, isPanelless: this.themeMode === "lightweight" } as any); return findSuitableTheme(themeName, this.themePalette, this.themeMode, probeThemeFullName); @@ -790,7 +816,6 @@ export class ThemeBuilder extends Base { private updateVisibilityOfPropertyGridGroups() { const page = this.themeEditorSurvey.pages[0]; page.getElementByName("groupHeader").visible = this.surveyProvider.isMobileView ? false : settings.theme.allowEditHeaderSettings; - page.getElementByName("groupAdvanced").visible = !this.surveyProvider.isMobileView; } private setCoverPropertiesFromSurvey(panel, themeCssVariables: { [index: string]: string }) { panel.getQuestionByName("headerTitle").readOnly = !this.survey.hasTitle; @@ -901,7 +926,6 @@ export class ThemeBuilder extends Base { themeEditorSurvey.getQuestionByName("backgroundImageAttachment").value = this.currentTheme.backgroundImageAttachment; themeEditorSurvey.getQuestionByName("backgroundOpacity").value = this.currentTheme.backgroundOpacity * 100; themeEditorSurvey.getQuestionByName("generalPrimaryColor").value = themeEditorSurvey.getQuestionByName("--sjs-primary-backcolor").value; - themeEditorSurvey.getQuestionByName("generalBackcolorDimColor").value = themeEditorSurvey.getQuestionByName("--sjs-general-backcolor-dim").value; this.updateHeaderViewContainerEditors(newCssVariables); elementSettingsFromCssVariable(themeEditorSurvey.getQuestionByName("questionPanel"), newCssVariables, newCssVariables["--sjs-general-backcolor"], newCssVariables["--sjs-general-backcolor-dark"]); @@ -1234,29 +1258,40 @@ export class ThemeBuilder extends Base { max: 100, step: 5 }, + { + type: "boolean", + name: "overlapEnabled", + renderAs: "checkbox", + title: getLocString("theme.coverOverlapEnabled"), + titleLocation: "hidden", + descriptionLocation: "hidden", + }, ] }, + ] + }, { + type: "panel", + questionTitleLocation: "top", + visibleIf: "{panel.headerView} = 'advanced'", + elements: [ { - type: "fontSettings", - name: "headerTitle", - title: getLocString("theme.surveyTitle"), - descriptionLocation: "hidden", - defaultValue: this.getDefaultTitleSetting(true) - }, - { - type: "fontSettings", - name: "headerDescription", - title: getLocString("theme.surveyDescription"), - descriptionLocation: "hidden", - defaultValue: this.getDefaultDescriptionSetting(true) - }, - { - type: "boolean", - name: "overlapEnabled", - renderAs: "checkbox", - title: getLocString("theme.coverOverlapEnabled"), - titleLocation: "hidden", - descriptionLocation: "hidden", + type: "panel", + elements: [ + { + type: "fontSettings", + name: "headerTitle", + title: getLocString("theme.surveyTitle"), + descriptionLocation: "hidden", + defaultValue: this.getDefaultTitleSetting(true) + }, + { + type: "fontSettings", + name: "headerDescription", + title: getLocString("theme.surveyDescription"), + descriptionLocation: "hidden", + defaultValue: this.getDefaultDescriptionSetting(true) + }, + ] } ] }, { @@ -1303,7 +1338,7 @@ export class ThemeBuilder extends Base { elements: [ { type: "color", - name: "generalBackcolorDimColor", + name: "--sjs-general-backcolor-dim", title: getLocString("theme.backgroundDimColor"), descriptionLocation: "hidden", }, @@ -1367,8 +1402,15 @@ export class ThemeBuilder extends Base { state: "collapsed", title: getLocString("theme.groupAppearance"), elements: [ + { + "type": "boolean", + "name": "advancedMode", + "visible": false, + "defaultValue": "false" + }, { type: "panel", + visibleIf: "{advancedMode} = false", elements: [ { type: "color", @@ -1401,6 +1443,7 @@ export class ThemeBuilder extends Base { ] }, { type: "panel", + visibleIf: "{advancedMode} = false", elements: [ { type: "dropdown", @@ -1424,6 +1467,7 @@ export class ThemeBuilder extends Base { ] }, { type: "panel", + visibleIf: "{advancedMode} = false", elements: [ { type: "spinedit", @@ -1445,23 +1489,11 @@ export class ThemeBuilder extends Base { min: 0 }, ] - } - ] - }, { - type: "panel", - name: "groupAdvanced", - title: getLocString("theme.groupAdvanced"), - state: "collapsed", - elements: [ - { + }, { type: "panel", + visibleIf: "{advancedMode} = true", elements: [ { - type: "color", - name: "--sjs-general-backcolor-dim", - title: getLocString("theme.backgroundDimColor"), - descriptionLocation: "hidden", - }, { type: "panel", title: getLocString("theme.accentBackground"), elements: [ @@ -1511,14 +1543,20 @@ export class ThemeBuilder extends Base { descriptionLocation: "hidden", } ] - }] + }, { + type: "html", + name: "theme", + html: `
${getLocString("theme.pageTitle")}
`, + }, + ] }, { type: "panel", + visibleIf: "{advancedMode} = true", elements: [ { type: "fontSettings", name: "pageTitle", - title: getLocString("theme.pageTitle"), + title: getLocString("theme.titleFont"), descriptionLocation: "hidden", defaultValue: { family: settings.theme.fontFamily, @@ -1529,7 +1567,7 @@ export class ThemeBuilder extends Base { }, { type: "fontSettings", name: "pageDescription", - title: getLocString("theme.pageDescription"), + title: getLocString("theme.descriptionFont"), descriptionLocation: "hidden", defaultValue: { family: settings.theme.fontFamily, @@ -1537,15 +1575,20 @@ export class ThemeBuilder extends Base { weight: "400", size: 16 } - } + }, { + type: "html", + name: "theme", + html: `
${getLocString("theme.questionTitle")}
`, + }, ] }, { type: "panel", + visibleIf: "{advancedMode} = true", elements: [ { type: "elementSettings", name: "questionPanel", - title: getLocString("theme.questionPanel"), + title: getLocString("theme.backgroundCornerRadius"), descriptionLocation: "hidden", defaultValue: { backcolor: "rgba(255, 255, 255, 1)", @@ -1558,7 +1601,7 @@ export class ThemeBuilder extends Base { type: "boxshadowsettings", name: "--sjs-shadow-small", descriptionLocation: "hidden", - title: getLocString("theme.questionShadow"), + title: getLocString("theme.shadow"), defaultValue: [ { x: 0, @@ -1578,7 +1621,7 @@ export class ThemeBuilder extends Base { }, { type: "fontSettings", name: "questionTitle", - title: getLocString("theme.questionTitle"), + title: getLocString("theme.titleFont"), descriptionLocation: "hidden", defaultValue: { family: settings.theme.fontFamily, @@ -1589,7 +1632,7 @@ export class ThemeBuilder extends Base { }, { type: "fontSettings", name: "questionDescription", - title: getLocString("theme.questionDescription"), + title: getLocString("theme.descriptionFont"), descriptionLocation: "hidden", defaultValue: { family: settings.theme.fontFamily, @@ -1597,15 +1640,20 @@ export class ThemeBuilder extends Base { weight: "400", size: 16 } - } + }, { + type: "html", + name: "theme", + html: `
${getLocString("theme.editorPanel")}
`, + }, ] }, { type: "panel", + visibleIf: "{advancedMode} = true", elements: [ { type: "elementSettings", name: "editorPanel", - title: getLocString("theme.editorPanel"), + title: getLocString("theme.backgroundCornerRadius"), descriptionLocation: "hidden", defaultValue: { backcolor: "rgba(255, 255, 255, 1)", @@ -1618,7 +1666,7 @@ export class ThemeBuilder extends Base { type: "boxshadowsettings", name: "--sjs-shadow-inner", descriptionLocation: "hidden", - title: getLocString("theme.editorShadow"), + title: getLocString("theme.shadow"), defaultValue: [ { x: 0, @@ -1638,7 +1686,7 @@ export class ThemeBuilder extends Base { }, { type: "fontSettings", name: "editorFont", - title: getLocString("theme.editorFont"), + title: getLocString("theme.font"), descriptionLocation: "hidden", defaultValue: { family: settings.theme.fontFamily, @@ -1646,13 +1694,18 @@ export class ThemeBuilder extends Base { weight: "400", size: 16 } - } + }, { + type: "html", + name: "theme", + html: `
${getLocString("theme.lines")}
`, + }, ] }, { type: "panel", + visibleIf: "{advancedMode} = true", elements: [{ type: "panel", - title: getLocString("theme.linesColors"), + title: getLocString("theme.colorsTitle"), elements: [ { type: "colorsettings", diff --git a/packages/survey-creator-core/src/entries/index.ts b/packages/survey-creator-core/src/entries/index.ts index 40373d0616..bc14e8ed4f 100644 --- a/packages/survey-creator-core/src/entries/index.ts +++ b/packages/survey-creator-core/src/entries/index.ts @@ -77,6 +77,7 @@ export * from "../textWorker"; export * from "../toolbox"; export * from "../components/side-bar/side-bar-model"; export * from "../components/side-bar/side-bar-tab-model"; +export * from "../components/switcher/switcher"; export * from "../utils/events"; export * from "../utils/utils"; export * from "../question-editor/definition"; diff --git a/packages/survey-creator-core/src/localization/english.ts b/packages/survey-creator-core/src/localization/english.ts index ec7590bdd5..cacb8f6f43 100644 --- a/packages/survey-creator-core/src/localization/english.ts +++ b/packages/survey-creator-core/src/localization/english.ts @@ -1038,8 +1038,8 @@ export var enStrings = { "--primary-foreground": "Primary foreground color", "--foreground": "Foreground color", "--base-unit": "Base unit", + advancedMode: "Advanced mode", groupGeneral: "General", - groupAdvanced: "Advanced", groupHeader: "Header", groupBackground: "Background", groupAppearance: "Appearance", @@ -1068,11 +1068,9 @@ export var enStrings = { backgroundImageAttachmentScroll: "Scroll", panelBackgroundTransparency: "Panel background opacity", questionBackgroundTransparency: "Question background opacity", - questionPanel: "Panel background and corner radius", - questionTitle: "Question title font", - questionDescription: "Question description font", + questionTitle: "Question Box", editorPanel: "Input element", - editorFont: "Input element font", + backgroundCornerRadius: "Background and corner radius", backcolor: "Default background", hovercolor: "Hover background", borderDecoration: "Border decoration", @@ -1080,7 +1078,9 @@ export var enStrings = { accentForeground: "Accent foreground", primaryForecolor: "Default color", primaryForecolorLight: "Disabled color", - linesColors: "Minor line colors", + colorsTitle: "Colors", + font: "Font", + lines: "Lines", borderDefault: "Darker", borderLight: "Lighter", fontFamily: "Font family", @@ -1096,8 +1096,9 @@ export var enStrings = { cornerRadius: "Corner radius", surveyTitle: "Survey title font", surveyDescription: "Survey description font", - pageTitle: "Page title font", - pageDescription: "Page description font", + pageTitle: "Page", + titleFont: "Title font", + descriptionFont: "Description font", boxShadowX: "X", boxShadowY: "Y", boxShadowAddRule: "Add Shadow Effect", @@ -1106,8 +1107,7 @@ export var enStrings = { boxShadowSpread: "Spread", boxShadowDrop: "Drop", boxShadowInner: "Inner", - questionShadow: "Shadow effects", - editorShadow: "Input element shadow effects", + shadow: "Shadow effects", headerView: "View", headerViewBasic: "Basic", headerViewAdvanced: "Advanced", diff --git a/packages/survey-creator-core/src/property-grid-theme/blocks/spg-theme-builder.scss b/packages/survey-creator-core/src/property-grid-theme/blocks/spg-theme-builder.scss index 12d6e7edab..45823c9eae 100644 --- a/packages/survey-creator-core/src/property-grid-theme/blocks/spg-theme-builder.scss +++ b/packages/survey-creator-core/src/property-grid-theme/blocks/spg-theme-builder.scss @@ -120,6 +120,25 @@ content: none; } } + + .spg-theme-group-caption { + @include defaultBold; + color: $foreground-dim; + + position: relative; + top: calc(4 * #{$base-unit}); + padding: calc(1 * #{$base-unit}) 0; + cursor: auto; + } + + .sv-theme-group_title-action .spg-action-button:hover, + .sv-theme-group_title-action .spg-action-button:focus { + background-color: unset; + } + + .sd-panel__header.sd-element__header .spg-action-bar { + pointer-events: none; + } } .sv-mobile-side-bar .spg-theme-builder-root { diff --git a/packages/survey-creator-core/tests/tabs/theme-builder.tests.ts b/packages/survey-creator-core/tests/tabs/theme-builder.tests.ts index 691d3ac7a4..e0046656fb 100644 --- a/packages/survey-creator-core/tests/tabs/theme-builder.tests.ts +++ b/packages/survey-creator-core/tests/tabs/theme-builder.tests.ts @@ -1183,34 +1183,29 @@ test("Theme undo redo changes", (): any => { const themeSurveyTab = themePlugin.model as ThemeBuilder; const themeEditor = themeSurveyTab.themeEditorSurvey; const question = themeEditor.getQuestionByName("--sjs-general-backcolor-dim"); - const generalBackcolorDimColorQuestion = themeEditor.getQuestionByName("generalBackcolorDimColor"); expect(themeSurveyTab.undoRedoManager.canUndo()).toBe(false); expect(themeSurveyTab.undoRedoManager.canRedo()).toBe(false); expect(themeSurveyTab["blockThemeChangedNotifications"]).toBe(0); expect(question.value).toBe("rgba(243, 243, 243, 1)"); - expect(generalBackcolorDimColorQuestion.value).toBe("#f3f3f3"); question.value = "#ff0000"; expect(themeSurveyTab.undoRedoManager.canUndo()).toBe(true); expect(themeSurveyTab.undoRedoManager.canRedo()).toBe(false); expect(themeSurveyTab["blockThemeChangedNotifications"]).toBe(0); expect(question.value).toBe("#ff0000"); - expect(generalBackcolorDimColorQuestion.value).toBe("#ff0000"); themePlugin.undo(); expect(themeSurveyTab.undoRedoManager.canUndo()).toBe(false); expect(themeSurveyTab.undoRedoManager.canRedo()).toBe(true); expect(themeSurveyTab["blockThemeChangedNotifications"]).toBe(0); expect(question.value).toBe("#f3f3f3"); - expect(generalBackcolorDimColorQuestion.value).toBe("#f3f3f3"); themePlugin.redo(); expect(themeSurveyTab.undoRedoManager.canUndo()).toBe(true); expect(themeSurveyTab.undoRedoManager.canRedo()).toBe(false); expect(themeSurveyTab["blockThemeChangedNotifications"]).toBe(0); expect(question.value).toBe("#ff0000"); - expect(generalBackcolorDimColorQuestion.value).toBe("#ff0000"); }); test("Theme undo redo general settings", (): any => { @@ -1558,7 +1553,6 @@ test("onThemeSelected + onThemePropertyChanged events", (): any => { const themePalette = themeEditorSurvey.getQuestionByName("themePalette"); const primaryBackColor = themeEditorSurvey.getQuestionByName("--sjs-primary-backcolor"); const backgroundDimColor = themeEditorSurvey.getQuestionByName("--sjs-general-backcolor-dim"); - const generalBackcolorDimColor = themeEditorSurvey.getQuestionByName("generalBackcolorDimColor"); const generalPrimaryColor = themeEditorSurvey.getQuestionByName("generalPrimaryColor"); let pluginThemeSelectedCount = 0; @@ -1582,7 +1576,7 @@ test("onThemeSelected + onThemePropertyChanged events", (): any => { expect(builderThemeModifiedCount).toBe(1); expect(builderThemeSelectedCount).toBe(1); - generalBackcolorDimColor.value = "#7a46bb"; + backgroundDimColor.value = "#7a46bb"; expect(pluginThemeModifiedCount).toBe(2); expect(pluginThemeSelectedCount).toBe(1); expect(builderThemeModifiedCount).toBe(2); @@ -2263,6 +2257,26 @@ test("Creator footer action bar: all tabs", (): any => { receivedOrder = creator.footerToolbar.visibleActions.map(a => a.id).join("|"); expect(receivedOrder).toEqual(designerTabButtonOrder); }); + +test("Desktop mode: add advanced mode switcher", (): any => { + const creator: CreatorTester = new CreatorTester({ showThemeTab: true }); + creator.JSON = { questions: [{ type: "text", name: "q1" }] }; + + const themePlugin: ThemeTabPlugin = creator.getPlugin("theme"); + themePlugin.activate(); + const themeBuilder = themePlugin.model as ThemeBuilder; + const themeEditorSurvey = themeBuilder.themeEditorSurvey; + const propertyGridGroups = themeEditorSurvey.pages[0].elements; + expect(propertyGridGroups.length).toBe(4); + expect(propertyGridGroups[0].visible).toBeTruthy(); + expect(propertyGridGroups[1].visible).toBeTruthy(); + expect(propertyGridGroups[2].visible).toBeTruthy(); + expect(propertyGridGroups[3].visible).toBeTruthy(); + + const actions = propertyGridGroups[3].getTitleActions(); + expect(actions.length).toBe(1); +}); + test("Mobile mode: hide advanced settings in property grid", (): any => { const creator: CreatorTester = new CreatorTester({ showThemeTab: true }); creator.JSON = { questions: [{ type: "text", name: "q1" }] }; @@ -2273,12 +2287,14 @@ test("Mobile mode: hide advanced settings in property grid", (): any => { const themeBuilder = themePlugin.model as ThemeBuilder; const themeEditorSurvey = themeBuilder.themeEditorSurvey; const propertyGridGroups = themeEditorSurvey.pages[0].elements; - expect(propertyGridGroups.length).toBe(5); + expect(propertyGridGroups.length).toBe(4); expect(propertyGridGroups[0].visible).toBeTruthy(); expect(propertyGridGroups[1].visible).toBeFalsy(); expect(propertyGridGroups[2].visible).toBeTruthy(); expect(propertyGridGroups[3].visible).toBeTruthy(); - expect(propertyGridGroups[4].visible).toBeFalsy(); + + const actions = propertyGridGroups[3].getTitleActions(); + expect(actions.length).toBe(0); }); test("loadTheme fill all theme parameters: name, mode and compactness", (): any => { const creator: CreatorTester = new CreatorTester({ showThemeTab: true }); diff --git a/packages/survey-creator-knockout/src/entries/index.ts b/packages/survey-creator-knockout/src/entries/index.ts index 217eff9cae..1cb0e5ef3e 100644 --- a/packages/survey-creator-knockout/src/entries/index.ts +++ b/packages/survey-creator-knockout/src/entries/index.ts @@ -62,6 +62,7 @@ export * from "../header/logo-image"; export * from "../tabs/translation-line-skeleton"; export * from "../utils/survey-widget"; export * from "../utils/utils"; +export * from "../switcher/switcher"; export * from "../creator"; diff --git a/packages/survey-creator-knockout/src/switcher/switcher.html b/packages/survey-creator-knockout/src/switcher/switcher.html new file mode 100644 index 0000000000..d3cf2aa3b1 --- /dev/null +++ b/packages/survey-creator-knockout/src/switcher/switcher.html @@ -0,0 +1,11 @@ + + + \ No newline at end of file diff --git a/packages/survey-creator-knockout/src/switcher/switcher.ts b/packages/survey-creator-knockout/src/switcher/switcher.ts new file mode 100644 index 0000000000..3502ad68e4 --- /dev/null +++ b/packages/survey-creator-knockout/src/switcher/switcher.ts @@ -0,0 +1,15 @@ +import * as ko from "knockout"; +import { Switcher } from "survey-creator-core"; +import { ImplementorBase } from "survey-knockout-ui"; +const template = require("./switcher.html"); + +ko.components.register("svc-switcher", { + viewModel: { + createViewModel: (params: any) => { + const item: Switcher = params.item; + new ImplementorBase(item); + return params; + }, + }, + template: template +}); diff --git a/packages/survey-creator-react/src/Switcher.tsx b/packages/survey-creator-react/src/Switcher.tsx new file mode 100644 index 0000000000..6f10248ce2 --- /dev/null +++ b/packages/survey-creator-react/src/Switcher.tsx @@ -0,0 +1,47 @@ +import React from "react"; +import { Switcher } from "survey-creator-core"; +import { Base } from "survey-core"; +import { ReactElementFactory, attachKey2click, SurveyElementBase } from "survey-react-ui"; + +interface ISwitcherComponentProps { + item: Switcher; +} + +export class SwitcherComponent extends SurveyElementBase { + get item(): Switcher { + return this.props.item; + } + + protected getStateElement(): Base { + return this.item; + } + + renderElement() { + const tooltip = this.item.tooltip || this.item.title; + const className = "svc-switcher " + this.item.getActionBarItemCss(); + const title = this.item.hasTitle ? {this.item.title} : null; + const button = attachKey2click( + , this.item, { processEsc: false }); + + return button; + } +} + +export default SwitcherComponent; + +ReactElementFactory.Instance.registerElement("svc-switcher", (props) => { + return React.createElement(SwitcherComponent, props); +}); \ No newline at end of file diff --git a/packages/survey-creator-react/src/entries/index.ts b/packages/survey-creator-react/src/entries/index.ts index 1ded8ea7b8..da66acc2e7 100644 --- a/packages/survey-creator-react/src/entries/index.ts +++ b/packages/survey-creator-react/src/entries/index.ts @@ -52,6 +52,7 @@ export * from "../events"; export * from "../ObjectSelector"; export * from "../PropertyGrid"; export * from "../Search"; +export * from "../Switcher"; export * from "../tabs/JsonErrorItem"; diff --git a/visualRegressionTests/tests/designer/etalons/theme-editor-property-grid-appearance-group.png b/visualRegressionTests/tests/designer/etalons/theme-editor-property-grid-appearance-group.png index 91ad8336b5..a8f9950ab0 100644 Binary files a/visualRegressionTests/tests/designer/etalons/theme-editor-property-grid-appearance-group.png and b/visualRegressionTests/tests/designer/etalons/theme-editor-property-grid-appearance-group.png differ diff --git a/visualRegressionTests/tests/designer/theme-tab.ts b/visualRegressionTests/tests/designer/theme-tab.ts index 07b04a10ce..faf46de251 100644 --- a/visualRegressionTests/tests/designer/theme-tab.ts +++ b/visualRegressionTests/tests/designer/theme-tab.ts @@ -7,6 +7,8 @@ fixture`${title}`.page`${url}`.beforeEach(async (t) => { await t.maximizeWindow(); }); +const advancedModeSwitcher = getPropertyGridCategory("Appearance").parent(".spg-title").find(".svc-switcher"); + test("Check boxshadow settings", async (t) => { await wrapVisualTest(t, async (t, comparer) => { const json = {}; @@ -14,7 +16,8 @@ test("Check boxshadow settings", async (t) => { const root = Selector("div[data-name='--sjs-shadow-small']"); await t.resizeWindow(2000, 2000) .click(getTabbedMenuItemByText("Themes")) - .click(Selector("h4[aria-label='Advanced']")); + .click(getPropertyGridCategory("Appearance")) + .click(advancedModeSwitcher); await takeElementScreenshot("boxshadow-one-panel.png", root, t, comparer); await t.click(".spg-paneldynamic__add-btn"); await t.hover(root, { offsetX: 0, offsetY: 0 }); @@ -87,8 +90,7 @@ test("theme setting property grid", async (t) => { await ClientFunction(() => document.body.focus())(); await takeElementScreenshot("theme-editor-property-grid-appearance-group.png", expandedGroup, t, comparer); - await t.click(getPropertyGridCategory("Appearance")); - await t.click(getPropertyGridCategory("Advanced")); + await t.click(advancedModeSwitcher); await ClientFunction(() => document.body.focus())(); await takeElementScreenshot("theme-editor-property-grid-advanced-group.png", expandedGroup, t, comparer); });