src/styling-panel-definition.js
import { fontResolver as createFontResolver } from "qlik-chart-modules";
import styleDefaults from "./style-defaults";
import propertyResolver from "./utils/property-resolver";
import { colorOptions, sizeBehaviorOptions, toggleOptions } from "./utils/style-utils";
export const getStyleEditorDefinition = ({ flags, theme, translator }) => {
const fontResolver = createFontResolver({
theme,
translator,
flags,
config: {
id: "actionButton",
paths: ["style.font"],
},
});
return {
items: {
labelSection: {
component: "panel-section",
translation: "Common.Label",
items: {
labelItem: {
items: {
fontFamily: {
component: "dropdown",
ref: "style.font.fontFamily",
options: () => fontResolver.getOptions("style.font.fontFamily"),
defaultValue: () => fontResolver.getDefaultValue("style.font.fontFamily"),
},
fontWrapper: {
component: "inline-wrapper",
type: "items",
grouped: true,
items: {
fontStyle: {
type: "array",
component: "font-style-buttons",
width: false,
ref: "style.font.style",
defaultValue: ["bold"],
},
textAlign: {
component: "text-align-buttons",
ref: "style.font.align",
defaultValue: styleDefaults.TEXT_ALIGN,
},
},
},
fontSizeBehavior: {
component: "dropdown",
ref: "style.font.sizeBehavior",
translation: "properties.kpi.layoutBehavior",
defaultValue: "responsive",
options: sizeBehaviorOptions,
},
fontSize: {
component: "slider",
type: "number",
ref: "style.font.size",
translation: "properties.fontSize",
min: 0.2,
max: 1,
step: 0.01,
defaultValue: 0.5,
show: (data) => !(propertyResolver.getValue(data, "style.font.sizeBehavior") === "fixed"),
},
fontSizeFixed: {
type: "number",
ref: "style.font.sizeFixed",
component: "integer",
translation: "properties.fontSize",
min: 5,
defaultValue: 20,
option: "optional",
show: (data) => propertyResolver.getValue(data, "style.font.sizeBehavior") === "fixed",
},
fontColor: {
items: {
useFontColorExpression: {
ref: "style.font.useColorExpression",
type: "boolean",
translation: "properties.fontColor",
component: "dropdown",
width: 14,
options: colorOptions,
},
colorPicker: {
type: "object",
component: "color-picker",
ref: "style.font.color",
translation: "properties.color",
defaultValue: styleDefaults.FONT_COLOR,
disabledNone: true,
width: 12,
show: (data) => !propertyResolver.getValue(data, "style.font.useColorExpression"),
},
colorExpression: {
type: "string",
component: "input-field-expression",
ref: "style.font.colorExpression",
translation: "Common.Expression",
expression: "optional",
show: (data) => propertyResolver.getValue(data, "style.font.useColorExpression"),
},
},
},
},
},
},
},
backgroundOptions: {
component: "panel-section",
translation: "properties.background.options",
items: {
backgroundColor: {
type: "items",
items: {
useColorExpression: {
type: "boolean",
component: "dropdown",
ref: "style.background.useColorExpression",
translation: "properties.color",
options: colorOptions,
},
colorExpression: {
type: "string",
component: "input-field-expression",
ref: "style.background.colorExpression",
translation: "Common.Expression",
expression: "optional",
show: (data) => propertyResolver.getValue(data, "style.background.useColorExpression"),
},
colorPicker: {
type: "object",
component: "color-picker",
ref: "style.background.color",
translation: "properties.color.used",
disableNone: false,
defaultValue: styleDefaults.COLOR,
dualOutput: true,
show: (data) => !propertyResolver.getValue(data, "style.background.useColorExpression"),
},
},
},
backgroundImage: {
items: {
backgroundImageMode: {
component: "dropdown",
ref: "style.background.mode",
translation: "properties.backgroundImage",
defaultValue: styleDefaults.BGIMAGE_MODE,
options: [
{
value: "none",
translation: "Background.None",
},
{
value: "media",
translation: "MediaLibrary.Header",
},
],
change(data) {
const bgImageComp = data.style.background;
if (!bgImageComp) data.style.background = { qStaticContentUrlDef: {} };
if (!bgImageComp.url) data.style.background.url = {};
},
},
MediaLibrary: {
component: "media-library-button",
ref: "style.background.url",
translation: "MediaLibrary.Header",
show: (data) => propertyResolver.getValue(data, "style.background.mode") === "media",
},
imageSize: {
component: "dropdown",
ref: "style.background.size",
defaultValue: styleDefaults.BACKGROUND_SIZE,
options: [
{
value: "auto",
translation: "properties.backgroundImage.originalSize",
},
{
value: "alwaysFit",
translation: "properties.backgroundImage.sizeAlwaysFit",
},
{
value: "fitWidth",
translation: "properties.backgroundImage.sizeFitWidth",
},
{
value: "fitHeight",
translation: "properties.backgroundImage.sizeFitHeight",
},
{
value: "stretchFit",
translation: "properties.backgroundImage.sizeStretch",
},
{
value: "alwaysFill",
translation: "properties.backgroundImage.sizeAlwaysFill",
},
],
change: (data) => {
if (propertyResolver.getValue(data, "style.background.position"))
data.style.background.position = styleDefaults.BGIMAGE_POSITION;
},
show: (data) =>
propertyResolver.getValue(data, "style.background.mode") === "media" &&
!!propertyResolver.getValue(data, "style.background.url.qStaticContentUrlDef.qUrl"),
},
position: {
component: "position-grid",
ref: "style.background.position",
translation: "properties.backgroundImage.position",
defaultValue: styleDefaults.BGIMAGE_POSITION,
show: (data) =>
propertyResolver.getValue(data, "style.background.mode") === "media" &&
propertyResolver.getValue(data, "style.background.url.qStaticContentUrlDef.qUrl") &&
propertyResolver.getValue(data, "style.background.size") !== "stretchFit",
currentSizeRef: "style.background.size",
},
},
},
},
},
backgroundBorder: {
component: "panel-section",
translation: "properties.border",
items: {
backgroundBorderItem: {
items: {
useBorder: {
type: "boolean",
component: "switch",
ref: "style.border.useBorder",
translation: "properties.border.use",
defaultValue: false,
options: toggleOptions,
},
borderRadius: {
type: "number",
component: "slider",
ref: "style.border.radius",
translation: "properties.border.radius",
min: 0,
max: 1,
step: 0.01,
show: (data) => propertyResolver.getValue(data, "style.border.useBorder"),
},
borderWidth: {
type: "number",
component: "slider",
ref: "style.border.width",
translation: "properties.border.width",
min: 0,
max: 0.5,
step: 0.005,
show: (data) => propertyResolver.getValue(data, "style.border.useBorder"),
},
colorDropdown: {
type: "string",
component: "dropdown",
ref: "style.border.useColorExpression",
translation: "properties.border.color",
options: colorOptions,
show: (data) => propertyResolver.getValue(data, "style.border.useBorder"),
},
colorPicker: {
type: "object",
component: "color-picker",
ref: "style.border.color",
translation: "properties.color",
defaultValue: styleDefaults.COLOR,
disableNone: false,
dualOutput: true,
show: (data) =>
propertyResolver.getValue(data, "style.border.useBorder") &&
!propertyResolver.getValue(data, "style.border.useColorExpression"),
},
colorExpression: {
type: "string",
component: "input-field-expression",
ref: "style.border.colorExpression",
translation: "Common.Expression",
show: (data) =>
propertyResolver.getValue(data, "style.border.useBorder") &&
propertyResolver.getValue(data, "style.border.useColorExpression"),
expression: "optional",
},
},
},
},
},
},
};
};
export const getStylingPanelDefinition = (opt) => ({
type: "items",
grouped: false,
translation: "properties.presentation",
items: {
styleEditor: {
component: "styling-panel",
chartTitle: "Object.ActionButton",
translation: "LayerStyleEditor.component.styling",
subtitle: "LayerStyleEditor.component.styling",
ref: "components",
useGeneral: true,
useBackground: true,
...getStyleEditorDefinition(opt),
},
},
});