diff --git a/accessibilityTests/helper.ts b/accessibilityTests/helper.ts new file mode 100644 index 000000000..35b142763 --- /dev/null +++ b/accessibilityTests/helper.ts @@ -0,0 +1,36 @@ +import { Page } from "@playwright/test"; +import { RunOptions } from "axe-core"; + +export const FLOAT_PRECISION = 0.01; + +// https://www.deque.com/axe/core-documentation/api-documentation/#overview +export const axeTags = ["wcag2a", "wcag2aa", "wcag21a", "wcag21aa", "best-practice", "section508", "wcag412"]; + +export const axeOptions: RunOptions = { + runOnly: { + type: "tag", + values: axeTags + }, + rules: { + //https://github.com/dequelabs/axe-core/blob/develop/doc/rule-descriptions.md + "color-contrast": { + enabled: false + }, + "document-title": { + enabled: false + }, + "landmark-one-main": { + enabled: false + }, + "page-has-heading-one": { + enabled: false + }, + "region": { + enabled: false + } + } +}; + +export function getListItemByText(page, text) { + return page.getByRole("option", { name: text, exact: true }); +} \ No newline at end of file diff --git a/accessibilityTests/matrixes.spec.ts b/accessibilityTests/matrixes.spec.ts new file mode 100644 index 000000000..10faef424 --- /dev/null +++ b/accessibilityTests/matrixes.spec.ts @@ -0,0 +1,108 @@ +import { axeOptions, getListItemByText } from "./helper"; +import { checkA11y, injectAxe } from "axe-playwright"; +import { test } from "@playwright/test"; + +test.describe("Matrixes visualizer", () => { + test.beforeEach(async ({ page }) => { + await page.goto("http://localhost:8080/examples/matrixes.html"); + await page.waitForLoadState("networkidle"); + await injectAxe(page); + }); + + test("matrix single", async ({ page }) => { + const axeContext = "#summaryContainer"; + const questionTitleSelector = page.locator("h3").filter({ hasText: "What is your perception of these brands?" }); + const questionVisualizerSelector = questionTitleSelector.locator("..").locator(".."); + questionVisualizerSelector.scrollIntoViewIfNeeded(); + + const chartTypeSelector = questionVisualizerSelector.locator(".sa-dropdown").first(); + const chartContentSelector = questionVisualizerSelector.locator(".sa-visualizer__content"); + await checkA11y(page, axeContext, { axeOptions }); + + await chartTypeSelector.click(); + await getListItemByText(page, "Stacked Bar").click(); + await checkA11y(page, axeContext, { axeOptions }); + + await chartTypeSelector.click(); + await getListItemByText(page, "Pie").click(); + await checkA11y(page, axeContext, { axeOptions }); + + await chartTypeSelector.click(); + await getListItemByText(page, "Doughnut").click(); + await checkA11y(page, axeContext, { axeOptions }); + + const transposeButtonSelector = questionVisualizerSelector.locator(".sa-toolbar__button").filter({ hasText: /^Per Columns$/ }); + await transposeButtonSelector.click(); + + await chartTypeSelector.click(); + await getListItemByText(page, "Bar").click(); + await checkA11y(page, axeContext, { axeOptions }); + + await chartTypeSelector.click(); + await getListItemByText(page, "Stacked Bar").click(); + await checkA11y(page, axeContext, { axeOptions }); + + await chartTypeSelector.click(); + await getListItemByText(page, "Pie").click(); + await checkA11y(page, axeContext, { axeOptions }); + + await chartTypeSelector.click(); + await getListItemByText(page, "Doughnut").click(); + await checkA11y(page, axeContext, { axeOptions }); + }); + + test("matrixdropdown simple", async ({ page }) => { + const axeContext = "#summaryContainer"; + const questionTitleSelector = page.locator("h3").filter({ hasText: "What do you feel about these brands?" }); + const questionVisualizerSelector = questionTitleSelector.locator("..").locator(".."); + questionVisualizerSelector.scrollIntoViewIfNeeded(); + + const column1TitleSelector = page.locator("h3").filter({ hasText: "My Opinion" }); + const column1VisualizerSelector = column1TitleSelector.locator("..").locator(".."); + column1VisualizerSelector.scrollIntoViewIfNeeded(); + + const chartCol1TypeSelector = column1VisualizerSelector.locator(".sa-dropdown").nth(1); + const chartCol1ContentSelector = column1VisualizerSelector.locator(".sa-visualizer__content").nth(1); + await checkA11y(page, axeContext, { axeOptions }); + + await chartCol1TypeSelector.click(); + await getListItemByText(page, "Vertical Bar").click(); + await checkA11y(page, axeContext, { axeOptions }); + + await chartCol1TypeSelector.click(); + await getListItemByText(page, "Pie").click(); + await checkA11y(page, axeContext, { axeOptions }); + + await chartCol1TypeSelector.click(); + await getListItemByText(page, "Doughnut").click(); + await checkA11y(page, axeContext, { axeOptions }); + + await chartCol1TypeSelector.click(); + await getListItemByText(page, "Stacked Bar").click(); + await checkA11y(page, axeContext, { axeOptions }); + + const transposeButtonSelector = column1VisualizerSelector.locator(".sa-toolbar__button").filter({ hasText: /^Per Columns$/ }); + await transposeButtonSelector.click(); + + await chartCol1TypeSelector.click(); + await getListItemByText(page, "Bar").click(); + await checkA11y(page, axeContext, { axeOptions }); + + await chartCol1TypeSelector.click(); + await getListItemByText(page, "Vertical Bar").click(); + await checkA11y(page, axeContext, { axeOptions }); + + await chartCol1TypeSelector.click(); + await getListItemByText(page, "Pie").click(); + await checkA11y(page, axeContext, { axeOptions }); + + await chartCol1TypeSelector.click(); + await getListItemByText(page, "Doughnut").click(); + await checkA11y(page, axeContext, { axeOptions }); + + await chartCol1TypeSelector.click(); + await getListItemByText(page, "Stacked Bar").click(); + await checkA11y(page, axeContext, { axeOptions }); + }); + +}); \ No newline at end of file diff --git a/accessibilityTests/misc.spec.ts b/accessibilityTests/misc.spec.ts new file mode 100644 index 000000000..fb67a6d0e --- /dev/null +++ b/accessibilityTests/misc.spec.ts @@ -0,0 +1,70 @@ +import { axeOptions, getListItemByText } from "./helper"; +import { checkA11y, injectAxe } from "axe-playwright"; +import { test } from "@playwright/test"; + +test.describe("Miscellaneous cases", () => { + test.beforeEach(async ({ page }) => { + }); + + test("matrix one row", async ({ page }) => { + await page.goto("http://localhost:8080/examples/matrix-one-row.html"); + await injectAxe(page); + await page.setViewportSize({ width: 800, height: 1000 }); + const axeContext = "#summaryContainer"; + + const questionTitleSelector = page.locator("h3").filter({ hasText: "Please indicate if you agree or disagree with the following statements" }); + const questionVisualizerSelector = questionTitleSelector.locator("..").locator(".."); + questionVisualizerSelector.scrollIntoViewIfNeeded(); + + const chartTypeSelector = questionVisualizerSelector.locator(".sa-dropdown").first(); + const chartContentSelector = questionVisualizerSelector.locator(".sa-visualizer__content"); + + await checkA11y(page, axeContext, { axeOptions }); + + await chartTypeSelector.click(); + await getListItemByText(page, "Pie").click(); + await checkA11y(page, axeContext, { axeOptions }); + + const transposeButtonSelector = questionVisualizerSelector.locator(".sa-toolbar__button").filter({ hasText: /^Per Columns$/ }); + await transposeButtonSelector.click(); + + await chartTypeSelector.click(); + await getListItemByText(page, "Bar").click(); + await checkA11y(page, axeContext, { axeOptions }); + + await chartTypeSelector.click(); + await getListItemByText(page, "Pie").click(); + await checkA11y(page, axeContext, { axeOptions }); + }); + + test("matrix dropdown grouped", async ({ page }) => { + await page.goto("http://localhost:8080/examples/matrixdropdown-grouped.html"); + await injectAxe(page); + await page.setViewportSize({ width: 800, height: 1000 }); + + const axeContext = "#summaryContainer"; + const questionTitleSelector = page.locator("h3").filter({ hasText: "Please select the top 3 processes that you perceived as most difficult or troublesome." }); + const questionVisualizerSelector = questionTitleSelector.locator("..").locator(".."); + questionVisualizerSelector.scrollIntoViewIfNeeded(); + + const chartTypeSelector = questionVisualizerSelector.locator(".sa-dropdown").first(); + const chartContentSelector = questionVisualizerSelector.locator(".sa-visualizer__content"); + + await checkA11y(page, axeContext, { axeOptions }); + + await chartTypeSelector.click(); + await getListItemByText(page, "Bar").click(); + await checkA11y(page, axeContext, { axeOptions }); + + const transposeButtonSelector = questionVisualizerSelector.locator(".sa-toolbar__button").filter({ hasText: /^Per Columns$/ }); + await transposeButtonSelector.click(); + + await chartTypeSelector.click(); + await getListItemByText(page, "Stacked Bar").click(); + await checkA11y(page, axeContext, { axeOptions }); + + await chartTypeSelector.click(); + await getListItemByText(page, "Bar").click(); + await checkA11y(page, axeContext, { axeOptions }); + }); +}); \ No newline at end of file diff --git a/accessibilityTests/pivot.spec.ts b/accessibilityTests/pivot.spec.ts new file mode 100644 index 000000000..651fece72 --- /dev/null +++ b/accessibilityTests/pivot.spec.ts @@ -0,0 +1,42 @@ +import { axeOptions, getListItemByText } from "./helper"; +import { checkA11y, injectAxe } from "axe-playwright"; +import { test } from "@playwright/test"; + +test.describe("Pivot chart", () => { + test.beforeEach(async ({ page }) => { + await page.goto("http://localhost:8080/examples/pivot.html"); + await injectAxe(page); + await page.setViewportSize({ width: 1000, height: 800 }); + }); + + test("simple cases", async ({ page }) => { + const axeContext = "#pivotContainer"; + const xAxisSelector = page.locator(".sa-dropdown-header").nth(1); + const yAxisSelector = page.locator(".sa-dropdown-header").nth(2); + await checkA11y(page, axeContext, { axeOptions }); + + await yAxisSelector.click(); + await getListItemByText(page, "Item kind").click(); + await checkA11y(page, axeContext, { axeOptions }); + await yAxisSelector.click(); + await getListItemByText(page, "Bill amount").click(); + await checkA11y(page, axeContext, { axeOptions }); + await xAxisSelector.click(); + await getListItemByText(page, "Item kind").click(); + await yAxisSelector.click(); + await getListItemByText(page, "Gender").click(); + await checkA11y(page, axeContext, { axeOptions }); + await yAxisSelector.click(); + await getListItemByText(page, "Bill amount").click(); + await checkA11y(page, axeContext, { axeOptions }); + await xAxisSelector.click(); + await getListItemByText(page, "Bill amount").click(); + await yAxisSelector.click(); + await getListItemByText(page, "Gender").click(); + await checkA11y(page, axeContext, { axeOptions }); + await yAxisSelector.click(); + await getListItemByText(page, "Item kind").click(); + await checkA11y(page, axeContext, { axeOptions }); + }); + +}); \ No newline at end of file diff --git a/accessibilityTests/summary.spec.ts b/accessibilityTests/summary.spec.ts new file mode 100644 index 000000000..00c36e6de --- /dev/null +++ b/accessibilityTests/summary.spec.ts @@ -0,0 +1,122 @@ +import { axeOptions, getListItemByText } from "./helper"; +import { checkA11y, injectAxe } from "axe-playwright"; +import { test } from "@playwright/test"; + +test.describe("Summary common", () => { + test.beforeEach(async ({ page }) => { + await page.goto("http://localhost:8080/examples/summary.html"); + await injectAxe(page); + await page.setViewportSize({ width: 800, height: 1000 }); + }); + + test("matrix simple cases", async ({ page }) => { + const axeContext = "#summaryContainer"; + const questionTitleSelector = page.locator("h3").filter({ hasText: "Please indicate if you agree or disagree with the following statements" }); + const questionVisualizerSelector = questionTitleSelector.locator("..").locator(".."); + questionVisualizerSelector.scrollIntoViewIfNeeded(); + + const chartTypeSelector = questionVisualizerSelector.locator(".sa-dropdown").first(); + const chartContentSelector = questionVisualizerSelector.locator(".sa-visualizer__content"); + await checkA11y(page, axeContext, { axeOptions }); + + await chartTypeSelector.click(); + await getListItemByText(page, "Stacked Bar").click(); + await checkA11y(page, axeContext, { axeOptions }); + + await chartTypeSelector.click(); + await getListItemByText(page, "Pie").click(); + await checkA11y(page, axeContext, { axeOptions }); + + await chartTypeSelector.click(); + await getListItemByText(page, "Doughnut").click(); + await checkA11y(page, axeContext, { axeOptions }); + }); + + test("boolean simple cases", async ({ page }) => { + const axeContext = "#summaryContainer"; + const questionTitleSelector = page.locator("h3").filter({ hasText: "Please answer the question" }); + const questionVisualizerSelector = questionTitleSelector.locator("..").locator(".."); + questionVisualizerSelector.scrollIntoViewIfNeeded(); + + const chartTypeSelector = questionVisualizerSelector.locator(".sa-dropdown").first(); + const chartContentSelector = questionVisualizerSelector.locator(".sa-visualizer__content"); + await checkA11y(page, axeContext, { axeOptions }); + + await chartTypeSelector.click(); + await getListItemByText(page, "Bar").click(); + await checkA11y(page, axeContext, { axeOptions }); + + await chartTypeSelector.click(); + await getListItemByText(page, "Doughnut").click(); + await checkA11y(page, axeContext, { axeOptions }); + }); + + test("select simple cases", async ({ page }) => { + const axeContext = "#summaryContainer"; + const questionTitleSelector = page.locator("h3").filter({ hasText: "Which of the following best describes you or your organization?" }); + const questionVisualizerSelector = questionTitleSelector.locator("..").locator(".."); + questionVisualizerSelector.scrollIntoViewIfNeeded(); + + const visualizerSelector = questionVisualizerSelector.locator(".sa-dropdown").first(); + const chartTypeSelector = questionVisualizerSelector.locator(".sa-dropdown").nth(1); + const chartContentSelector = questionVisualizerSelector.locator(".sa-visualizer__content").nth(1); + await checkA11y(page, axeContext, { axeOptions }); + + await chartTypeSelector.click(); + await getListItemByText(page, "Vertical Bar").click(); + await checkA11y(page, axeContext, { axeOptions }); + + await chartTypeSelector.click(); + await getListItemByText(page, "Pie").click(); + await checkA11y(page, axeContext, { axeOptions }); + + await chartTypeSelector.click(); + await getListItemByText(page, "Doughnut").click(); + await checkA11y(page, axeContext, { axeOptions }); + + await visualizerSelector.click(); + await getListItemByText(page, "Table").click(); + await checkA11y(page, axeContext, { axeOptions }); + }); + + test("simple cases", async ({ page }) => { + const axeContext = "#summaryContainer"; + const questionTitleSelector = page.locator("h3").filter({ hasText: "How likely are you to recommend SurveyJS to a friend or colleague?" }); + const questionVisualizerSelector = questionTitleSelector.locator("..").locator(".."); + questionVisualizerSelector.scrollIntoViewIfNeeded(); + + const visualizerSelector = questionVisualizerSelector.locator(".sa-dropdown").first(); + const chartTypeSelector = questionVisualizerSelector.locator(".sa-dropdown").nth(1); + const chartContentSelector = questionVisualizerSelector.locator(".sa-visualizer__content").nth(1); + await checkA11y(page, axeContext, { axeOptions }); + + await chartTypeSelector.click(); + await getListItemByText(page, "Bar").click(); + await checkA11y(page, axeContext, { axeOptions }); + + await visualizerSelector.click(); + await getListItemByText(page, "Average").click(); + + const gaugeTypeSelector = questionVisualizerSelector.locator(".sa-dropdown").nth(1); + await checkA11y(page, axeContext, { axeOptions }); + + await gaugeTypeSelector.click(); + await getListItemByText(page, "Bullet").click(); + await checkA11y(page, axeContext, { axeOptions }); + }); + + test("text simple cases", async ({ page }) => { + const axeContext = "#summaryContainer"; + const questionTitleSelector = page.locator("h3").filter({ hasText: "What's your favorite functionality / add-on?" }); + const questionVisualizerSelector = questionTitleSelector.locator("..").locator(".."); + questionVisualizerSelector.scrollIntoViewIfNeeded(); + + const visualizerTypeSelector = questionVisualizerSelector.locator(".sa-dropdown").first(); + const chartContentSelector = questionVisualizerSelector.locator(".sa-visualizer__content").nth(1); + await checkA11y(page, axeContext, { axeOptions }); + + await visualizerTypeSelector.click(); + await getListItemByText(page, "Texts in table").click(); + await checkA11y(page, axeContext, { axeOptions }); + }); +}); \ No newline at end of file diff --git a/e2e/declarative.spec.ts b/e2e/declarative.spec.ts new file mode 100644 index 000000000..3651d47ba --- /dev/null +++ b/e2e/declarative.spec.ts @@ -0,0 +1,20 @@ +import { test, expect } from "@playwright/test"; +import { compareScreenshot } from "./helper"; + +process.env.SNAPSHOT_SUFFIX = undefined; +process.env.SNAPSHOT_SUFFIX = ""; + +test.describe("Declarative common", () => { + test.beforeEach(async ({ page }) => { + await page.goto("http://localhost:8080/examples/declarative.html"); + await page.setViewportSize({ width: 800, height: 1000 }); + }); + + test("Total answers count visualizer", async ({ page }) => { + const questionTitleSelector = page.locator("h3").filter({ hasText: "Total answers count - Card" }); + await expect(questionTitleSelector).toBeVisible(); + const questionVisualizerSelector = questionTitleSelector.locator("..").locator("..").first(); + + await compareScreenshot(page, questionVisualizerSelector, "total-answer-count.png"); + }); +}); diff --git a/e2e/declarative.spec.ts-snapshots/total-answer-count.png b/e2e/declarative.spec.ts-snapshots/total-answer-count.png new file mode 100644 index 000000000..6e1979e78 Binary files /dev/null and b/e2e/declarative.spec.ts-snapshots/total-answer-count.png differ diff --git a/e2e/helper.ts b/e2e/helper.ts index 1bb8b706d..45d67dd08 100644 --- a/e2e/helper.ts +++ b/e2e/helper.ts @@ -4,6 +4,17 @@ import { expect, test as baseTest } from "@playwright/test"; export const url_summary = "http://127.0.0.1:8080/examples/summarytest.html"; export const url_tabulator = "http://127.0.0.1:8080/examples/tabulator.html"; +export const testConfigs = [ + { + name: "plotly", + suffix: "", + }, + { + name: "apexcharts", + suffix: "_apexcharts", + }, +]; + export const initSummary = async (page: Page, json: any, data, options, elements?, state?) => { await page.evaluate(([json, data, options, elements, state]) => { var model = new (window as any).Survey.SurveyModel(json); @@ -70,6 +81,19 @@ export async function getYAxisValues(page) { }); } +export function getListItemByText(page, text) { + return page.getByRole("option", { name: text, exact: true }); +} + +export async function resetFocusToBody(page: Page): Promise { + await page.evaluate(() => { + if (!!document.activeElement) { + document.activeElement.blur(); + } + document.body.focus(); + }); +} + // export const getYAxisValues = ClientFunction(() => { // var yValues = []; // document.querySelectorAll(".yaxislayer-above g.ytick text").forEach((el) => { @@ -78,11 +102,19 @@ export async function getYAxisValues(page) { // return yValues; // }); -export async function compareScreenshot(page: Page, elementSelector: string | Locator | undefined, screenshotName: string, elementIndex = 0): Promise { +export async function compareScreenshot(page: Page, elementSelector: string | Locator | undefined, screenshotName: string, mask?: Array): Promise { await page.addStyleTag({ content: "textarea::-webkit-resizer { visibility: hidden !important; }" }); + const options = { + timeout: 10000 + }; + if (mask) { + (options as any).mask = mask; + (options as any).maskColor = "#000000"; + } + if (!!elementSelector) { let elementLocator: Locator; if(typeof elementSelector == "string") { @@ -91,14 +123,11 @@ export async function compareScreenshot(page: Page, elementSelector: string | Lo elementLocator = elementSelector; } const element = elementLocator.filter({ visible: true }); - await expect.soft(element.nth(elementIndex)).toBeVisible(); - await expect.soft(element.nth(elementIndex)).toHaveScreenshot(screenshotName, { - timeout: 10000 - }); + element.scrollIntoViewIfNeeded(); + await expect.soft(element.nth(0)).toBeVisible(); + await expect.soft(element.nth(0)).toHaveScreenshot(screenshotName, options); } else { - await expect.soft(page).toHaveScreenshot(screenshotName, { - timeout: 10000 - }); + await expect.soft(page).toHaveScreenshot(screenshotName, options); } } diff --git a/e2e/matrixes.spec.ts b/e2e/matrixes.spec.ts index 484116e50..9acf8be99 100644 --- a/e2e/matrixes.spec.ts +++ b/e2e/matrixes.spec.ts @@ -1,103 +1,124 @@ import { test, expect } from "@playwright/test"; -import { compareScreenshot } from "./helper"; +import { compareScreenshot, getListItemByText, testConfigs } from "./helper"; + +for (const config of testConfigs) { + process.env.SNAPSHOT_SUFFIX = undefined; + process.env.SNAPSHOT_SUFFIX = config.suffix; + + test.describe(`Matrixes visualizer ${config.name}`, () => { + test.beforeEach(async ({ page }) => { + await page.goto(`http://localhost:8080/examples/matrixes${config.suffix}.html`); + await page.setViewportSize({ width: 800, height: 1000 }); + }); + + test("matrix single", async ({ page }) => { + const questionTitleSelector = page.locator("h3").filter({ hasText: "What is your perception of these brands?" }); + await expect(questionTitleSelector).toBeVisible(); + const questionVisualizerSelector = questionTitleSelector.locator("..").locator(".."); + questionVisualizerSelector.scrollIntoViewIfNeeded(); + + const chartTypeSelector = questionVisualizerSelector.locator(".sa-dropdown").first(); + await expect(chartTypeSelector).toBeVisible(); + const chartContentSelector = questionVisualizerSelector.locator(".sa-visualizer__content"); + await expect(chartContentSelector).toBeVisible(); + + await expect(chartTypeSelector.locator(".sa-dropdown-header-text")).toHaveText("Bar"); + await compareScreenshot(page, chartContentSelector, "matrix-single-bar.png"); + + await chartTypeSelector.click(); + await getListItemByText(page, "Stacked Bar").click(); + await compareScreenshot(page, chartContentSelector, "matrix-single-stackedbar.png"); + + await chartTypeSelector.click(); + await getListItemByText(page, "Pie").click(); + await compareScreenshot(page, chartContentSelector, "matrix-single-pie.png"); + + await chartTypeSelector.click(); + await getListItemByText(page, "Doughnut").click(); + await compareScreenshot(page, chartContentSelector, "matrix-single-doughnut.png"); + + const transposeButtonSelector = questionVisualizerSelector.locator(".sa-toolbar__button").filter({ hasText: /^Per Columns$/ }); + await expect(transposeButtonSelector).toBeVisible(); + await transposeButtonSelector.click(); + await expect(questionVisualizerSelector.locator(".sa-toolbar__button").filter({ hasText: /^Per Values$/ })).toBeVisible(); + + await chartTypeSelector.click(); + await getListItemByText(page, "Bar").click(); + await compareScreenshot(page, chartContentSelector, "matrix-single-bar-per-values.png"); + + await chartTypeSelector.click(); + await getListItemByText(page, "Stacked Bar").click(); + await compareScreenshot(page, chartContentSelector, "matrix-single-stackedbar-per-values.png"); + + await chartTypeSelector.click(); + await getListItemByText(page, "Pie").click(); + await compareScreenshot(page, chartContentSelector, "matrix-single-pie-per-values.png"); + + await chartTypeSelector.click(); + await getListItemByText(page, "Doughnut").click(); + await compareScreenshot(page, chartContentSelector, "matrix-single-doughnut-per-values.png"); + }); + + test("matrixdropdown simple", async ({ page }) => { + const questionTitleSelector = page.locator("h3").filter({ hasText: "What do you feel about these brands?" }); + await expect(questionTitleSelector).toBeVisible(); + const questionVisualizerSelector = questionTitleSelector.locator("..").locator(".."); + questionVisualizerSelector.scrollIntoViewIfNeeded(); + + const column1TitleSelector = page.locator("h3").filter({ hasText: "My Opinion" }); + await expect(column1TitleSelector).toBeVisible(); + const column1VisualizerSelector = column1TitleSelector.locator("..").locator(".."); + column1VisualizerSelector.scrollIntoViewIfNeeded(); + + const chartCol1TypeSelector = column1VisualizerSelector.locator(".sa-dropdown").nth(1); + await expect(chartCol1TypeSelector).toBeVisible(); + const chartCol1ContentSelector = column1VisualizerSelector.locator(".sa-visualizer__content"); + await expect(chartCol1ContentSelector).toBeVisible(); + + await expect(chartCol1TypeSelector.locator(".sa-dropdown-header-text")).toHaveText("Bar"); + await compareScreenshot(page, chartCol1ContentSelector, "matrixdropdown-simple-bar.png"); + + await chartCol1TypeSelector.click(); + await getListItemByText(page, "Vertical Bar").click(); + await compareScreenshot(page, chartCol1ContentSelector, "matrixdropdown-simple-vbar.png"); + + await chartCol1TypeSelector.click(); + await getListItemByText(page, "Pie").click(); + await compareScreenshot(page, chartCol1ContentSelector, "matrixdropdown-simple-pie.png"); + + await chartCol1TypeSelector.click(); + await getListItemByText(page, "Doughnut").click(); + await compareScreenshot(page, chartCol1ContentSelector, "matrixdropdown-simple-doughnut.png"); + + await chartCol1TypeSelector.click(); + await getListItemByText(page, "Stacked Bar").click(); + await compareScreenshot(page, chartCol1ContentSelector, "matrixdropdown-simple-stackedbar.png"); + + const transposeButtonSelector = column1VisualizerSelector.locator(".sa-toolbar__button").filter({ hasText: /^Per Columns$/ }); + await expect(transposeButtonSelector).toBeVisible(); + await transposeButtonSelector.click(); + await expect(column1VisualizerSelector.locator(".sa-toolbar__button").filter({ hasText: /^Per Values$/ })).toBeVisible(); + + await chartCol1TypeSelector.click(); + await getListItemByText(page, "Bar").click(); + await compareScreenshot(page, chartCol1ContentSelector, "matrixdropdown-simple-bar-per-values.png"); + + await chartCol1TypeSelector.click(); + await getListItemByText(page, "Vertical Bar").click(); + await compareScreenshot(page, chartCol1ContentSelector, "matrixdropdown-simple-vbar-per-values.png"); + + await chartCol1TypeSelector.click(); + await getListItemByText(page, "Pie").click(); + await compareScreenshot(page, chartCol1ContentSelector, "matrixdropdown-simple-pie-per-values.png"); + + await chartCol1TypeSelector.click(); + await getListItemByText(page, "Doughnut").click(); + await compareScreenshot(page, chartCol1ContentSelector, "matrixdropdown-simple-doughnut-per-values.png"); + + await chartCol1TypeSelector.click(); + await getListItemByText(page, "Stacked Bar").click(); + await compareScreenshot(page, chartCol1ContentSelector, "matrixdropdown-simple-stackedbar-per-values.png"); + }); -test.describe("Matrixes visualizer", () => { - test.beforeEach(async ({ page }) => { - await page.goto("http://localhost:8080/examples/matrixes.html"); - await page.setViewportSize({ width: 800, height: 1000 }); }); - - test("matrix single", async ({ page }) => { - const questionTitleSelector = page.locator("h3").filter({ hasText: "What is your perception of these brands?" }); - await expect(questionTitleSelector).toBeVisible(); - const questionVisualizerSelector = questionTitleSelector.locator("..").locator(".."); - questionVisualizerSelector.scrollIntoViewIfNeeded(); - - const chartTypeSelector = questionVisualizerSelector.locator("select").filter({ hasText: /^BarStacked BarPieDoughnut$/ }); - await expect(chartTypeSelector).toBeVisible(); - const chartContentSelector = questionVisualizerSelector.locator(".sa-visualizer__content"); - await expect(chartContentSelector).toBeVisible(); - - await expect(chartTypeSelector).toHaveValue("bar"); - await compareScreenshot(page, chartContentSelector, "matrix-single-bar.png"); - - await chartTypeSelector.selectOption("stackedbar"); - await compareScreenshot(page, chartContentSelector, "matrix-single-stackedbar.png"); - - await chartTypeSelector.selectOption("pie"); - await compareScreenshot(page, chartContentSelector, "matrix-single-pie.png"); - - await chartTypeSelector.selectOption("doughnut"); - await compareScreenshot(page, chartContentSelector, "matrix-single-doughnut.png"); - - const transposeButtonSelector = questionVisualizerSelector.locator(".sa-toolbar__button").filter({ hasText: /^Per Columns$/ }); - await expect(transposeButtonSelector).toBeVisible(); - await transposeButtonSelector.click(); - await expect(questionVisualizerSelector.locator(".sa-toolbar__button").filter({ hasText: /^Per Values$/ })).toBeVisible(); - - await chartTypeSelector.selectOption("bar"); - await compareScreenshot(page, chartContentSelector, "matrix-single-bar-per-values.png"); - - await chartTypeSelector.selectOption("stackedbar"); - await compareScreenshot(page, chartContentSelector, "matrix-single-stackedbar-per-values.png"); - - await chartTypeSelector.selectOption("pie"); - await compareScreenshot(page, chartContentSelector, "matrix-single-pie-per-values.png"); - - await chartTypeSelector.selectOption("doughnut"); - await compareScreenshot(page, chartContentSelector, "matrix-single-doughnut-per-values.png"); - }); - - test("matrixdropdown simple", async ({ page }) => { - const questionTitleSelector = page.locator("h3").filter({ hasText: "What do you feel about these brands?" }); - await expect(questionTitleSelector).toBeVisible(); - const questionVisualizerSelector = questionTitleSelector.locator("..").locator(".."); - questionVisualizerSelector.scrollIntoViewIfNeeded(); - - const column1TitleSelector = page.locator("h3").filter({ hasText: "My Opinion" }); - await expect(column1TitleSelector).toBeVisible(); - const column1VisualizerSelector = column1TitleSelector.locator("..").locator(".."); - column1VisualizerSelector.scrollIntoViewIfNeeded(); - - const chartCol1TypeSelector = column1VisualizerSelector.locator("select").filter({ hasText: /^BarVertical BarPieDoughnutStacked Bar$/ }); - await expect(chartCol1TypeSelector).toBeVisible(); - const chartCol1ContentSelector = column1VisualizerSelector.locator(".sa-visualizer__content").nth(1); - await expect(chartCol1ContentSelector).toBeVisible(); - - await expect(chartCol1TypeSelector).toHaveValue("bar"); - await compareScreenshot(page, chartCol1ContentSelector, "matrixdropdown-simple-bar.png"); - - await chartCol1TypeSelector.selectOption("vbar"); - await compareScreenshot(page, chartCol1ContentSelector, "matrixdropdown-simple-vbar.png"); - - await chartCol1TypeSelector.selectOption("pie"); - await compareScreenshot(page, chartCol1ContentSelector, "matrixdropdown-simple-pie.png"); - - await chartCol1TypeSelector.selectOption("doughnut"); - await compareScreenshot(page, chartCol1ContentSelector, "matrixdropdown-simple-doughnut.png"); - - await chartCol1TypeSelector.selectOption("stackedbar"); - await compareScreenshot(page, chartCol1ContentSelector, "matrixdropdown-simple-stackedbar.png"); - - const transposeButtonSelector = column1VisualizerSelector.locator(".sa-toolbar__button").filter({ hasText: /^Per Columns$/ }); - await expect(transposeButtonSelector).toBeVisible(); - await transposeButtonSelector.click(); - await expect(column1VisualizerSelector.locator(".sa-toolbar__button").filter({ hasText: /^Per Values$/ })).toBeVisible(); - - await chartCol1TypeSelector.selectOption("bar"); - await compareScreenshot(page, chartCol1ContentSelector, "matrixdropdown-simple-bar-per-values.png"); - - await chartCol1TypeSelector.selectOption("vbar"); - await compareScreenshot(page, chartCol1ContentSelector, "matrixdropdown-simple-vbar-per-values.png"); - - await chartCol1TypeSelector.selectOption("pie"); - await compareScreenshot(page, chartCol1ContentSelector, "matrixdropdown-simple-pie-per-values.png"); - - await chartCol1TypeSelector.selectOption("doughnut"); - await compareScreenshot(page, chartCol1ContentSelector, "matrixdropdown-simple-doughnut-per-values.png"); - - await chartCol1TypeSelector.selectOption("stackedbar"); - await compareScreenshot(page, chartCol1ContentSelector, "matrixdropdown-simple-stackedbar-per-values.png"); - }); - -}); \ No newline at end of file +} \ No newline at end of file diff --git a/e2e/matrixes.spec.ts-snapshots/matrix-single-bar-per-values.png b/e2e/matrixes.spec.ts-snapshots/matrix-single-bar-per-values.png index 1cdf02836..657224398 100644 Binary files a/e2e/matrixes.spec.ts-snapshots/matrix-single-bar-per-values.png and b/e2e/matrixes.spec.ts-snapshots/matrix-single-bar-per-values.png differ diff --git a/e2e/matrixes.spec.ts-snapshots/matrix-single-bar.png b/e2e/matrixes.spec.ts-snapshots/matrix-single-bar.png index 586ea542f..2e83d66fa 100644 Binary files a/e2e/matrixes.spec.ts-snapshots/matrix-single-bar.png and b/e2e/matrixes.spec.ts-snapshots/matrix-single-bar.png differ diff --git a/e2e/matrixes.spec.ts-snapshots/matrix-single-doughnut-per-values.png b/e2e/matrixes.spec.ts-snapshots/matrix-single-doughnut-per-values.png index 4d21adc26..3744497a2 100644 Binary files a/e2e/matrixes.spec.ts-snapshots/matrix-single-doughnut-per-values.png and b/e2e/matrixes.spec.ts-snapshots/matrix-single-doughnut-per-values.png differ diff --git a/e2e/matrixes.spec.ts-snapshots/matrix-single-doughnut.png b/e2e/matrixes.spec.ts-snapshots/matrix-single-doughnut.png index 5d335f987..0bf500553 100644 Binary files a/e2e/matrixes.spec.ts-snapshots/matrix-single-doughnut.png and b/e2e/matrixes.spec.ts-snapshots/matrix-single-doughnut.png differ diff --git a/e2e/matrixes.spec.ts-snapshots/matrix-single-pie-per-values.png b/e2e/matrixes.spec.ts-snapshots/matrix-single-pie-per-values.png index f24d2f676..c5061bf4d 100644 Binary files a/e2e/matrixes.spec.ts-snapshots/matrix-single-pie-per-values.png and b/e2e/matrixes.spec.ts-snapshots/matrix-single-pie-per-values.png differ diff --git a/e2e/matrixes.spec.ts-snapshots/matrix-single-pie.png b/e2e/matrixes.spec.ts-snapshots/matrix-single-pie.png index e38277b2e..2cf679306 100644 Binary files a/e2e/matrixes.spec.ts-snapshots/matrix-single-pie.png and b/e2e/matrixes.spec.ts-snapshots/matrix-single-pie.png differ diff --git a/e2e/matrixes.spec.ts-snapshots/matrix-single-stackedbar-per-values.png b/e2e/matrixes.spec.ts-snapshots/matrix-single-stackedbar-per-values.png index c520ebfc1..b9c3810a1 100644 Binary files a/e2e/matrixes.spec.ts-snapshots/matrix-single-stackedbar-per-values.png and b/e2e/matrixes.spec.ts-snapshots/matrix-single-stackedbar-per-values.png differ diff --git a/e2e/matrixes.spec.ts-snapshots/matrix-single-stackedbar.png b/e2e/matrixes.spec.ts-snapshots/matrix-single-stackedbar.png index d4f8d677f..b15ec4112 100644 Binary files a/e2e/matrixes.spec.ts-snapshots/matrix-single-stackedbar.png and b/e2e/matrixes.spec.ts-snapshots/matrix-single-stackedbar.png differ diff --git a/e2e/matrixes.spec.ts-snapshots/matrixdropdown-simple-bar-per-values.png b/e2e/matrixes.spec.ts-snapshots/matrixdropdown-simple-bar-per-values.png index 0b2fa39ef..e068ad6c3 100644 Binary files a/e2e/matrixes.spec.ts-snapshots/matrixdropdown-simple-bar-per-values.png and b/e2e/matrixes.spec.ts-snapshots/matrixdropdown-simple-bar-per-values.png differ diff --git a/e2e/matrixes.spec.ts-snapshots/matrixdropdown-simple-bar.png b/e2e/matrixes.spec.ts-snapshots/matrixdropdown-simple-bar.png index 04ddbcb71..1980034bf 100644 Binary files a/e2e/matrixes.spec.ts-snapshots/matrixdropdown-simple-bar.png and b/e2e/matrixes.spec.ts-snapshots/matrixdropdown-simple-bar.png differ diff --git a/e2e/matrixes.spec.ts-snapshots/matrixdropdown-simple-doughnut-per-values.png b/e2e/matrixes.spec.ts-snapshots/matrixdropdown-simple-doughnut-per-values.png index 632fe7e56..686417435 100644 Binary files a/e2e/matrixes.spec.ts-snapshots/matrixdropdown-simple-doughnut-per-values.png and b/e2e/matrixes.spec.ts-snapshots/matrixdropdown-simple-doughnut-per-values.png differ diff --git a/e2e/matrixes.spec.ts-snapshots/matrixdropdown-simple-doughnut.png b/e2e/matrixes.spec.ts-snapshots/matrixdropdown-simple-doughnut.png index 9bf7bdc77..98e9ba4f6 100644 Binary files a/e2e/matrixes.spec.ts-snapshots/matrixdropdown-simple-doughnut.png and b/e2e/matrixes.spec.ts-snapshots/matrixdropdown-simple-doughnut.png differ diff --git a/e2e/matrixes.spec.ts-snapshots/matrixdropdown-simple-pie-per-values.png b/e2e/matrixes.spec.ts-snapshots/matrixdropdown-simple-pie-per-values.png index f9e931a59..b72a66ec7 100644 Binary files a/e2e/matrixes.spec.ts-snapshots/matrixdropdown-simple-pie-per-values.png and b/e2e/matrixes.spec.ts-snapshots/matrixdropdown-simple-pie-per-values.png differ diff --git a/e2e/matrixes.spec.ts-snapshots/matrixdropdown-simple-pie.png b/e2e/matrixes.spec.ts-snapshots/matrixdropdown-simple-pie.png index 3e836a4fe..fb67c075a 100644 Binary files a/e2e/matrixes.spec.ts-snapshots/matrixdropdown-simple-pie.png and b/e2e/matrixes.spec.ts-snapshots/matrixdropdown-simple-pie.png differ diff --git a/e2e/matrixes.spec.ts-snapshots/matrixdropdown-simple-stackedbar-per-values.png b/e2e/matrixes.spec.ts-snapshots/matrixdropdown-simple-stackedbar-per-values.png index c79a5ef1e..0e6a6d80e 100644 Binary files a/e2e/matrixes.spec.ts-snapshots/matrixdropdown-simple-stackedbar-per-values.png and b/e2e/matrixes.spec.ts-snapshots/matrixdropdown-simple-stackedbar-per-values.png differ diff --git a/e2e/matrixes.spec.ts-snapshots/matrixdropdown-simple-stackedbar.png b/e2e/matrixes.spec.ts-snapshots/matrixdropdown-simple-stackedbar.png index 45db2bdb5..c9cd376c3 100644 Binary files a/e2e/matrixes.spec.ts-snapshots/matrixdropdown-simple-stackedbar.png and b/e2e/matrixes.spec.ts-snapshots/matrixdropdown-simple-stackedbar.png differ diff --git a/e2e/matrixes.spec.ts-snapshots/matrixdropdown-simple-vbar-per-values.png b/e2e/matrixes.spec.ts-snapshots/matrixdropdown-simple-vbar-per-values.png index 0fc1007ef..a43085901 100644 Binary files a/e2e/matrixes.spec.ts-snapshots/matrixdropdown-simple-vbar-per-values.png and b/e2e/matrixes.spec.ts-snapshots/matrixdropdown-simple-vbar-per-values.png differ diff --git a/e2e/matrixes.spec.ts-snapshots/matrixdropdown-simple-vbar.png b/e2e/matrixes.spec.ts-snapshots/matrixdropdown-simple-vbar.png index 5b8157292..228cfd086 100644 Binary files a/e2e/matrixes.spec.ts-snapshots/matrixdropdown-simple-vbar.png and b/e2e/matrixes.spec.ts-snapshots/matrixdropdown-simple-vbar.png differ diff --git a/e2e/matrixes.spec.ts-snapshots_apexcharts/matrix-single-bar-per-values.png b/e2e/matrixes.spec.ts-snapshots_apexcharts/matrix-single-bar-per-values.png new file mode 100644 index 000000000..657224398 Binary files /dev/null and b/e2e/matrixes.spec.ts-snapshots_apexcharts/matrix-single-bar-per-values.png differ diff --git a/e2e/matrixes.spec.ts-snapshots_apexcharts/matrix-single-bar.png b/e2e/matrixes.spec.ts-snapshots_apexcharts/matrix-single-bar.png new file mode 100644 index 000000000..2e83d66fa Binary files /dev/null and b/e2e/matrixes.spec.ts-snapshots_apexcharts/matrix-single-bar.png differ diff --git a/e2e/matrixes.spec.ts-snapshots_apexcharts/matrix-single-doughnut-per-values.png b/e2e/matrixes.spec.ts-snapshots_apexcharts/matrix-single-doughnut-per-values.png new file mode 100644 index 000000000..3980075f2 Binary files /dev/null and b/e2e/matrixes.spec.ts-snapshots_apexcharts/matrix-single-doughnut-per-values.png differ diff --git a/e2e/matrixes.spec.ts-snapshots_apexcharts/matrix-single-doughnut.png b/e2e/matrixes.spec.ts-snapshots_apexcharts/matrix-single-doughnut.png new file mode 100644 index 000000000..61c81ed7e Binary files /dev/null and b/e2e/matrixes.spec.ts-snapshots_apexcharts/matrix-single-doughnut.png differ diff --git a/e2e/matrixes.spec.ts-snapshots_apexcharts/matrix-single-pie-per-values.png b/e2e/matrixes.spec.ts-snapshots_apexcharts/matrix-single-pie-per-values.png new file mode 100644 index 000000000..c48cfed48 Binary files /dev/null and b/e2e/matrixes.spec.ts-snapshots_apexcharts/matrix-single-pie-per-values.png differ diff --git a/e2e/matrixes.spec.ts-snapshots_apexcharts/matrix-single-pie.png b/e2e/matrixes.spec.ts-snapshots_apexcharts/matrix-single-pie.png new file mode 100644 index 000000000..2e010975b Binary files /dev/null and b/e2e/matrixes.spec.ts-snapshots_apexcharts/matrix-single-pie.png differ diff --git a/e2e/matrixes.spec.ts-snapshots_apexcharts/matrix-single-stackedbar-per-values.png b/e2e/matrixes.spec.ts-snapshots_apexcharts/matrix-single-stackedbar-per-values.png new file mode 100644 index 000000000..b9c3810a1 Binary files /dev/null and b/e2e/matrixes.spec.ts-snapshots_apexcharts/matrix-single-stackedbar-per-values.png differ diff --git a/e2e/matrixes.spec.ts-snapshots_apexcharts/matrix-single-stackedbar.png b/e2e/matrixes.spec.ts-snapshots_apexcharts/matrix-single-stackedbar.png new file mode 100644 index 000000000..b15ec4112 Binary files /dev/null and b/e2e/matrixes.spec.ts-snapshots_apexcharts/matrix-single-stackedbar.png differ diff --git a/e2e/matrixes.spec.ts-snapshots_apexcharts/matrixdropdown-simple-bar-per-values.png b/e2e/matrixes.spec.ts-snapshots_apexcharts/matrixdropdown-simple-bar-per-values.png new file mode 100644 index 000000000..e068ad6c3 Binary files /dev/null and b/e2e/matrixes.spec.ts-snapshots_apexcharts/matrixdropdown-simple-bar-per-values.png differ diff --git a/e2e/matrixes.spec.ts-snapshots_apexcharts/matrixdropdown-simple-bar.png b/e2e/matrixes.spec.ts-snapshots_apexcharts/matrixdropdown-simple-bar.png new file mode 100644 index 000000000..1980034bf Binary files /dev/null and b/e2e/matrixes.spec.ts-snapshots_apexcharts/matrixdropdown-simple-bar.png differ diff --git a/e2e/matrixes.spec.ts-snapshots_apexcharts/matrixdropdown-simple-doughnut-per-values.png b/e2e/matrixes.spec.ts-snapshots_apexcharts/matrixdropdown-simple-doughnut-per-values.png new file mode 100644 index 000000000..7c71779fb Binary files /dev/null and b/e2e/matrixes.spec.ts-snapshots_apexcharts/matrixdropdown-simple-doughnut-per-values.png differ diff --git a/e2e/matrixes.spec.ts-snapshots_apexcharts/matrixdropdown-simple-doughnut.png b/e2e/matrixes.spec.ts-snapshots_apexcharts/matrixdropdown-simple-doughnut.png new file mode 100644 index 000000000..c7d1eebb7 Binary files /dev/null and b/e2e/matrixes.spec.ts-snapshots_apexcharts/matrixdropdown-simple-doughnut.png differ diff --git a/e2e/matrixes.spec.ts-snapshots_apexcharts/matrixdropdown-simple-pie-per-values.png b/e2e/matrixes.spec.ts-snapshots_apexcharts/matrixdropdown-simple-pie-per-values.png new file mode 100644 index 000000000..b540809d9 Binary files /dev/null and b/e2e/matrixes.spec.ts-snapshots_apexcharts/matrixdropdown-simple-pie-per-values.png differ diff --git a/e2e/matrixes.spec.ts-snapshots_apexcharts/matrixdropdown-simple-pie.png b/e2e/matrixes.spec.ts-snapshots_apexcharts/matrixdropdown-simple-pie.png new file mode 100644 index 000000000..0b8f29311 Binary files /dev/null and b/e2e/matrixes.spec.ts-snapshots_apexcharts/matrixdropdown-simple-pie.png differ diff --git a/e2e/matrixes.spec.ts-snapshots_apexcharts/matrixdropdown-simple-stackedbar-per-values.png b/e2e/matrixes.spec.ts-snapshots_apexcharts/matrixdropdown-simple-stackedbar-per-values.png new file mode 100644 index 000000000..0e6a6d80e Binary files /dev/null and b/e2e/matrixes.spec.ts-snapshots_apexcharts/matrixdropdown-simple-stackedbar-per-values.png differ diff --git a/e2e/matrixes.spec.ts-snapshots_apexcharts/matrixdropdown-simple-stackedbar.png b/e2e/matrixes.spec.ts-snapshots_apexcharts/matrixdropdown-simple-stackedbar.png new file mode 100644 index 000000000..c9cd376c3 Binary files /dev/null and b/e2e/matrixes.spec.ts-snapshots_apexcharts/matrixdropdown-simple-stackedbar.png differ diff --git a/e2e/matrixes.spec.ts-snapshots_apexcharts/matrixdropdown-simple-vbar-per-values.png b/e2e/matrixes.spec.ts-snapshots_apexcharts/matrixdropdown-simple-vbar-per-values.png new file mode 100644 index 000000000..b6843e463 Binary files /dev/null and b/e2e/matrixes.spec.ts-snapshots_apexcharts/matrixdropdown-simple-vbar-per-values.png differ diff --git a/e2e/matrixes.spec.ts-snapshots_apexcharts/matrixdropdown-simple-vbar.png b/e2e/matrixes.spec.ts-snapshots_apexcharts/matrixdropdown-simple-vbar.png new file mode 100644 index 000000000..17b8321d4 Binary files /dev/null and b/e2e/matrixes.spec.ts-snapshots_apexcharts/matrixdropdown-simple-vbar.png differ diff --git a/e2e/misc.spec.ts b/e2e/misc.spec.ts index d0e09beba..95a9a0b27 100644 --- a/e2e/misc.spec.ts +++ b/e2e/misc.spec.ts @@ -1,69 +1,80 @@ import { test, expect } from "@playwright/test"; -import { compareScreenshot } from "./helper"; +import { compareScreenshot, getListItemByText, testConfigs } from "./helper"; -test.describe("Miscellaneous cases", () => { - test.beforeEach(async ({ page }) => { - }); +for (const config of testConfigs) { + process.env.SNAPSHOT_SUFFIX = undefined; + process.env.SNAPSHOT_SUFFIX = config.suffix; - test("matrix one row", async ({ page }) => { - await page.goto("http://localhost:8080/examples/matrix-one-row.html"); - await page.setViewportSize({ width: 800, height: 1000 }); - const questionTitleSelector = page.locator("h3").filter({ hasText: "Please indicate if you agree or disagree with the following statements" }); - await expect(questionTitleSelector).toBeVisible(); - const questionVisualizerSelector = questionTitleSelector.locator("..").locator(".."); - questionVisualizerSelector.scrollIntoViewIfNeeded(); + test.describe(`Miscellaneous cases ${config.name}`, () => { + test.beforeEach(async ({ page }) => { + }); - const chartTypeSelector = questionVisualizerSelector.locator("select").filter({ hasText: /^BarStacked BarPieDoughnut$/ }); - await expect(chartTypeSelector).toBeVisible(); - const chartContentSelector = questionVisualizerSelector.locator(".sa-visualizer__content"); - await expect(chartContentSelector).toBeVisible(); + test("matrix one row", async ({ page }) => { + await page.goto(`http://localhost:8080/examples/matrix-one-row${config.suffix}.html`); + await page.setViewportSize({ width: 800, height: 1000 }); + const questionTitleSelector = page.locator("h3").filter({ hasText: "Please indicate if you agree or disagree with the following statements" }); + await expect(questionTitleSelector).toBeVisible(); + const questionVisualizerSelector = questionTitleSelector.locator("..").locator(".."); + questionVisualizerSelector.scrollIntoViewIfNeeded(); - await expect(chartTypeSelector).toHaveValue("bar"); - await compareScreenshot(page, chartContentSelector, "matrix-single-row-bar.png"); + const chartTypeSelector = questionVisualizerSelector.locator(".sa-dropdown").first(); + await expect(chartTypeSelector).toBeVisible(); + const chartContentSelector = questionVisualizerSelector.locator(".sa-visualizer__content"); + await expect(chartContentSelector).toBeVisible(); - await chartTypeSelector.selectOption("pie"); - await compareScreenshot(page, chartContentSelector, "matrix-single-row-pie.png"); + await expect(chartTypeSelector.locator(".sa-dropdown-header-text")).toHaveText("Bar"); + await compareScreenshot(page, chartContentSelector, "matrix-single-row-bar.png"); - const transposeButtonSelector = questionVisualizerSelector.locator(".sa-toolbar__button").filter({ hasText: /^Per Columns$/ }); - await expect(transposeButtonSelector).toBeVisible(); - await transposeButtonSelector.click(); - await expect(questionVisualizerSelector.locator(".sa-toolbar__button").filter({ hasText: /^Per Values$/ })).toBeVisible(); + await chartTypeSelector.click(); + await getListItemByText(page, "Pie").click(); + await compareScreenshot(page, chartContentSelector, "matrix-single-row-pie.png"); - await chartTypeSelector.selectOption("bar"); - await compareScreenshot(page, chartContentSelector, "matrix-single-row-bar-per-values.png"); + const transposeButtonSelector = questionVisualizerSelector.locator(".sa-toolbar__button").filter({ hasText: /^Per Columns$/ }); + await expect(transposeButtonSelector).toBeVisible(); + await transposeButtonSelector.click(); + await expect(questionVisualizerSelector.locator(".sa-toolbar__button").filter({ hasText: /^Per Values$/ })).toBeVisible(); - await chartTypeSelector.selectOption("pie"); - await compareScreenshot(page, chartContentSelector, "matrix-single-row-pie-per-values.png"); - }); + await chartTypeSelector.click(); + await getListItemByText(page, "Bar").click(); + await compareScreenshot(page, chartContentSelector, "matrix-single-row-bar-per-values.png"); + + await chartTypeSelector.click(); + await getListItemByText(page, "Pie").click(); + await compareScreenshot(page, chartContentSelector, "matrix-single-row-pie-per-values.png"); + }); - test("matrix dropdown grouped", async ({ page }) => { - await page.goto("http://localhost:8080/examples/matrixdropdown-grouped.html"); - await page.setViewportSize({ width: 800, height: 1000 }); - const questionTitleSelector = page.locator("h3").filter({ hasText: "Please select the top 3 processes that you perceived as most difficult or troublesome." }); - await expect(questionTitleSelector).toBeVisible(); - const questionVisualizerSelector = questionTitleSelector.locator("..").locator(".."); - questionVisualizerSelector.scrollIntoViewIfNeeded(); + test("matrix dropdown grouped", async ({ page }) => { + await page.goto(`http://localhost:8080/examples/matrixdropdown-grouped${config.suffix}.html`); + await page.setViewportSize({ width: 800, height: 1000 }); + const questionTitleSelector = page.locator("h3").filter({ hasText: "Please select the top 3 processes that you perceived as most difficult or troublesome." }); + await expect(questionTitleSelector).toBeVisible(); + const questionVisualizerSelector = questionTitleSelector.locator("..").locator(".."); + questionVisualizerSelector.scrollIntoViewIfNeeded(); - const chartTypeSelector = questionVisualizerSelector.locator("select").filter({ hasText: /^Stacked BarBarPieDoughnut$/ }); - await expect(chartTypeSelector).toBeVisible(); - const chartContentSelector = questionVisualizerSelector.locator(".sa-visualizer__content").nth(1); - await expect(chartContentSelector).toBeVisible(); + const chartTypeSelector = questionVisualizerSelector.locator(".sa-dropdown").first(); + await expect(chartTypeSelector).toBeVisible(); + const chartContentSelector = questionVisualizerSelector.locator(".sa-visualizer__content"); + await expect(chartContentSelector).toBeVisible(); - await expect(chartTypeSelector).toHaveValue("stackedbar"); - await compareScreenshot(page, chartContentSelector, "matrixdropdown-grouped-stackedbar.png"); + await expect(chartTypeSelector.locator(".sa-dropdown-header-text")).toHaveText("Stacked Bar"); + await compareScreenshot(page, chartContentSelector, "matrixdropdown-grouped-stackedbar.png"); - await chartTypeSelector.selectOption("bar"); - await compareScreenshot(page, chartContentSelector, "matrixdropdown-grouped-bar.png"); + await chartTypeSelector.click(); + await getListItemByText(page, "Bar").click(); + await compareScreenshot(page, chartContentSelector, "matrixdropdown-grouped-bar.png"); - const transposeButtonSelector = questionVisualizerSelector.locator(".sa-toolbar__button").filter({ hasText: /^Per Columns$/ }); - await expect(transposeButtonSelector).toBeVisible(); - await transposeButtonSelector.click(); - await expect(questionVisualizerSelector.locator(".sa-toolbar__button").filter({ hasText: /^Per Values$/ })).toBeVisible(); + const transposeButtonSelector = questionVisualizerSelector.locator(".sa-toolbar__button").filter({ hasText: /^Per Columns$/ }); + await expect(transposeButtonSelector).toBeVisible(); + await transposeButtonSelector.click(); + await expect(questionVisualizerSelector.locator(".sa-toolbar__button").filter({ hasText: /^Per Values$/ })).toBeVisible(); - await chartTypeSelector.selectOption("stackedbar"); - await compareScreenshot(page, chartContentSelector, "matrixdropdown-grouped-stackedbar-per-values.png"); + await chartTypeSelector.click(); + await getListItemByText(page, "Stacked Bar").click(); + await compareScreenshot(page, chartContentSelector, "matrixdropdown-grouped-stackedbar-per-values.png"); - await chartTypeSelector.selectOption("bar"); - await compareScreenshot(page, chartContentSelector, "matrixdropdown-grouped-bar-per-values.png"); + await chartTypeSelector.click(); + await getListItemByText(page, "Bar").click(); + await compareScreenshot(page, chartContentSelector, "matrixdropdown-grouped-bar-per-values.png"); + }); }); -}); \ No newline at end of file +} \ No newline at end of file diff --git a/e2e/misc.spec.ts-snapshots/matrix-single-row-bar-per-values.png b/e2e/misc.spec.ts-snapshots/matrix-single-row-bar-per-values.png index 36e8fbb23..5b4a6f6d3 100644 Binary files a/e2e/misc.spec.ts-snapshots/matrix-single-row-bar-per-values.png and b/e2e/misc.spec.ts-snapshots/matrix-single-row-bar-per-values.png differ diff --git a/e2e/misc.spec.ts-snapshots/matrix-single-row-bar.png b/e2e/misc.spec.ts-snapshots/matrix-single-row-bar.png index 0c3dab861..c01339c17 100644 Binary files a/e2e/misc.spec.ts-snapshots/matrix-single-row-bar.png and b/e2e/misc.spec.ts-snapshots/matrix-single-row-bar.png differ diff --git a/e2e/misc.spec.ts-snapshots/matrix-single-row-pie-per-values.png b/e2e/misc.spec.ts-snapshots/matrix-single-row-pie-per-values.png index ef50a937b..cb445a3eb 100644 Binary files a/e2e/misc.spec.ts-snapshots/matrix-single-row-pie-per-values.png and b/e2e/misc.spec.ts-snapshots/matrix-single-row-pie-per-values.png differ diff --git a/e2e/misc.spec.ts-snapshots/matrix-single-row-pie.png b/e2e/misc.spec.ts-snapshots/matrix-single-row-pie.png index 7309505e2..d1fd3f0c5 100644 Binary files a/e2e/misc.spec.ts-snapshots/matrix-single-row-pie.png and b/e2e/misc.spec.ts-snapshots/matrix-single-row-pie.png differ diff --git a/e2e/misc.spec.ts-snapshots/matrixdropdown-grouped-bar-per-values.png b/e2e/misc.spec.ts-snapshots/matrixdropdown-grouped-bar-per-values.png index a988a617f..c0e40ae88 100644 Binary files a/e2e/misc.spec.ts-snapshots/matrixdropdown-grouped-bar-per-values.png and b/e2e/misc.spec.ts-snapshots/matrixdropdown-grouped-bar-per-values.png differ diff --git a/e2e/misc.spec.ts-snapshots/matrixdropdown-grouped-bar.png b/e2e/misc.spec.ts-snapshots/matrixdropdown-grouped-bar.png index 83ec0292f..3bb25aa3e 100644 Binary files a/e2e/misc.spec.ts-snapshots/matrixdropdown-grouped-bar.png and b/e2e/misc.spec.ts-snapshots/matrixdropdown-grouped-bar.png differ diff --git a/e2e/misc.spec.ts-snapshots/matrixdropdown-grouped-stackedbar-per-values.png b/e2e/misc.spec.ts-snapshots/matrixdropdown-grouped-stackedbar-per-values.png index 8f3685d5d..3ee919591 100644 Binary files a/e2e/misc.spec.ts-snapshots/matrixdropdown-grouped-stackedbar-per-values.png and b/e2e/misc.spec.ts-snapshots/matrixdropdown-grouped-stackedbar-per-values.png differ diff --git a/e2e/misc.spec.ts-snapshots/matrixdropdown-grouped-stackedbar.png b/e2e/misc.spec.ts-snapshots/matrixdropdown-grouped-stackedbar.png index 66bdcf4b4..b3342ddad 100644 Binary files a/e2e/misc.spec.ts-snapshots/matrixdropdown-grouped-stackedbar.png and b/e2e/misc.spec.ts-snapshots/matrixdropdown-grouped-stackedbar.png differ diff --git a/e2e/misc.spec.ts-snapshots_apexcharts/matrix-single-row-bar-per-values.png b/e2e/misc.spec.ts-snapshots_apexcharts/matrix-single-row-bar-per-values.png new file mode 100644 index 000000000..5b4a6f6d3 Binary files /dev/null and b/e2e/misc.spec.ts-snapshots_apexcharts/matrix-single-row-bar-per-values.png differ diff --git a/e2e/misc.spec.ts-snapshots_apexcharts/matrix-single-row-bar.png b/e2e/misc.spec.ts-snapshots_apexcharts/matrix-single-row-bar.png new file mode 100644 index 000000000..c01339c17 Binary files /dev/null and b/e2e/misc.spec.ts-snapshots_apexcharts/matrix-single-row-bar.png differ diff --git a/e2e/misc.spec.ts-snapshots_apexcharts/matrix-single-row-pie-per-values.png b/e2e/misc.spec.ts-snapshots_apexcharts/matrix-single-row-pie-per-values.png new file mode 100644 index 000000000..6c87642a9 Binary files /dev/null and b/e2e/misc.spec.ts-snapshots_apexcharts/matrix-single-row-pie-per-values.png differ diff --git a/e2e/misc.spec.ts-snapshots_apexcharts/matrix-single-row-pie.png b/e2e/misc.spec.ts-snapshots_apexcharts/matrix-single-row-pie.png new file mode 100644 index 000000000..d5a5dac38 Binary files /dev/null and b/e2e/misc.spec.ts-snapshots_apexcharts/matrix-single-row-pie.png differ diff --git a/e2e/misc.spec.ts-snapshots_apexcharts/matrixdropdown-grouped-bar-per-values.png b/e2e/misc.spec.ts-snapshots_apexcharts/matrixdropdown-grouped-bar-per-values.png new file mode 100644 index 000000000..c0e40ae88 Binary files /dev/null and b/e2e/misc.spec.ts-snapshots_apexcharts/matrixdropdown-grouped-bar-per-values.png differ diff --git a/e2e/misc.spec.ts-snapshots_apexcharts/matrixdropdown-grouped-bar.png b/e2e/misc.spec.ts-snapshots_apexcharts/matrixdropdown-grouped-bar.png new file mode 100644 index 000000000..3bb25aa3e Binary files /dev/null and b/e2e/misc.spec.ts-snapshots_apexcharts/matrixdropdown-grouped-bar.png differ diff --git a/e2e/misc.spec.ts-snapshots_apexcharts/matrixdropdown-grouped-stackedbar-per-values.png b/e2e/misc.spec.ts-snapshots_apexcharts/matrixdropdown-grouped-stackedbar-per-values.png new file mode 100644 index 000000000..3ee919591 Binary files /dev/null and b/e2e/misc.spec.ts-snapshots_apexcharts/matrixdropdown-grouped-stackedbar-per-values.png differ diff --git a/e2e/misc.spec.ts-snapshots_apexcharts/matrixdropdown-grouped-stackedbar.png b/e2e/misc.spec.ts-snapshots_apexcharts/matrixdropdown-grouped-stackedbar.png new file mode 100644 index 000000000..b3342ddad Binary files /dev/null and b/e2e/misc.spec.ts-snapshots_apexcharts/matrixdropdown-grouped-stackedbar.png differ diff --git a/e2e/pivot.spec.ts b/e2e/pivot.spec.ts index 36fb1616d..6c1b629f9 100644 --- a/e2e/pivot.spec.ts +++ b/e2e/pivot.spec.ts @@ -1,41 +1,53 @@ import { test, expect } from "@playwright/test"; -import { compareScreenshot } from "./helper"; +import { compareScreenshot, getListItemByText, testConfigs } from "./helper"; -test.describe("Pivot chart", () => { - test.beforeEach(async ({ page }) => { - await page.goto("http://localhost:8080/examples/pivot.html"); - await page.setViewportSize({ width: 1000, height: 800 }); - }); +for (const config of testConfigs) { + process.env.SNAPSHOT_SUFFIX = undefined; + process.env.SNAPSHOT_SUFFIX = config.suffix; - test("simple cases", async ({ page }) => { - await page.evaluate(() => { - const style = document.createElement("style"); - style.textContent = ".sa-commercial { display: none; }"; - document.head.appendChild(style); + test.describe(`Pivot chart ${config.name}`, () => { + test.beforeEach(async ({ page }) => { + await page.goto(`http://localhost:8080/examples/pivot${config.suffix}.html`); + await page.setViewportSize({ width: 1000, height: 800 }); }); - const xAxisSelector = page.locator("div").filter({ hasText: /^Category \(X Axis\):GenderItem kindBill amount$/ }).getByRole("combobox"); - let yAxisSelector = page.locator("div").filter({ hasText: /^Legend \(Series\):Not selectedItem kindBill amount$/ }).getByRole("combobox"); - await expect(page.locator("#pivotContainer").getByText("Category (X Axis):")).toBeVisible(); - await expect(xAxisSelector).toBeVisible(); - await expect(page.locator("#pivotContainer").getByText("Legend (Series):")).toBeVisible(); - await expect(yAxisSelector).toBeVisible(); - await compareScreenshot(page, "#pivotContainer", "pivot-q1-none.png"); - await yAxisSelector.selectOption("question2"); - await compareScreenshot(page, "#pivotContainer", "pivot-q1-q2.png"); - await yAxisSelector.selectOption("question3"); - await compareScreenshot(page, "#pivotContainer", "pivot-q1-q3.png"); - await xAxisSelector.selectOption("question2"); - yAxisSelector = page.locator("div").filter({ hasText: /^Legend \(Series\):Not selectedGenderBill amount$/ }).getByRole("combobox"); - await yAxisSelector.selectOption("question1"); - await compareScreenshot(page, "#pivotContainer", "pivot-q2-q1.png"); - await yAxisSelector.selectOption("question3"); - await compareScreenshot(page, "#pivotContainer", "pivot-q2-q3.png"); - await xAxisSelector.selectOption("question3"); - yAxisSelector = page.locator("div").filter({ hasText: /^Legend \(Series\):Not selectedGenderItem kind$/ }).getByRole("combobox"); - await yAxisSelector.selectOption("question1"); - await compareScreenshot(page, "#pivotContainer", "pivot-q3-q1.png"); - await yAxisSelector.selectOption("question2"); - await compareScreenshot(page, "#pivotContainer", "pivot-q3-q2.png"); - }); -}); \ No newline at end of file + test("simple cases", async ({ page }) => { + const xAxisSelector = page.locator(".sa-dropdown-header").nth(1); + const yAxisSelector = page.locator(".sa-dropdown-header").nth(2); + await page.evaluate(() => { + const style = document.createElement("style"); + style.textContent = ".sa-commercial { display: none; }"; + document.head.appendChild(style); + }); + await expect(page.locator("#pivotContainer").getByText("Category (X Axis):")).toBeVisible(); + await expect(xAxisSelector).toBeVisible(); + await expect(page.locator("#pivotContainer").getByText("Legend (Series):")).toBeVisible(); + await expect(yAxisSelector).toBeVisible(); + await compareScreenshot(page, "#pivotContainer", "pivot-q1-none.png"); + + await yAxisSelector.click(); + await getListItemByText(page, "Item kind").click(); + await compareScreenshot(page, "#pivotContainer", "pivot-q1-q2.png"); + await yAxisSelector.click(); + await getListItemByText(page, "Bill amount").click(); + await compareScreenshot(page, "#pivotContainer", "pivot-q1-q3.png"); + await xAxisSelector.click(); + await getListItemByText(page, "Item kind").click(); + await yAxisSelector.click(); + await getListItemByText(page, "Gender").click(); + await compareScreenshot(page, "#pivotContainer", "pivot-q2-q1.png"); + await yAxisSelector.click(); + await getListItemByText(page, "Bill amount").click(); + await compareScreenshot(page, "#pivotContainer", "pivot-q2-q3.png"); + await xAxisSelector.click(); + await getListItemByText(page, "Bill amount").click(); + await yAxisSelector.click(); + await getListItemByText(page, "Gender").click(); + await compareScreenshot(page, "#pivotContainer", "pivot-q3-q1.png"); + await yAxisSelector.click(); + await getListItemByText(page, "Item kind").click(); + await compareScreenshot(page, "#pivotContainer", "pivot-q3-q2.png"); + }); + + }); +} \ No newline at end of file diff --git a/e2e/pivot.spec.ts-snapshots/pivot-q1-none.png b/e2e/pivot.spec.ts-snapshots/pivot-q1-none.png index 70914d781..ef2811fe9 100644 Binary files a/e2e/pivot.spec.ts-snapshots/pivot-q1-none.png and b/e2e/pivot.spec.ts-snapshots/pivot-q1-none.png differ diff --git a/e2e/pivot.spec.ts-snapshots/pivot-q1-q2.png b/e2e/pivot.spec.ts-snapshots/pivot-q1-q2.png index b895112b4..264bfcf8b 100644 Binary files a/e2e/pivot.spec.ts-snapshots/pivot-q1-q2.png and b/e2e/pivot.spec.ts-snapshots/pivot-q1-q2.png differ diff --git a/e2e/pivot.spec.ts-snapshots/pivot-q1-q3.png b/e2e/pivot.spec.ts-snapshots/pivot-q1-q3.png index 32e9f0607..b637613ea 100644 Binary files a/e2e/pivot.spec.ts-snapshots/pivot-q1-q3.png and b/e2e/pivot.spec.ts-snapshots/pivot-q1-q3.png differ diff --git a/e2e/pivot.spec.ts-snapshots/pivot-q2-q1.png b/e2e/pivot.spec.ts-snapshots/pivot-q2-q1.png index ecf5a1cc1..5943ce9b2 100644 Binary files a/e2e/pivot.spec.ts-snapshots/pivot-q2-q1.png and b/e2e/pivot.spec.ts-snapshots/pivot-q2-q1.png differ diff --git a/e2e/pivot.spec.ts-snapshots/pivot-q2-q3.png b/e2e/pivot.spec.ts-snapshots/pivot-q2-q3.png index 809aa34d4..f7e89c5c2 100644 Binary files a/e2e/pivot.spec.ts-snapshots/pivot-q2-q3.png and b/e2e/pivot.spec.ts-snapshots/pivot-q2-q3.png differ diff --git a/e2e/pivot.spec.ts-snapshots/pivot-q3-q1.png b/e2e/pivot.spec.ts-snapshots/pivot-q3-q1.png index d3bd52b52..617778548 100644 Binary files a/e2e/pivot.spec.ts-snapshots/pivot-q3-q1.png and b/e2e/pivot.spec.ts-snapshots/pivot-q3-q1.png differ diff --git a/e2e/pivot.spec.ts-snapshots/pivot-q3-q2.png b/e2e/pivot.spec.ts-snapshots/pivot-q3-q2.png index be28e9e28..8708f9807 100644 Binary files a/e2e/pivot.spec.ts-snapshots/pivot-q3-q2.png and b/e2e/pivot.spec.ts-snapshots/pivot-q3-q2.png differ diff --git a/e2e/pivot.spec.ts-snapshots_apexcharts/pivot-q1-none.png b/e2e/pivot.spec.ts-snapshots_apexcharts/pivot-q1-none.png new file mode 100644 index 000000000..80c705280 Binary files /dev/null and b/e2e/pivot.spec.ts-snapshots_apexcharts/pivot-q1-none.png differ diff --git a/e2e/pivot.spec.ts-snapshots_apexcharts/pivot-q1-q2.png b/e2e/pivot.spec.ts-snapshots_apexcharts/pivot-q1-q2.png new file mode 100644 index 000000000..9d4dc47eb Binary files /dev/null and b/e2e/pivot.spec.ts-snapshots_apexcharts/pivot-q1-q2.png differ diff --git a/e2e/pivot.spec.ts-snapshots_apexcharts/pivot-q1-q3.png b/e2e/pivot.spec.ts-snapshots_apexcharts/pivot-q1-q3.png new file mode 100644 index 000000000..ebef16542 Binary files /dev/null and b/e2e/pivot.spec.ts-snapshots_apexcharts/pivot-q1-q3.png differ diff --git a/e2e/pivot.spec.ts-snapshots_apexcharts/pivot-q2-q1.png b/e2e/pivot.spec.ts-snapshots_apexcharts/pivot-q2-q1.png new file mode 100644 index 000000000..9d4fd4756 Binary files /dev/null and b/e2e/pivot.spec.ts-snapshots_apexcharts/pivot-q2-q1.png differ diff --git a/e2e/pivot.spec.ts-snapshots_apexcharts/pivot-q2-q3.png b/e2e/pivot.spec.ts-snapshots_apexcharts/pivot-q2-q3.png new file mode 100644 index 000000000..783402266 Binary files /dev/null and b/e2e/pivot.spec.ts-snapshots_apexcharts/pivot-q2-q3.png differ diff --git a/e2e/pivot.spec.ts-snapshots_apexcharts/pivot-q3-q1.png b/e2e/pivot.spec.ts-snapshots_apexcharts/pivot-q3-q1.png new file mode 100644 index 000000000..eaf780378 Binary files /dev/null and b/e2e/pivot.spec.ts-snapshots_apexcharts/pivot-q3-q1.png differ diff --git a/e2e/pivot.spec.ts-snapshots_apexcharts/pivot-q3-q2.png b/e2e/pivot.spec.ts-snapshots_apexcharts/pivot-q3-q2.png new file mode 100644 index 000000000..c35e3a595 Binary files /dev/null and b/e2e/pivot.spec.ts-snapshots_apexcharts/pivot-q3-q2.png differ diff --git a/e2e/rating.spec.ts b/e2e/rating.spec.ts index 4d331f3ac..a94b25eaf 100644 --- a/e2e/rating.spec.ts +++ b/e2e/rating.spec.ts @@ -1,51 +1,60 @@ import { test, expect } from "@playwright/test"; -import { compareScreenshot } from "./helper"; - -test.describe("Rating common", () => { - test.beforeEach(async ({ page }) => { - await page.goto("http://localhost:8080/examples/rating.html"); - await page.setViewportSize({ width: 800, height: 1000 }); - }); - - test("number value", async ({ page }) => { - const questionTitleSelector = page.locator("h3").filter({ hasText: "How likely are you to recommend SurveyJS to a friend or colleague?" }); - await expect(questionTitleSelector).toBeVisible(); - const questionVisualizerSelector = questionTitleSelector.locator("..").locator(".."); - questionVisualizerSelector.scrollIntoViewIfNeeded(); - - const visualizerTypeSelector = questionVisualizerSelector.locator("select").filter({ hasText: /^ChartAverageHistogram$/ }); - await expect(visualizerTypeSelector).toBeVisible(); - const chartContentSelector = questionVisualizerSelector.locator(".sa-visualizer__content").nth(1); - await expect(chartContentSelector).toBeVisible(); - - await expect(visualizerTypeSelector).toHaveValue("selectBase"); - await compareScreenshot(page, chartContentSelector, "rating-number-chart.png"); - - await visualizerTypeSelector.selectOption("number"); - await compareScreenshot(page, chartContentSelector, "rating-number-average.png"); - - await visualizerTypeSelector.selectOption("histogram"); - await compareScreenshot(page, chartContentSelector, "rating-number-histogram.png"); - }); - - test("string value", async ({ page }) => { - const questionTitleSelector = page.locator("h3").filter({ hasText: "What item do you prefer?" }); - await expect(questionTitleSelector).toBeVisible(); - const questionVisualizerSelector = questionTitleSelector.locator("..").locator(".."); - questionVisualizerSelector.scrollIntoViewIfNeeded(); - - const visualizerTypeSelector = questionVisualizerSelector.locator("select").filter({ hasText: /^ChartAverageHistogram$/ }); - await expect(visualizerTypeSelector).toBeVisible(); - const chartContentSelector = questionVisualizerSelector.locator(".sa-visualizer__content").nth(1); - await expect(chartContentSelector).toBeVisible(); - - await expect(visualizerTypeSelector).toHaveValue("selectBase"); - await compareScreenshot(page, chartContentSelector, "rating-string-chart.png"); - - await visualizerTypeSelector.selectOption("number"); - await compareScreenshot(page, chartContentSelector, "rating-string-average.png"); - - await visualizerTypeSelector.selectOption("histogram"); - await compareScreenshot(page, chartContentSelector, "rating-string-histogram.png"); +import { compareScreenshot, getListItemByText, testConfigs } from "./helper"; + +for (const config of testConfigs) { + process.env.SNAPSHOT_SUFFIX = undefined; + process.env.SNAPSHOT_SUFFIX = config.suffix; + + test.describe(`Rating common ${config.name}`, () => { + test.beforeEach(async ({ page }) => { + await page.goto(`http://localhost:8080/examples/rating${config.suffix}.html`); + await page.setViewportSize({ width: 800, height: 1000 }); + }); + + test("number value", async ({ page }) => { + const questionTitleSelector = page.locator("h3").filter({ hasText: "How likely are you to recommend SurveyJS to a friend or colleague?" }); + await expect(questionTitleSelector).toBeVisible(); + const questionVisualizerSelector = questionTitleSelector.locator("..").locator(".."); + questionVisualizerSelector.scrollIntoViewIfNeeded(); + + const visualizerTypeSelector = questionVisualizerSelector.locator(".sa-dropdown").first(); + await expect(visualizerTypeSelector).toBeVisible(); + const chartContentSelector = questionVisualizerSelector.locator(".sa-visualizer__content"); + await expect(chartContentSelector).toBeVisible(); + + await expect(visualizerTypeSelector.locator(".sa-dropdown-header-text")).toHaveText("Chart"); + await compareScreenshot(page, chartContentSelector, "rating-number-chart.png"); + + await visualizerTypeSelector.click(); + await getListItemByText(page, "Average").click(); + await compareScreenshot(page, chartContentSelector, "rating-number-average.png"); + + await visualizerTypeSelector.click(); + await getListItemByText(page, "Histogram").click(); + await compareScreenshot(page, chartContentSelector, "rating-number-histogram.png"); + }); + + test("string value", async ({ page }) => { + const questionTitleSelector = page.locator("h3").filter({ hasText: "What item do you prefer?" }); + await expect(questionTitleSelector).toBeVisible(); + const questionVisualizerSelector = questionTitleSelector.locator("..").locator(".."); + questionVisualizerSelector.scrollIntoViewIfNeeded(); + + const visualizerTypeSelector = questionVisualizerSelector.locator(".sa-dropdown").first(); + await expect(visualizerTypeSelector).toBeVisible(); + const chartContentSelector = questionVisualizerSelector.locator(".sa-visualizer__content"); + await expect(chartContentSelector).toBeVisible(); + + await expect(visualizerTypeSelector.locator(".sa-dropdown-header-text")).toHaveText("Chart"); + await compareScreenshot(page, chartContentSelector, "rating-string-chart.png"); + + await visualizerTypeSelector.click(); + await getListItemByText(page, "Average").click(); + await compareScreenshot(page, chartContentSelector, "rating-string-average.png"); + + await visualizerTypeSelector.click(); + await getListItemByText(page, "Histogram").click(); + await compareScreenshot(page, chartContentSelector, "rating-string-histogram.png"); + }); }); -}); \ No newline at end of file +} diff --git a/e2e/rating.spec.ts-snapshots/rating-number-average.png b/e2e/rating.spec.ts-snapshots/rating-number-average.png index c4fbaa6e4..6a369796e 100644 Binary files a/e2e/rating.spec.ts-snapshots/rating-number-average.png and b/e2e/rating.spec.ts-snapshots/rating-number-average.png differ diff --git a/e2e/rating.spec.ts-snapshots/rating-number-chart.png b/e2e/rating.spec.ts-snapshots/rating-number-chart.png index eb7bbb2e0..ae0597eaa 100644 Binary files a/e2e/rating.spec.ts-snapshots/rating-number-chart.png and b/e2e/rating.spec.ts-snapshots/rating-number-chart.png differ diff --git a/e2e/rating.spec.ts-snapshots/rating-number-histogram.png b/e2e/rating.spec.ts-snapshots/rating-number-histogram.png index bbfda9ecc..9317b5d8f 100644 Binary files a/e2e/rating.spec.ts-snapshots/rating-number-histogram.png and b/e2e/rating.spec.ts-snapshots/rating-number-histogram.png differ diff --git a/e2e/rating.spec.ts-snapshots/rating-string-average.png b/e2e/rating.spec.ts-snapshots/rating-string-average.png index 820b1c69b..da5c31ef7 100644 Binary files a/e2e/rating.spec.ts-snapshots/rating-string-average.png and b/e2e/rating.spec.ts-snapshots/rating-string-average.png differ diff --git a/e2e/rating.spec.ts-snapshots/rating-string-chart.png b/e2e/rating.spec.ts-snapshots/rating-string-chart.png index d0ff8ee49..a87b60305 100644 Binary files a/e2e/rating.spec.ts-snapshots/rating-string-chart.png and b/e2e/rating.spec.ts-snapshots/rating-string-chart.png differ diff --git a/e2e/rating.spec.ts-snapshots/rating-string-histogram.png b/e2e/rating.spec.ts-snapshots/rating-string-histogram.png index c98587f01..ca6e74ffe 100644 Binary files a/e2e/rating.spec.ts-snapshots/rating-string-histogram.png and b/e2e/rating.spec.ts-snapshots/rating-string-histogram.png differ diff --git a/e2e/rating.spec.ts-snapshots_apexcharts/rating-number-average.png b/e2e/rating.spec.ts-snapshots_apexcharts/rating-number-average.png new file mode 100644 index 000000000..f0ca31f49 Binary files /dev/null and b/e2e/rating.spec.ts-snapshots_apexcharts/rating-number-average.png differ diff --git a/e2e/rating.spec.ts-snapshots_apexcharts/rating-number-chart.png b/e2e/rating.spec.ts-snapshots_apexcharts/rating-number-chart.png new file mode 100644 index 000000000..ae0597eaa Binary files /dev/null and b/e2e/rating.spec.ts-snapshots_apexcharts/rating-number-chart.png differ diff --git a/e2e/rating.spec.ts-snapshots_apexcharts/rating-number-histogram.png b/e2e/rating.spec.ts-snapshots_apexcharts/rating-number-histogram.png new file mode 100644 index 000000000..fca88ab37 Binary files /dev/null and b/e2e/rating.spec.ts-snapshots_apexcharts/rating-number-histogram.png differ diff --git a/e2e/rating.spec.ts-snapshots_apexcharts/rating-string-average.png b/e2e/rating.spec.ts-snapshots_apexcharts/rating-string-average.png new file mode 100644 index 000000000..7a9703ed1 Binary files /dev/null and b/e2e/rating.spec.ts-snapshots_apexcharts/rating-string-average.png differ diff --git a/e2e/rating.spec.ts-snapshots_apexcharts/rating-string-chart.png b/e2e/rating.spec.ts-snapshots_apexcharts/rating-string-chart.png new file mode 100644 index 000000000..a87b60305 Binary files /dev/null and b/e2e/rating.spec.ts-snapshots_apexcharts/rating-string-chart.png differ diff --git a/e2e/rating.spec.ts-snapshots_apexcharts/rating-string-histogram.png b/e2e/rating.spec.ts-snapshots_apexcharts/rating-string-histogram.png new file mode 100644 index 000000000..894d74480 Binary files /dev/null and b/e2e/rating.spec.ts-snapshots_apexcharts/rating-string-histogram.png differ diff --git a/e2e/summary.spec.ts b/e2e/summary.spec.ts index 3487a07ee..fa69f7b09 100644 --- a/e2e/summary.spec.ts +++ b/e2e/summary.spec.ts @@ -1,149 +1,174 @@ import { test, expect } from "@playwright/test"; -import { compareScreenshot } from "./helper"; - -test.describe("Summary common", () => { - test.beforeEach(async ({ page }) => { - await page.goto("http://localhost:8080/examples/summary.html"); - await page.setViewportSize({ width: 800, height: 1000 }); - }); - - test("matrix simple cases", async ({ page }) => { - const questionTitleSelector = page.locator("h3").filter({ hasText: "Please indicate if you agree or disagree with the following statements" }); - await expect(questionTitleSelector).toBeVisible(); - const questionVisualizerSelector = questionTitleSelector.locator("..").locator(".."); - questionVisualizerSelector.scrollIntoViewIfNeeded(); - - const chartTypeSelector = questionVisualizerSelector.locator("select").filter({ hasText: /^BarStacked BarPieDoughnut$/ }); - await expect(chartTypeSelector).toBeVisible(); - const chartContentSelector = questionVisualizerSelector.locator(".sa-visualizer__content"); - await expect(chartContentSelector).toBeVisible(); - - await expect(chartTypeSelector).toHaveValue("bar"); - await compareScreenshot(page, chartContentSelector, "matrix-simple-bar.png"); - - await chartTypeSelector.selectOption("stackedbar"); - await compareScreenshot(page, chartContentSelector, "matrix-simple-stackedbar.png"); - - await chartTypeSelector.selectOption("pie"); - await compareScreenshot(page, chartContentSelector, "matrix-simple-pie.png"); - - await chartTypeSelector.selectOption("doughnut"); - await compareScreenshot(page, chartContentSelector, "matrix-simple-doughnut.png"); - }); - - test("boolean simple cases", async ({ page }) => { - const questionTitleSelector = page.locator("h3").filter({ hasText: "Please answer the question" }); - await expect(questionTitleSelector).toBeVisible(); - const questionVisualizerSelector = questionTitleSelector.locator("..").locator(".."); - questionVisualizerSelector.scrollIntoViewIfNeeded(); - - const visualizerSelector = questionVisualizerSelector.locator("select").filter({ hasText: /^ChartTable$/ }); - await expect(visualizerSelector).toBeVisible(); - await expect(visualizerSelector).toHaveValue("boolean"); - - const chartTypeSelector = questionVisualizerSelector.locator("select").filter({ hasText: /^PieBarDoughnut$/ }); - await expect(chartTypeSelector).toBeVisible(); - const chartContentSelector = questionVisualizerSelector.locator(".sa-visualizer__content").nth(1); - await expect(chartContentSelector).toBeVisible(); - - await expect(chartTypeSelector).toHaveValue("pie"); - await compareScreenshot(page, chartContentSelector, "boolean-simple-bar.png"); - - await chartTypeSelector.selectOption("bar"); - await compareScreenshot(page, chartContentSelector, "boolean-simple-pie.png"); - - await chartTypeSelector.selectOption("doughnut"); - await compareScreenshot(page, chartContentSelector, "boolean-simple-doughnut.png"); - - await visualizerSelector.selectOption("options"); - await expect(chartTypeSelector).toBeHidden(); - await compareScreenshot(page, chartContentSelector, "boolean-simple-table.png"); - }); - - test("select simple cases", async ({ page }) => { - const questionTitleSelector = page.locator("h3").filter({ hasText: "Which of the following best describes you or your organization?" }); - await expect(questionTitleSelector).toBeVisible(); - const questionVisualizerSelector = questionTitleSelector.locator("..").locator(".."); - questionVisualizerSelector.scrollIntoViewIfNeeded(); - - const visualizerSelector = questionVisualizerSelector.locator("select").filter({ hasText: /^ChartTable$/ }); - await expect(visualizerSelector).toBeVisible(); - await expect(visualizerSelector).toHaveValue("selectBase"); - - const chartTypeSelector = questionVisualizerSelector.locator("select").filter({ hasText: /^BarVertical BarPieDoughnut$/ }); - await expect(chartTypeSelector).toBeVisible(); - const chartContentSelector = questionVisualizerSelector.locator(".sa-visualizer__content").nth(1); - await expect(chartContentSelector).toBeVisible(); - - await expect(chartTypeSelector).toHaveValue("bar"); - await compareScreenshot(page, chartContentSelector, "select-simple-bar.png"); - - await chartTypeSelector.selectOption("vbar"); - await compareScreenshot(page, chartContentSelector, "select-simple-vbar.png"); - - await chartTypeSelector.selectOption("pie"); - await compareScreenshot(page, chartContentSelector, "select-simple-pie.png"); - - await chartTypeSelector.selectOption("doughnut"); - await compareScreenshot(page, chartContentSelector, "select-simple-doughnut.png"); - - await visualizerSelector.selectOption("choices"); - await expect(chartTypeSelector).toBeHidden(); - await compareScreenshot(page, chartContentSelector, "select-simple-table.png"); - - const otherItemsSelector = questionVisualizerSelector.locator("h4").filter({ hasText: "Other items and comments" }); - await expect(otherItemsSelector).toBeVisible(); - }); - - test("histogram simple cases", async ({ page }) => { - const questionTitleSelector = page.locator("h3").filter({ hasText: "How likely are you to recommend SurveyJS to a friend or colleague?" }); - await expect(questionTitleSelector).toBeVisible(); - const questionVisualizerSelector = questionTitleSelector.locator("..").locator(".."); - questionVisualizerSelector.scrollIntoViewIfNeeded(); - - const visualizerSelector = questionVisualizerSelector.locator("select").filter({ hasText: /^ChartAverageHistogram$/ }); - await expect(visualizerSelector).toBeVisible(); - await expect(visualizerSelector).toHaveValue("selectBase"); - await visualizerSelector.selectOption("histogram"); - - const chartTypeSelector = questionVisualizerSelector.locator("select").filter({ hasText: /^Vertical BarBar$/ }); - await expect(chartTypeSelector).toBeVisible(); - const chartContentSelector = questionVisualizerSelector.locator(".sa-visualizer__content").nth(1); - await expect(chartContentSelector).toBeVisible(); - - await expect(chartTypeSelector).toHaveValue("vbar"); - await compareScreenshot(page, chartContentSelector, "histogram-simple-vbar.png"); - - await chartTypeSelector.selectOption("bar"); - await compareScreenshot(page, chartContentSelector, "histogram-simple-bar.png"); - - await visualizerSelector.selectOption("number"); - await expect(chartTypeSelector).toBeHidden(); - - const gaugeTypeSelector = questionVisualizerSelector.locator("select").filter({ hasText: /^GaugeBullet$/ }); - await expect(gaugeTypeSelector).toBeVisible(); - await expect(gaugeTypeSelector).toHaveValue("gauge"); - await compareScreenshot(page, chartContentSelector, "number-simple-gauge.png"); - - await gaugeTypeSelector.selectOption("bullet"); - await compareScreenshot(page, chartContentSelector, "number-simple-bullet.png"); - }); - - test("text simple cases", async ({ page }) => { - const questionTitleSelector = page.locator("h3").filter({ hasText: "What's your favorite functionality / add-on?" }); - await expect(questionTitleSelector).toBeVisible(); - const questionVisualizerSelector = questionTitleSelector.locator("..").locator(".."); - questionVisualizerSelector.scrollIntoViewIfNeeded(); - - const visualizerTypeSelector = questionVisualizerSelector.locator("select").filter({ hasText: /^WordcloudTexts in table$/ }); - await expect(visualizerTypeSelector).toBeVisible(); - const chartContentSelector = questionVisualizerSelector.locator(".sa-visualizer__content").nth(1); - await expect(chartContentSelector).toBeVisible(); - - await expect(visualizerTypeSelector).toHaveValue("wordcloud"); - await compareScreenshot(page, chartContentSelector, "text-simple-wordcloud.png"); - - await visualizerTypeSelector.selectOption("text"); - await compareScreenshot(page, chartContentSelector, "text-simple-table.png"); +import { compareScreenshot, getListItemByText, testConfigs } from "./helper"; + +for (const config of testConfigs) { + process.env.SNAPSHOT_SUFFIX = undefined; + process.env.SNAPSHOT_SUFFIX = config.suffix; + + test.describe(`Summary common ${config.name}`, () => { + test.beforeEach(async ({ page }) => { + await page.goto(`http://localhost:8080/examples/summary${config.suffix}.html`); + await page.setViewportSize({ width: 800, height: 1000 }); + }); + + test("matrix simple cases", async ({ page }) => { + const questionTitleSelector = page.locator("h3").filter({ hasText: "Please indicate if you agree or disagree with the following statements" }); + await expect(questionTitleSelector).toBeVisible(); + const questionVisualizerSelector = questionTitleSelector.locator("..").locator(".."); + questionVisualizerSelector.scrollIntoViewIfNeeded(); + + const chartTypeSelector = questionVisualizerSelector.locator(".sa-dropdown").first(); + await expect(chartTypeSelector).toBeVisible(); + const chartContentSelector = questionVisualizerSelector.locator(".sa-visualizer__content"); + await expect(chartContentSelector).toBeVisible(); + + await expect(chartTypeSelector.locator(".sa-dropdown-header-text")).toHaveText("Bar"); + await compareScreenshot(page, chartContentSelector, "matrix-simple-bar.png"); + + await chartTypeSelector.click(); + await getListItemByText(page, "Stacked Bar").click(); + await compareScreenshot(page, chartContentSelector, "matrix-simple-stackedbar.png"); + + await chartTypeSelector.click(); + await getListItemByText(page, "Pie").click(); + await compareScreenshot(page, chartContentSelector, "matrix-simple-pie.png"); + + await chartTypeSelector.click(); + await getListItemByText(page, "Doughnut").click(); + await compareScreenshot(page, chartContentSelector, "matrix-simple-doughnut.png"); + }); + + test("boolean simple cases", async ({ page }) => { + const questionTitleSelector = page.locator("h3").filter({ hasText: "Please answer the question" }); + await expect(questionTitleSelector).toBeVisible(); + const questionVisualizerSelector = questionTitleSelector.locator("..").locator(".."); + questionVisualizerSelector.scrollIntoViewIfNeeded(); + + // const chartTypeSelector = questionVisualizerSelector.locator(".sa-dropdown").first(); + // await expect(chartTypeSelector).toBeVisible(); + // const chartContentSelector = questionVisualizerSelector.locator(".sa-visualizer__content"); + // await expect(chartContentSelector).toBeVisible(); + const visualizerSelector = questionVisualizerSelector.locator(".sa-dropdown").first(); + await expect(visualizerSelector).toBeVisible(); + await expect(visualizerSelector.locator(".sa-dropdown-header-text")).toHaveText("Chart"); + + const chartTypeSelector = questionVisualizerSelector.locator(".sa-dropdown").nth(1); + await expect(chartTypeSelector).toBeVisible(); + const chartContentSelector = questionVisualizerSelector.locator(".sa-visualizer__content").first(); + await expect(chartContentSelector).toBeVisible(); + + await expect(chartTypeSelector.locator(".sa-dropdown-header-text")).toHaveText("Pie"); + await compareScreenshot(page, chartContentSelector, "boolean-simple-bar.png"); + + await chartTypeSelector.click(); + await getListItemByText(page, "Bar").click(); + await compareScreenshot(page, chartContentSelector, "boolean-simple-pie.png"); + + await chartTypeSelector.click(); + await getListItemByText(page, "Doughnut").click(); + await compareScreenshot(page, chartContentSelector, "boolean-simple-doughnut.png"); + + await visualizerSelector.click(); + await getListItemByText(page, "Table").click(); + await expect(chartTypeSelector).toBeHidden(); + await compareScreenshot(page, chartContentSelector, "boolean-simple-table.png"); + }); + + test("select simple cases", async ({ page }) => { + const questionTitleSelector = page.locator("h3").filter({ hasText: "Which of the following best describes you or your organization?" }); + await expect(questionTitleSelector).toBeVisible(); + const questionVisualizerSelector = questionTitleSelector.locator("..").locator(".."); + questionVisualizerSelector.scrollIntoViewIfNeeded(); + + const visualizerSelector = questionVisualizerSelector.locator(".sa-dropdown").first(); + await expect(visualizerSelector).toBeVisible(); + await expect(visualizerSelector.locator(".sa-dropdown-header-text")).toHaveText("Chart"); + + const chartTypeSelector = questionVisualizerSelector.locator(".sa-dropdown").nth(1); + await expect(chartTypeSelector).toBeVisible(); + const chartContentSelector = questionVisualizerSelector.locator(".sa-visualizer__content").first(); + await expect(chartContentSelector).toBeVisible(); + + await expect(chartTypeSelector.locator(".sa-dropdown-header-text")).toHaveText("Bar"); + await compareScreenshot(page, chartContentSelector, "select-simple-bar.png"); + + await chartTypeSelector.click(); + await getListItemByText(page, "Vertical Bar").click(); + await compareScreenshot(page, chartContentSelector, "select-simple-vbar.png"); + + await chartTypeSelector.click(); + await getListItemByText(page, "Pie").click(); + await compareScreenshot(page, chartContentSelector, "select-simple-pie.png"); + + await chartTypeSelector.click(); + await getListItemByText(page, "Doughnut").click(); + await compareScreenshot(page, chartContentSelector, "select-simple-doughnut.png"); + + await visualizerSelector.click(); + await getListItemByText(page, "Table").click(); + await compareScreenshot(page, chartContentSelector, "select-simple-table.png"); + + const otherItemsSelector = questionVisualizerSelector.locator("h4").filter({ hasText: "Other items and comments" }); + await expect(otherItemsSelector).toBeVisible(); + }); + + test("simple cases", async ({ page }) => { + const questionTitleSelector = page.locator("h3").filter({ hasText: "How likely are you to recommend SurveyJS to a friend or colleague?" }); + await expect(questionTitleSelector).toBeVisible(); + const questionVisualizerSelector = questionTitleSelector.locator("..").locator(".."); + questionVisualizerSelector.scrollIntoViewIfNeeded(); + await expect(questionVisualizerSelector.locator(".sa-dropdown")).toHaveCount(3); + + const visualizerSelector = questionVisualizerSelector.locator(".sa-dropdown").first(); + await expect(visualizerSelector).toBeVisible(); + await expect(visualizerSelector.locator(".sa-dropdown-header-text")).toHaveText("Chart"); + + await visualizerSelector.click(); + await getListItemByText(page, "Histogram").click(); + + const chartTypeSelector = questionVisualizerSelector.locator(".sa-dropdown").nth(1); + await expect(chartTypeSelector).toBeVisible(); + const chartContentSelector = questionVisualizerSelector.locator(".sa-visualizer__content"); + await expect(chartContentSelector).toBeVisible(); + + await expect(chartTypeSelector.locator(".sa-dropdown-header-text")).toHaveText("Vertical Bar"); + await compareScreenshot(page, chartContentSelector, "histogram-simple-vbar.png"); + + await chartTypeSelector.click(); + await getListItemByText(page, "Bar").click(); + await compareScreenshot(page, chartContentSelector, "histogram-simple-bar.png"); + + await visualizerSelector.click(); + await getListItemByText(page, "Average").click(); + await expect(questionVisualizerSelector.locator(".sa-dropdown")).toHaveCount(2); + + const gaugeTypeSelector = questionVisualizerSelector.locator(".sa-dropdown").nth(1); + await expect(gaugeTypeSelector).toBeVisible(); + await expect(gaugeTypeSelector.locator(".sa-dropdown-header-text")).toHaveText("Gauge"); + await compareScreenshot(page, chartContentSelector, "number-simple-gauge.png"); + + await gaugeTypeSelector.click(); + await getListItemByText(page, "Bullet").click(); + await compareScreenshot(page, chartContentSelector, "number-simple-bullet.png"); + }); + + test("text simple cases", async ({ page }) => { + const questionTitleSelector = page.locator("h3").filter({ hasText: "What's your favorite functionality / add-on?" }); + await expect(questionTitleSelector).toBeVisible(); + const questionVisualizerSelector = questionTitleSelector.locator("..").locator(".."); + questionVisualizerSelector.scrollIntoViewIfNeeded(); + + const visualizerTypeSelector = questionVisualizerSelector.locator(".sa-dropdown").first(); + await expect(visualizerTypeSelector).toBeVisible(); + const chartContentSelector = questionVisualizerSelector.locator(".sa-visualizer__content"); + await expect(chartContentSelector).toBeVisible(); + + await expect(visualizerTypeSelector.locator(".sa-dropdown-header-text")).toHaveText("Wordcloud"); + await compareScreenshot(page, chartContentSelector, "text-simple-wordcloud.png"); + + await visualizerTypeSelector.click(); + await getListItemByText(page, "Texts in table").click(); + await compareScreenshot(page, chartContentSelector, "text-simple-table.png"); + }); }); -}); \ No newline at end of file +} \ No newline at end of file diff --git a/e2e/summary.spec.ts-snapshots/boolean-simple-bar.png b/e2e/summary.spec.ts-snapshots/boolean-simple-bar.png index 62750a631..bf992fc38 100644 Binary files a/e2e/summary.spec.ts-snapshots/boolean-simple-bar.png and b/e2e/summary.spec.ts-snapshots/boolean-simple-bar.png differ diff --git a/e2e/summary.spec.ts-snapshots/boolean-simple-doughnut.png b/e2e/summary.spec.ts-snapshots/boolean-simple-doughnut.png index 86ea732fc..34d78fb8f 100644 Binary files a/e2e/summary.spec.ts-snapshots/boolean-simple-doughnut.png and b/e2e/summary.spec.ts-snapshots/boolean-simple-doughnut.png differ diff --git a/e2e/summary.spec.ts-snapshots/boolean-simple-pie.png b/e2e/summary.spec.ts-snapshots/boolean-simple-pie.png index 06f297244..d5f3ac021 100644 Binary files a/e2e/summary.spec.ts-snapshots/boolean-simple-pie.png and b/e2e/summary.spec.ts-snapshots/boolean-simple-pie.png differ diff --git a/e2e/summary.spec.ts-snapshots/boolean-simple-table.png b/e2e/summary.spec.ts-snapshots/boolean-simple-table.png index 5ef070420..95df50327 100644 Binary files a/e2e/summary.spec.ts-snapshots/boolean-simple-table.png and b/e2e/summary.spec.ts-snapshots/boolean-simple-table.png differ diff --git a/e2e/summary.spec.ts-snapshots/histogram-simple-bar.png b/e2e/summary.spec.ts-snapshots/histogram-simple-bar.png index 1ddf2a959..62f4ea757 100644 Binary files a/e2e/summary.spec.ts-snapshots/histogram-simple-bar.png and b/e2e/summary.spec.ts-snapshots/histogram-simple-bar.png differ diff --git a/e2e/summary.spec.ts-snapshots/histogram-simple-vbar.png b/e2e/summary.spec.ts-snapshots/histogram-simple-vbar.png index ee22bffb9..0abc4e22d 100644 Binary files a/e2e/summary.spec.ts-snapshots/histogram-simple-vbar.png and b/e2e/summary.spec.ts-snapshots/histogram-simple-vbar.png differ diff --git a/e2e/summary.spec.ts-snapshots/matrix-simple-bar.png b/e2e/summary.spec.ts-snapshots/matrix-simple-bar.png index dea7bf259..882b69b29 100644 Binary files a/e2e/summary.spec.ts-snapshots/matrix-simple-bar.png and b/e2e/summary.spec.ts-snapshots/matrix-simple-bar.png differ diff --git a/e2e/summary.spec.ts-snapshots/matrix-simple-doughnut.png b/e2e/summary.spec.ts-snapshots/matrix-simple-doughnut.png index f30d9cf24..5bd25c8d5 100644 Binary files a/e2e/summary.spec.ts-snapshots/matrix-simple-doughnut.png and b/e2e/summary.spec.ts-snapshots/matrix-simple-doughnut.png differ diff --git a/e2e/summary.spec.ts-snapshots/matrix-simple-pie.png b/e2e/summary.spec.ts-snapshots/matrix-simple-pie.png index de5c76ed0..bf69f4427 100644 Binary files a/e2e/summary.spec.ts-snapshots/matrix-simple-pie.png and b/e2e/summary.spec.ts-snapshots/matrix-simple-pie.png differ diff --git a/e2e/summary.spec.ts-snapshots/matrix-simple-stackedbar.png b/e2e/summary.spec.ts-snapshots/matrix-simple-stackedbar.png index eaa4fc515..f00efcd94 100644 Binary files a/e2e/summary.spec.ts-snapshots/matrix-simple-stackedbar.png and b/e2e/summary.spec.ts-snapshots/matrix-simple-stackedbar.png differ diff --git a/e2e/summary.spec.ts-snapshots/number-simple-bullet.png b/e2e/summary.spec.ts-snapshots/number-simple-bullet.png index 9e6ba1c82..31e2c225f 100644 Binary files a/e2e/summary.spec.ts-snapshots/number-simple-bullet.png and b/e2e/summary.spec.ts-snapshots/number-simple-bullet.png differ diff --git a/e2e/summary.spec.ts-snapshots/number-simple-gauge.png b/e2e/summary.spec.ts-snapshots/number-simple-gauge.png index 9e05dd12b..6d38a775c 100644 Binary files a/e2e/summary.spec.ts-snapshots/number-simple-gauge.png and b/e2e/summary.spec.ts-snapshots/number-simple-gauge.png differ diff --git a/e2e/summary.spec.ts-snapshots/select-simple-bar.png b/e2e/summary.spec.ts-snapshots/select-simple-bar.png index 79734b684..36189298c 100644 Binary files a/e2e/summary.spec.ts-snapshots/select-simple-bar.png and b/e2e/summary.spec.ts-snapshots/select-simple-bar.png differ diff --git a/e2e/summary.spec.ts-snapshots/select-simple-doughnut.png b/e2e/summary.spec.ts-snapshots/select-simple-doughnut.png index 52cf9a2e4..b0516518b 100644 Binary files a/e2e/summary.spec.ts-snapshots/select-simple-doughnut.png and b/e2e/summary.spec.ts-snapshots/select-simple-doughnut.png differ diff --git a/e2e/summary.spec.ts-snapshots/select-simple-pie.png b/e2e/summary.spec.ts-snapshots/select-simple-pie.png index 9f72d5c2c..b1fb60b94 100644 Binary files a/e2e/summary.spec.ts-snapshots/select-simple-pie.png and b/e2e/summary.spec.ts-snapshots/select-simple-pie.png differ diff --git a/e2e/summary.spec.ts-snapshots/select-simple-table.png b/e2e/summary.spec.ts-snapshots/select-simple-table.png index 773efe7f5..f388d2184 100644 Binary files a/e2e/summary.spec.ts-snapshots/select-simple-table.png and b/e2e/summary.spec.ts-snapshots/select-simple-table.png differ diff --git a/e2e/summary.spec.ts-snapshots/select-simple-vbar.png b/e2e/summary.spec.ts-snapshots/select-simple-vbar.png index c59838484..75f527ad4 100644 Binary files a/e2e/summary.spec.ts-snapshots/select-simple-vbar.png and b/e2e/summary.spec.ts-snapshots/select-simple-vbar.png differ diff --git a/e2e/summary.spec.ts-snapshots/text-simple-table.png b/e2e/summary.spec.ts-snapshots/text-simple-table.png index d6231c913..c6a6a64ca 100644 Binary files a/e2e/summary.spec.ts-snapshots/text-simple-table.png and b/e2e/summary.spec.ts-snapshots/text-simple-table.png differ diff --git a/e2e/summary.spec.ts-snapshots/text-simple-wordcloud.png b/e2e/summary.spec.ts-snapshots/text-simple-wordcloud.png index 144669df3..174e2a6e1 100644 Binary files a/e2e/summary.spec.ts-snapshots/text-simple-wordcloud.png and b/e2e/summary.spec.ts-snapshots/text-simple-wordcloud.png differ diff --git a/e2e/summary.spec.ts-snapshots_apexcharts/boolean-simple-bar.png b/e2e/summary.spec.ts-snapshots_apexcharts/boolean-simple-bar.png new file mode 100644 index 000000000..812aea7b2 Binary files /dev/null and b/e2e/summary.spec.ts-snapshots_apexcharts/boolean-simple-bar.png differ diff --git a/e2e/summary.spec.ts-snapshots_apexcharts/boolean-simple-doughnut.png b/e2e/summary.spec.ts-snapshots_apexcharts/boolean-simple-doughnut.png new file mode 100644 index 000000000..3d06ac5b2 Binary files /dev/null and b/e2e/summary.spec.ts-snapshots_apexcharts/boolean-simple-doughnut.png differ diff --git a/e2e/summary.spec.ts-snapshots_apexcharts/boolean-simple-pie.png b/e2e/summary.spec.ts-snapshots_apexcharts/boolean-simple-pie.png new file mode 100644 index 000000000..d5f3ac021 Binary files /dev/null and b/e2e/summary.spec.ts-snapshots_apexcharts/boolean-simple-pie.png differ diff --git a/e2e/summary.spec.ts-snapshots_apexcharts/boolean-simple-table.png b/e2e/summary.spec.ts-snapshots_apexcharts/boolean-simple-table.png new file mode 100644 index 000000000..95df50327 Binary files /dev/null and b/e2e/summary.spec.ts-snapshots_apexcharts/boolean-simple-table.png differ diff --git a/e2e/summary.spec.ts-snapshots_apexcharts/histogram-simple-bar.png b/e2e/summary.spec.ts-snapshots_apexcharts/histogram-simple-bar.png new file mode 100644 index 000000000..62f4ea757 Binary files /dev/null and b/e2e/summary.spec.ts-snapshots_apexcharts/histogram-simple-bar.png differ diff --git a/e2e/summary.spec.ts-snapshots_apexcharts/histogram-simple-vbar.png b/e2e/summary.spec.ts-snapshots_apexcharts/histogram-simple-vbar.png new file mode 100644 index 000000000..705d171a5 Binary files /dev/null and b/e2e/summary.spec.ts-snapshots_apexcharts/histogram-simple-vbar.png differ diff --git a/e2e/summary.spec.ts-snapshots_apexcharts/matrix-simple-bar.png b/e2e/summary.spec.ts-snapshots_apexcharts/matrix-simple-bar.png new file mode 100644 index 000000000..882b69b29 Binary files /dev/null and b/e2e/summary.spec.ts-snapshots_apexcharts/matrix-simple-bar.png differ diff --git a/e2e/summary.spec.ts-snapshots_apexcharts/matrix-simple-doughnut.png b/e2e/summary.spec.ts-snapshots_apexcharts/matrix-simple-doughnut.png new file mode 100644 index 000000000..a45a57a51 Binary files /dev/null and b/e2e/summary.spec.ts-snapshots_apexcharts/matrix-simple-doughnut.png differ diff --git a/e2e/summary.spec.ts-snapshots_apexcharts/matrix-simple-pie.png b/e2e/summary.spec.ts-snapshots_apexcharts/matrix-simple-pie.png new file mode 100644 index 000000000..f0e50549b Binary files /dev/null and b/e2e/summary.spec.ts-snapshots_apexcharts/matrix-simple-pie.png differ diff --git a/e2e/summary.spec.ts-snapshots_apexcharts/matrix-simple-stackedbar.png b/e2e/summary.spec.ts-snapshots_apexcharts/matrix-simple-stackedbar.png new file mode 100644 index 000000000..f00efcd94 Binary files /dev/null and b/e2e/summary.spec.ts-snapshots_apexcharts/matrix-simple-stackedbar.png differ diff --git a/e2e/summary.spec.ts-snapshots_apexcharts/number-simple-bullet.png b/e2e/summary.spec.ts-snapshots_apexcharts/number-simple-bullet.png new file mode 100644 index 000000000..dca729f5b Binary files /dev/null and b/e2e/summary.spec.ts-snapshots_apexcharts/number-simple-bullet.png differ diff --git a/e2e/summary.spec.ts-snapshots_apexcharts/number-simple-gauge.png b/e2e/summary.spec.ts-snapshots_apexcharts/number-simple-gauge.png new file mode 100644 index 000000000..4a6df5721 Binary files /dev/null and b/e2e/summary.spec.ts-snapshots_apexcharts/number-simple-gauge.png differ diff --git a/e2e/summary.spec.ts-snapshots_apexcharts/select-simple-bar.png b/e2e/summary.spec.ts-snapshots_apexcharts/select-simple-bar.png new file mode 100644 index 000000000..36189298c Binary files /dev/null and b/e2e/summary.spec.ts-snapshots_apexcharts/select-simple-bar.png differ diff --git a/e2e/summary.spec.ts-snapshots_apexcharts/select-simple-doughnut.png b/e2e/summary.spec.ts-snapshots_apexcharts/select-simple-doughnut.png new file mode 100644 index 000000000..4c6704213 Binary files /dev/null and b/e2e/summary.spec.ts-snapshots_apexcharts/select-simple-doughnut.png differ diff --git a/e2e/summary.spec.ts-snapshots_apexcharts/select-simple-pie.png b/e2e/summary.spec.ts-snapshots_apexcharts/select-simple-pie.png new file mode 100644 index 000000000..ee8bdbb35 Binary files /dev/null and b/e2e/summary.spec.ts-snapshots_apexcharts/select-simple-pie.png differ diff --git a/e2e/summary.spec.ts-snapshots_apexcharts/select-simple-table.png b/e2e/summary.spec.ts-snapshots_apexcharts/select-simple-table.png new file mode 100644 index 000000000..f388d2184 Binary files /dev/null and b/e2e/summary.spec.ts-snapshots_apexcharts/select-simple-table.png differ diff --git a/e2e/summary.spec.ts-snapshots_apexcharts/select-simple-vbar.png b/e2e/summary.spec.ts-snapshots_apexcharts/select-simple-vbar.png new file mode 100644 index 000000000..75f527ad4 Binary files /dev/null and b/e2e/summary.spec.ts-snapshots_apexcharts/select-simple-vbar.png differ diff --git a/e2e/summary.spec.ts-snapshots_apexcharts/text-simple-table.png b/e2e/summary.spec.ts-snapshots_apexcharts/text-simple-table.png new file mode 100644 index 000000000..c6a6a64ca Binary files /dev/null and b/e2e/summary.spec.ts-snapshots_apexcharts/text-simple-table.png differ diff --git a/e2e/summary.spec.ts-snapshots_apexcharts/text-simple-wordcloud.png b/e2e/summary.spec.ts-snapshots_apexcharts/text-simple-wordcloud.png new file mode 100644 index 000000000..174e2a6e1 Binary files /dev/null and b/e2e/summary.spec.ts-snapshots_apexcharts/text-simple-wordcloud.png differ diff --git a/e2e/summary/basetests.spec.ts b/e2e/summary/basetests.spec.ts index 7e405bdd8..a700357b1 100644 --- a/e2e/summary/basetests.spec.ts +++ b/e2e/summary/basetests.spec.ts @@ -1,5 +1,5 @@ import { test, expect, Page } from "@playwright/test"; -import { url_summary, initSummary, dragDropElement } from "../helper"; +import { url_summary, initSummary, dragDropElement, getListItemByText } from "../helper"; const json = { elements: [ @@ -53,17 +53,16 @@ test.describe("basetests", () => { } const questionTitle = "Question 1"; - const questionSelector = page.locator("#summaryContainer .sa-question div", { hasText: questionTitle }); - const showDropdown = page.locator("#summaryContainer .sa-question__select").first(); + const questionSelector = page.locator("#summaryContainer .sa-question .sa-question__content", { hasText: questionTitle }); + const showQuestionDropdown = page.locator("#summaryContainer .sa-action-dropdown-header").first(); await expect(questionSelector).toBeVisible(); - await questionSelector.locator("span", { hasText: "Hide" }).click(); + await questionSelector.locator(".sa-question__hide-action").click(); await expect(questionSelector).not.toBeVisible(); expect(await isVisibleInState(page, questionTitle)).toBeFalsy(); - // await showDropdown.click(); - // await showDropdown.locator("option", { hasText: questionTitle }).click(); - await showDropdown.selectOption(questionTitle); + await showQuestionDropdown.click(); + await getListItemByText(page, questionTitle).click(); await expect(questionSelector).toBeVisible(); expect(await isVisibleInState(page, questionTitle)).toBeTruthy(); }); @@ -83,8 +82,8 @@ test.describe("basetests", () => { renderedElement: {}, }, ]); - const q1 = page.locator("#summaryContainer .sa-question div", { hasText: "Question 1" }); - const q2 = page.locator("#summaryContainer .sa-question div", { hasText: "Question 2" }); + const q1 = page.locator("#summaryContainer .sa-question .sa-question__content", { hasText: "Question 1" }); + const q2 = page.locator("#summaryContainer .sa-question .sa-question__content", { hasText: "Question 2" }); await expect(q1).not.toBeVisible(); await expect(q2).toBeVisible(); }); @@ -97,7 +96,7 @@ test.describe("basetests", () => { }, title); } const questionTitle = "Question 1"; - const questionSelector = page.locator("#summaryContainer .sa-question div", { hasText: questionTitle }); + const questionSelector = page.locator("#summaryContainer .sa-question .sa-question__content", { hasText: questionTitle }); expect(await getPositionInState(page, questionTitle)).toBe(0); // await questionSelector.locator(".sa-question__title").hover({ force: true }); @@ -107,7 +106,7 @@ test.describe("basetests", () => { // await page.waitForTimeout(500); // await page.mouse.up(); // await page.waitForTimeout(500); - await dragDropElement(page, questionSelector.locator(".sa-question__title"), page.locator("#summaryContainer .sa-panel__content")); + await dragDropElement(page, questionSelector.locator(".sa-question__header--draggable"), page.locator("#summaryContainer .sa-panel__content")); expect(await getPositionInState(page, questionTitle)).toBe(1); }); @@ -115,15 +114,15 @@ test.describe("basetests", () => { test("check filtering data", async ({ page }) => { const questionTitle = "Question 1"; const secondQuestionTitle = "Question 2"; - const questionSelector = page.locator("#summaryContainer .sa-question div", { hasText: questionTitle }); - const secondQuestionSelector = page.locator("#summaryContainer .sa-question div", { hasText: secondQuestionTitle }); + const questionSelector = page.locator("#summaryContainer .sa-question .sa-question__content", { hasText: questionTitle }); + const secondQuestionSelector = page.locator("#summaryContainer .sa-question .sa-question__content", { hasText: secondQuestionTitle }); // await questionSelector.locator("[data-unformatted='Yes
66.7%']").click(); await page.getByRole("img").filter({ hasText: "Yes66.67%No33.33%" }).locator("path").first().click({ position: { x: 125, y: 125 } }); await expect(questionSelector.locator("[data-unformatted='No
33.33%']")).not.toBeVisible(); await expect(secondQuestionSelector.locator("[data-unformatted='Yes
33.33%']")).not.toBeVisible(); - await questionSelector.locator("span", { hasText: "Clear" }).click(); + await questionSelector.locator(".sa-question__filter .sa-toolbar__button").click(); await expect(questionSelector.locator("[data-unformatted='No
33.33%']")).toBeVisible(); await expect(secondQuestionSelector.locator("[data-unformatted='Yes
33.33%']")).toBeVisible(); }); diff --git a/e2e/summary/localization.spec.ts b/e2e/summary/localization.spec.ts index 0115c54e3..96e8d3337 100644 --- a/e2e/summary/localization.spec.ts +++ b/e2e/summary/localization.spec.ts @@ -1,5 +1,5 @@ import { test, expect } from "@playwright/test"; -import { url_summary, initSummary, getYAxisValues } from "../helper"; +import { url_summary, initSummary, getYAxisValues, getListItemByText } from "../helper"; const json = { locale: "ru", @@ -57,10 +57,9 @@ test.describe("localization", () => { expect(title).toBe(json.questions[0].title.ru); // Change locale to English - const changeLocaleDropdown = page.locator(".sa-question__select", { hasText: "Русский" }); - await changeLocaleDropdown.selectOption("en"); - // await changeLocaleDropdown.click(); - // await page.locator(".sa-question__select option", { hasText: "English" }).click(); + const changeLocaleDropdown = page.locator(".sa-dropdown", { hasText: "Русский" }); + await changeLocaleDropdown.click(); + await getListItemByText(page, "English").click(); // Check Y axis values in English const yAxisValuesEn = await getYAxisValues(page); @@ -71,7 +70,7 @@ test.describe("localization", () => { expect(titleEn).toBe(json.questions[0].title.default); // Check dropdown shows English - await expect(page.locator(".sa-question__select", { hasText: "English" })).toHaveCount(1); + await expect(page.locator(".sa-dropdown", { hasText: "English" })).toHaveCount(1); // Check locale in state const localeInState = await page.evaluate(() => (window as any).visPanel.state.locale); @@ -84,6 +83,6 @@ test.describe("localization", () => { const yAxisValues = await getYAxisValues(page); expect(yAxisValues).toEqual(json.questions[0].choices.map((choice) => choice.text.default + " ").reverse()); - await expect(page.locator(".sa-question__select", { hasText: "English" })).toHaveCount(1); + await expect(page.locator(".sa-dropdown", { hasText: "English" })).toHaveCount(1); }); }); \ No newline at end of file diff --git a/e2e/summary/matrix.spec.ts b/e2e/summary/matrix.spec.ts index a4c4ac198..66e2a11a8 100644 --- a/e2e/summary/matrix.spec.ts +++ b/e2e/summary/matrix.spec.ts @@ -86,15 +86,19 @@ test.describe("matrix", () => { }; // check that percentages aren't shown - await expect(page.locator(".trace.bars .point text")).toHaveCount(0); + // await expect(page.locator(".trace.bars .point text")).toHaveCount(0); + await expect(await getValuesInsideBars(1)).toEqual(["2", "1"].reverse()); + await expect(await getValuesInsideBars(2)).toEqual(["1", "2"].reverse()); // check that percentages are shown when button is clicked - await page.click("span:has-text('Show percentages')"); + await page.getByText("Show %").click(); await expect(await getValuesInsideBars(1)).toEqual(["2 (66.67%)", "1 (33.33%)"].reverse()); await expect(await getValuesInsideBars(2)).toEqual(["1 (33.33%)", "2 (66.67%)"].reverse()); // check that percentage are hidden when button is double-clicked - await page.click("span:has-text('Hide percentages')"); - await expect(page.locator(".trace.bars .point text")).toHaveCount(0); + await page.getByText("Show %").click(); + // await expect(page.locator(".trace.bars .point text")).toHaveCount(0); + await expect(await getValuesInsideBars(1)).toEqual(["2", "1"].reverse()); + await expect(await getValuesInsideBars(2)).toEqual(["1", "2"].reverse()); }); }); \ No newline at end of file diff --git a/e2e/summary/selectbase.spec.ts b/e2e/summary/selectbase.spec.ts index 091bfd281..b4ee03984 100644 --- a/e2e/summary/selectbase.spec.ts +++ b/e2e/summary/selectbase.spec.ts @@ -1,5 +1,5 @@ import { test, expect, Page } from "@playwright/test"; -import { url_summary, initSummary, RGBToHex, getYAxisValues } from "../helper"; +import { url_summary, initSummary, RGBToHex, getYAxisValues, getListItemByText } from "../helper"; let json = { elements: [ @@ -46,13 +46,14 @@ test.describe("selectbase", () => { // check data filtering for regular choice // await page.locator(".trace.bars .point").nth(1).click(); - await page.locator(".nsewdrag").click({ position: { x: 100, y: 60 } }); //selector for choice with value 1 + const box = await page.locator(".nsewdrag").boundingBox(); + await page.mouse.click(box.x + 100, box.y + 10); //selector for choice with value 1 await page.waitForTimeout(500); - expect(await isBarVisible(3)).toBeFalsy(); expect(await isBarVisible(1)).toBeFalsy(); - expect(await isBarVisible(2)).toBeTruthy(); + expect(await isBarVisible(2)).toBeFalsy(); + expect(await isBarVisible(3)).toBeTruthy(); - await page.click('span:text("Clear")'); + await page.locator(".sa-question__filter .sa-toolbar__button").click(); await page.waitForTimeout(500); expect(await isBarVisible(3)).toBeTruthy(); expect(await isBarVisible(2)).toBeTruthy(); @@ -60,13 +61,13 @@ test.describe("selectbase", () => { // check data filtering for other choice // await page.locator(".trace.bars .point").nth(0).click(); - await page.locator(".nsewdrag").click({ position: { x: 100, y: 100 } }); //selector for 'other' choice + await page.mouse.click(box.x + 100, box.y + box.height - 20); //selector for 'other' choice await page.waitForTimeout(500); - expect(await isBarVisible(3)).toBeFalsy(); - expect(await isBarVisible(2)).toBeFalsy(); expect(await isBarVisible(1)).toBeTruthy(); + expect(await isBarVisible(2)).toBeFalsy(); + expect(await isBarVisible(3)).toBeFalsy(); - await page.click('span:text("Clear")'); + await page.locator(".sa-question__filter .sa-toolbar__button").click(); await page.waitForTimeout(500); expect(await isBarVisible(3)).toBeTruthy(); expect(await isBarVisible(2)).toBeTruthy(); @@ -93,16 +94,18 @@ test.describe("selectbase", () => { await initSummary(page, json, data, options); // check that percentages aren't shown - await expect(page.locator(".trace.bars .point text")).not.toBeVisible(); + // await expect(page.locator(".trace.bars .point text")).not.toBeVisible(); + await expect(await getValuesInsideBars()).toEqual(["2", "1", "2"].reverse()); // check that percentages are shown when button is clicked - await page.click('span:text("Show percentages")'); + await page.getByText("Show %").click(); const valuesInsideBars = await getValuesInsideBars(); expect(valuesInsideBars).toEqual(["2 (40%)", "1 (20%)", "2 (40%)"]); // check that percentage are hided when button is double-clicked - await page.click('span:text("Hide percentages")'); - await expect(page.locator(".trace.bars .point text")).not.toBeVisible(); + await page.getByText("Show %").click(); + // await expect(page.locator(".trace.bars .point text")).not.toBeVisible(); + await expect(await getValuesInsideBars()).toEqual(["2", "1", "2"].reverse()); }); test("check comment actions", async ({ page }) => { @@ -118,24 +121,26 @@ test.describe("selectbase", () => { await initSummary(page, json, data, options); // check that comment's footer doesn't exists - await expect(page.locator(".sa-visualizer__footer-content")).not.toBeVisible(); + await expect(page.locator(".sa-visualizer__footer .sa-visualizer__content")).not.toBeVisible(); // check comment's actions await page.click('.sa-visualizer__footer span:text("Show")'); - await expect(page.locator(".sa-visualizer__footer-content")).toBeVisible(); + await expect(page.locator(".sa-visualizer__footer .sa-visualizer__content")).toBeVisible(); // check that wordcloud exists - await expect(page.locator(".sa-visualizer__footer-content .sa-visualizer-wordcloud")).toHaveCount(1); + await expect(page.locator(".sa-visualizer__footer .sa-visualizer__content .sa-visualizer-wordcloud")).toHaveCount(1); // check comment's table - await page.locator("div").filter({ hasText: /^WordcloudTexts in tablecommenttext$/ }).getByRole("combobox").selectOption("text"); + await page.locator(".sa-dropdown").nth(3).click(); + await getListItemByText(page, "Texts in table").click(); + await page.waitForTimeout(100); const cells = await getTableCells(); expect(cells).toEqual(["Comment text", "Another comment text"]); // check that comment's footer is hided await page.click('.sa-visualizer__footer span:text("Hide")'); - await expect(page.locator(".sa-visualizer__footer-content")).not.toBeVisible(); + await expect(page.locator(".sa-visualizer__footer .sa-visualizer__content")).not.toBeVisible(); }); test("check sign when there is no comment data", async ({ page }) => { @@ -175,20 +180,27 @@ test.describe("selectbase", () => { ]; await initSummary(page, json, data, options); - const orderingSelect = page.locator("select").nth(3); + const orderingSelect = page.locator(".sa-dropdown").nth(2); + const color1 = "#84cad4"; + const color2 = "#3a99fb"; + const color3 = "#ff6771"; // check default order expect(await getYAxisValues(page)).toEqual(["Other ", "Two ", "One "]); - expect((await getColorsOrder()).map(RGBToHex)).toEqual(["#86e1fb", "#3999fb", "#ff6771"]); + expect((await getColorsOrder()).map(RGBToHex)).toEqual([color1, color2, color3]); // check ascending order - await orderingSelect.selectOption("asc"); + await orderingSelect.click(); + await getListItemByText(page, "Ascending").click(); + expect(await getYAxisValues(page)).toEqual(["One ", "Other ", "Two "]); - expect((await getColorsOrder()).map(RGBToHex)).toEqual(["#ff6771", "#86e1fb", "#3999fb"]); + expect((await getColorsOrder()).map(RGBToHex)).toEqual([color3, color1, color2]); // check descending order - await orderingSelect.selectOption("desc"); + await orderingSelect.click(); + await getListItemByText(page, "Descending").click(); + expect(await getYAxisValues(page)).toEqual(["Two ", "Other ", "One "]); - expect((await getColorsOrder()).map(RGBToHex)).toEqual(["#3999fb", "#86e1fb", "#ff6771"]); + expect((await getColorsOrder()).map(RGBToHex)).toEqual([color2, color1, color3]); }); }); \ No newline at end of file diff --git a/e2e/summary/text.spec.ts b/e2e/summary/text.spec.ts index 46e90cba2..decdf31d0 100644 --- a/e2e/summary/text.spec.ts +++ b/e2e/summary/text.spec.ts @@ -1,5 +1,5 @@ import { test, expect } from "@playwright/test"; -import { initSummary, url_summary } from "../helper"; +import { getListItemByText, initSummary, url_summary } from "../helper"; const json = { elements: [ @@ -23,7 +23,8 @@ test.describe("text", () => { await initSummary(page, json, data, options); // Select "Texts in table" from the dropdown - await page.locator(".sa-question__select").nth(1).selectOption({ label: "Texts in table" }); + await page.locator(".sa-dropdown").click(); + await getListItemByText(page, "Texts in table").click(); // Get all table cell values const cells = await page.evaluate(() => { diff --git a/e2e/tabulator/basetests.spec.ts b/e2e/tabulator/basetests.spec.ts index 062071b07..2ff65d9af 100644 --- a/e2e/tabulator/basetests.spec.ts +++ b/e2e/tabulator/basetests.spec.ts @@ -23,8 +23,8 @@ test.describe("basetests", () => { const xssText = "Which of the following best describes you or your organization?"; // Selectors adapted for Playwright - const headerSelector = ".tabulator-headers div:nth-of-type(6) span"; - const cellSelector = ".tabulator-row div:nth-of-type(6)"; + const headerSelector = ".tabulator-headers div:nth-of-type(7) span"; + const cellSelector = ".tabulator-row div:nth-of-type(7)"; const headerText = await page.locator(headerSelector).first().innerText(); const cellText = await page.locator(cellSelector).first().innerText(); diff --git a/e2e/tabulator/columnactions.spec.ts b/e2e/tabulator/columnactions.spec.ts index db3925011..d3bbe851d 100644 --- a/e2e/tabulator/columnactions.spec.ts +++ b/e2e/tabulator/columnactions.spec.ts @@ -1,5 +1,5 @@ import { test, expect, Page } from "@playwright/test"; -import { dragDropElement, initTabulator, url_tabulator } from "../helper"; +import { dragDropElement, getListItemByText, initTabulator, url_tabulator } from "../helper"; test.describe("columnactions", () => { test.beforeEach(async ({ page }) => { @@ -47,7 +47,7 @@ test.describe("columnactions", () => { // "#tabulatorContainer .sa-table__show-column.sa-table__header-extension", // { label: "Question 1" } // ); - await page.getByRole("combobox").first().selectOption("Question 1"); + await getListItemByText(page, "Question 1").click(); await expect(page.locator("#tabulatorContainer .tabulator-col-title", { hasText: "Question 1" })).toBeVisible(); await expect(await getColumnsVisibilityArray()).toEqual([true, true, true]); }); @@ -61,22 +61,22 @@ test.describe("columnactions", () => { await expect(page.locator('#tabulatorContainer .tabulator-col[tabulator-field="bool"]')).toBeVisible(); await expect(await getColumnsLocationsArray()).toEqual([0, 0, 0]); - await page.click('#tabulatorContainer .tabulator-row:nth-child(1) button[title="Show minor columns"]'); + await page.click('#tabulatorContainer .tabulator-row:nth-child(1) .sa-table__svg-button[title="Show minor columns"]'); await expect(page.locator("#tabulatorContainer td", { hasText: "Question 1" })).toHaveCount(0); - await page.click('#tabulatorContainer .tabulator-col[tabulator-field="bool"] button[title="Move to Detail"]'); + await page.click('#tabulatorContainer .tabulator-col[tabulator-field="bool"] .sa-table__svg-button[title="Move to Detail"]'); await expect(page.locator('#tabulatorContainer .tabulator-col[tabulator-field="bool"]')).not.toBeVisible(); - await page.click('#tabulatorContainer .tabulator-row:nth-child(1) button[title="Show minor columns"]'); + await page.click('#tabulatorContainer .tabulator-row:nth-child(1) .sa-table__svg-button[title="Show minor columns"]'); await expect(page.locator("#tabulatorContainer td", { hasText: "Question 1" })).toBeVisible(); await expect(page.locator("#tabulatorContainer td", { hasText: "Yes" })).toBeVisible(); await expect(await getColumnsLocationsArray()).toEqual([1, 0, 0]); - await page.click('#tabulatorContainer button:has-text("Show as Column")'); + await page.click('#tabulatorContainer .tabulator-row:nth-child(1) .sa-table__svg-button[title="Show as Column"]'); await expect(page.locator('#tabulatorContainer .tabulator-col[tabulator-field="bool"]')).toBeVisible(); await expect(await getColumnsLocationsArray()).toEqual([0, 0, 0]); - await page.click('#tabulatorContainer .tabulator-row:nth-child(1) button[title="Show minor columns"]'); + await page.click('#tabulatorContainer .tabulator-row:nth-child(1) .sa-table__svg-button[title="Show minor columns"]'); await expect(page.locator("#tabulatorContainer td", { hasText: "Question 1" })).toHaveCount(0); }); @@ -85,7 +85,7 @@ test.describe("columnactions", () => { await page.evaluate(() => { const names: string[] = []; document.querySelectorAll(".tabulator .tabulator-col").forEach((col) => names.push((col as HTMLElement).innerText)); - names.splice(0, 1); + names.splice(0, 2); return names; }); @@ -143,7 +143,7 @@ test.describe("columnactions", () => { await page.evaluate(() => { const names: string[] = []; document.querySelectorAll(".tabulator .tabulator-col").forEach((col) => names.push((col as HTMLElement).innerText)); - names.splice(0, 1); + names.splice(0, 2); return names; }); @@ -152,7 +152,7 @@ test.describe("columnactions", () => { await expect(page.locator("#tabulatorContainer .tabulator-col", { hasText: "Question 2" })).not.toBeVisible(); const columnSelector = page.locator("#tabulatorContainer .sa-table__show-column.sa-table__header-extension"); - await expect(columnSelector.locator("option")).not.toHaveCount(0); + await expect(columnSelector.locator(".sa-action-dropdown-item")).not.toHaveCount(0); await page.click('#tabulatorContainer .tabulator-row:nth-child(1) button[title="Show minor columns"]'); await expect(page.locator("#tabulatorContainer td", { hasText: "Question 2" })).toBeVisible(); diff --git a/e2e/tabulator/headeractions.spec.ts b/e2e/tabulator/headeractions.spec.ts index 782035d67..af0fac803 100644 --- a/e2e/tabulator/headeractions.spec.ts +++ b/e2e/tabulator/headeractions.spec.ts @@ -1,5 +1,5 @@ import { test, expect } from "@playwright/test"; -import { url_tabulator, initTabulator } from "../helper"; +import { url_tabulator, initTabulator, getListItemByText } from "../helper"; test.describe("headeractions", () => { test.beforeEach(async ({ page }) => { @@ -32,15 +32,15 @@ test.describe("headeractions", () => { await expect(page.locator("#tabulatorContainer .tabulator-table")).toHaveCount(1); await expect(page.locator("#tabulatorContainer .tabulator-table").locator(".tabulator-row")).toHaveCount(5); - await page.click(".sa-table__entries select"); - await page.selectOption(".sa-table__entries select", { label: "1" }); + await page.locator(".sa-table__entries .sa-action-dropdown-header").click(); + await getListItemByText(page, "1").click(); await expect(page.locator("#tabulatorContainer .tabulator-table").locator(".tabulator-row")).toHaveCount(1); const pageSize1 = await page.evaluate(() => (window as any).surveyAnalyticsTabulator.state.pageSize); expect(pageSize1).toBe(1); - await page.click(".sa-table__entries select"); - await page.selectOption(".sa-table__entries select", { label: "10" }); + await page.locator(".sa-table__entries .sa-action-dropdown-header").click(); + await getListItemByText(page, "10").click(); await expect(page.locator("#tabulatorContainer .tabulator-table").locator(".tabulator-row")).toHaveCount(9); const pageSize10 = await page.evaluate(() => (window as any).surveyAnalyticsTabulator.state.pageSize); @@ -75,7 +75,7 @@ test.describe("headeractions", () => { await expect(page.locator("#tabulatorContainer .tabulator-row").nth(2)).toHaveText("Полностью устраивает"); await page.click('#tabulatorContainer .sa-table__header-extension:has-text("Сменить язык")'); - await page.getByRole("combobox").first().selectOption("en"); + await getListItemByText(page, "English").click(); await expect(page.locator("#tabulatorContainer span", { hasText: "How satisfied are you with the Product?" })).toHaveText("How satisfied are you with the Product?"); await expect(page.locator("#tabulatorContainer .tabulator-row").nth(0)).toHaveText("Not Satisfied"); @@ -109,7 +109,7 @@ test.describe("headeractions", () => { await initTabulator(page, json, data, { actionsColumnWidth: 100 }, { pageSize: 10 }); await expect(page.locator("#tabulatorContainer .tabulator-table").locator(".tabulator-row")).toHaveCount(9); - await expect(page.locator(".sa-table__entries select")).toHaveValue("10"); + await expect(page.locator(".sa-table__entries .sa-action-dropdown-header")).toHaveText("10"); }); test("Check locale from state", async ({ page }) => { diff --git a/e2e/toolbar.spec.ts b/e2e/toolbar.spec.ts new file mode 100644 index 000000000..985234d24 --- /dev/null +++ b/e2e/toolbar.spec.ts @@ -0,0 +1,84 @@ +import { test } from "@playwright/test"; +import { compareScreenshot, resetFocusToBody } from "./helper"; + +process.env.SNAPSHOT_SUFFIX = undefined; +process.env.SNAPSHOT_SUFFIX = ""; + +test.describe("Toolbar visualizers", () => { + test("Toolbar visualizer", async ({ page }) => { + await page.goto("http://localhost:8080/examples/histogram_apexcharts.html"); + + const visLocator = page.locator(".sa-question__content").first(); + const dropdownPopupLocator = page.locator(".sa-dropdown-list.sa-dropdown--opened").filter({ visible: true }).first(); + const mask = [ + page.locator(".apexcharts-canvas") + ]; + + await page.setViewportSize({ width: 900, height: 1000 }); + await compareScreenshot(page, visLocator, "visualizer-toolbar.png", mask); + + await page.locator(".sa-dropdown").first().click(); + await compareScreenshot(page, dropdownPopupLocator, "visualizer-toolbar-popup.png"); + await page.locator(".sa-dropdown").first().click(); + + await page.setViewportSize({ width: 500, height: 1000 }); + await resetFocusToBody(page); + await compareScreenshot(page, visLocator, "visualizer-toolbar-mobile-view.png", mask); + + await page.locator(".sa-dropdown").first().click(); + await compareScreenshot(page, dropdownPopupLocator, "visualizer-toolbar-mobile-view-popup.png"); + }); + + test("Toolbar visualizer if disable the layout engine", async ({ page }) => { + await page.goto("http://localhost:8080/examples/disable_layout_engine_apexcharts.html"); + + const visLocator = page.locator(".sa-question__content").first(); + const mask = [ + page.locator(".apexcharts-canvas") + ]; + + await page.setViewportSize({ width: 900, height: 1000 }); + await compareScreenshot(page, visLocator, "visualizer-toolbar-disable-layout-engine.png", mask); + + await page.setViewportSize({ width: 500, height: 1000 }); + await compareScreenshot(page, visLocator, "visualizer-toolbar-disable-layout-engine-mobile-view.png", mask); + }); + + test("Custom date range toolbar", async ({ page }) => { + await page.goto("http://localhost:8080/examples/date_period_field_name_apexcharts.html"); + + const toolbarLocator = page.locator(".sa-panel__header").first(); + + await page.setViewportSize({ width: 1200, height: 1000 }); + await compareScreenshot(page, toolbarLocator, "custom-date-range-toolbar-desktop.png"); + + await page.setViewportSize({ width: 700, height: 1000 }); + await compareScreenshot(page, toolbarLocator, "custom-date-range-toolbar-tablet.png"); + + await page.setViewportSize({ width: 500, height: 1000 }); + await compareScreenshot(page, toolbarLocator, "custom-date-range-toolbar-mobile.png"); + }); + + test("Custom date range toolbar with validation error", async ({ page }) => { + await page.goto("http://localhost:8080/examples/date_period_field_name_apexcharts.html"); + + const toolbarLocator = page.locator(".sa-panel__header").first(); + const dateInput = page.locator(".sa-date-range_editor input").first(); + const dateValue = (new Date(2025, 9, 17)).toISOString().split("T")[0]; + + await dateInput.dispatchEvent("focus"); + await dateInput.fill(dateValue); + await dateInput.dispatchEvent("change"); + await dateInput.dispatchEvent("blur"); + + await page.setViewportSize({ width: 1200, height: 1000 }); + await compareScreenshot(page, toolbarLocator, "custom-date-range-toolbar-with-error-desktop.png"); + + await page.setViewportSize({ width: 700, height: 1000 }); + await compareScreenshot(page, toolbarLocator, "custom-date-range-toolbar-with-error-tablet.png"); + + await page.setViewportSize({ width: 500, height: 1000 }); + await compareScreenshot(page, toolbarLocator, "custom-date-range-toolbar-with-error-mobile.png"); + }); + +}); diff --git a/e2e/toolbar.spec.ts-snapshots/custom-date-range-toolbar-desktop.png b/e2e/toolbar.spec.ts-snapshots/custom-date-range-toolbar-desktop.png new file mode 100644 index 000000000..83d713109 Binary files /dev/null and b/e2e/toolbar.spec.ts-snapshots/custom-date-range-toolbar-desktop.png differ diff --git a/e2e/toolbar.spec.ts-snapshots/custom-date-range-toolbar-mobile.png b/e2e/toolbar.spec.ts-snapshots/custom-date-range-toolbar-mobile.png new file mode 100644 index 000000000..0a0d17cb7 Binary files /dev/null and b/e2e/toolbar.spec.ts-snapshots/custom-date-range-toolbar-mobile.png differ diff --git a/e2e/toolbar.spec.ts-snapshots/custom-date-range-toolbar-tablet.png b/e2e/toolbar.spec.ts-snapshots/custom-date-range-toolbar-tablet.png new file mode 100644 index 000000000..1ed3c0876 Binary files /dev/null and b/e2e/toolbar.spec.ts-snapshots/custom-date-range-toolbar-tablet.png differ diff --git a/e2e/toolbar.spec.ts-snapshots/custom-date-range-toolbar-with-error-desktop.png b/e2e/toolbar.spec.ts-snapshots/custom-date-range-toolbar-with-error-desktop.png new file mode 100644 index 000000000..3e92f65de Binary files /dev/null and b/e2e/toolbar.spec.ts-snapshots/custom-date-range-toolbar-with-error-desktop.png differ diff --git a/e2e/toolbar.spec.ts-snapshots/custom-date-range-toolbar-with-error-mobile.png b/e2e/toolbar.spec.ts-snapshots/custom-date-range-toolbar-with-error-mobile.png new file mode 100644 index 000000000..4466e6a23 Binary files /dev/null and b/e2e/toolbar.spec.ts-snapshots/custom-date-range-toolbar-with-error-mobile.png differ diff --git a/e2e/toolbar.spec.ts-snapshots/custom-date-range-toolbar-with-error-tablet.png b/e2e/toolbar.spec.ts-snapshots/custom-date-range-toolbar-with-error-tablet.png new file mode 100644 index 000000000..4885eee06 Binary files /dev/null and b/e2e/toolbar.spec.ts-snapshots/custom-date-range-toolbar-with-error-tablet.png differ diff --git a/e2e/toolbar.spec.ts-snapshots/visualizer-toolbar-disable-layout-engine-mobile-view.png b/e2e/toolbar.spec.ts-snapshots/visualizer-toolbar-disable-layout-engine-mobile-view.png new file mode 100644 index 000000000..63d53d768 Binary files /dev/null and b/e2e/toolbar.spec.ts-snapshots/visualizer-toolbar-disable-layout-engine-mobile-view.png differ diff --git a/e2e/toolbar.spec.ts-snapshots/visualizer-toolbar-disable-layout-engine.png b/e2e/toolbar.spec.ts-snapshots/visualizer-toolbar-disable-layout-engine.png new file mode 100644 index 000000000..72c839b48 Binary files /dev/null and b/e2e/toolbar.spec.ts-snapshots/visualizer-toolbar-disable-layout-engine.png differ diff --git a/e2e/toolbar.spec.ts-snapshots/visualizer-toolbar-mobile-view-popup.png b/e2e/toolbar.spec.ts-snapshots/visualizer-toolbar-mobile-view-popup.png new file mode 100644 index 000000000..3a865b2ee Binary files /dev/null and b/e2e/toolbar.spec.ts-snapshots/visualizer-toolbar-mobile-view-popup.png differ diff --git a/e2e/toolbar.spec.ts-snapshots/visualizer-toolbar-mobile-view.png b/e2e/toolbar.spec.ts-snapshots/visualizer-toolbar-mobile-view.png new file mode 100644 index 000000000..f7f2522d0 Binary files /dev/null and b/e2e/toolbar.spec.ts-snapshots/visualizer-toolbar-mobile-view.png differ diff --git a/e2e/toolbar.spec.ts-snapshots/visualizer-toolbar-popup.png b/e2e/toolbar.spec.ts-snapshots/visualizer-toolbar-popup.png new file mode 100644 index 000000000..924045129 Binary files /dev/null and b/e2e/toolbar.spec.ts-snapshots/visualizer-toolbar-popup.png differ diff --git a/e2e/toolbar.spec.ts-snapshots/visualizer-toolbar.png b/e2e/toolbar.spec.ts-snapshots/visualizer-toolbar.png new file mode 100644 index 000000000..ebf85c61a Binary files /dev/null and b/e2e/toolbar.spec.ts-snapshots/visualizer-toolbar.png differ diff --git a/examples/apexcharts.js b/examples/apexcharts.js new file mode 100644 index 000000000..2fb0149fb --- /dev/null +++ b/examples/apexcharts.js @@ -0,0 +1,37 @@ +/*! + * ApexCharts v5.3.5 + * (c) 2018-2025 ApexCharts + */ +!function(t,e){"object"==typeof exports&&"undefined"!=typeof module?module.exports=e():"function"==typeof define&&define.amd?define(e):(t="undefined"!=typeof globalThis?globalThis:t||self).ApexCharts=e()}(this,(function(){"use strict";function t(t,e){(null==e||e>t.length)&&(e=t.length);for(var i=0,a=Array(e);i=t.length?{done:!0}:{done:!1,value:t[a++]}},e:function(t){throw t},f:s}}throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}var r,n=!0,o=!1;return{s:function(){i=i.call(t)},n:function(){var t=i.next();return n=t.done,t},e:function(t){o=!0,r=t},f:function(){try{n||null==i.return||i.return()}finally{if(o)throw r}}}}function n(t){var i=c();return function(){var a,s=l(t);if(i){var r=l(this).constructor;a=Reflect.construct(s,arguments,r)}else a=s.apply(this,arguments);return function(t,i){if(i&&("object"==typeof i||"function"==typeof i))return i;if(void 0!==i)throw new TypeError("Derived constructors may only return object or undefined");return e(t)}(this,a)}}function o(t,e,i){return(e=x(e))in t?Object.defineProperty(t,e,{value:i,enumerable:!0,configurable:!0,writable:!0}):t[e]=i,t}function l(t){return l=Object.setPrototypeOf?Object.getPrototypeOf.bind():function(t){return t.__proto__||Object.getPrototypeOf(t)},l(t)}function h(t,e){if("function"!=typeof e&&null!==e)throw new TypeError("Super expression must either be null or a function");t.prototype=Object.create(e&&e.prototype,{constructor:{value:t,writable:!0,configurable:!0}}),Object.defineProperty(t,"prototype",{writable:!1}),e&&g(t,e)}function c(){try{var t=!Boolean.prototype.valueOf.call(Reflect.construct(Boolean,[],(function(){})))}catch(t){}return(c=function(){return!!t})()}function d(t,e){var i=Object.keys(t);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(t);e&&(a=a.filter((function(e){return Object.getOwnPropertyDescriptor(t,e).enumerable}))),i.push.apply(i,a)}return i}function u(t){for(var e=1;e>16,n=i>>8&255,o=255&i;return"#"+(16777216+65536*(Math.round((a-r)*s)+r)+256*(Math.round((a-n)*s)+n)+(Math.round((a-o)*s)+o)).toString(16).slice(1)}},{key:"shadeColor",value:function(e,i){return t.isColorHex(i)?this.shadeHexColor(e,i):this.shadeRGBColor(e,i)}}],[{key:"bind",value:function(t,e){return function(){return t.apply(e,arguments)}}},{key:"isObject",value:function(t){return t&&"object"===b(t)&&!Array.isArray(t)&&null!=t}},{key:"is",value:function(t,e){return Object.prototype.toString.call(e)==="[object "+t+"]"}},{key:"isSafari",value:function(){return/^((?!chrome|android).)*safari/i.test(navigator.userAgent)}},{key:"listToArray",value:function(t){var e,i=[];for(e=0;e1&&void 0!==arguments[1]?arguments[1]:new WeakMap;if(null===t||"object"!==b(t))return t;if(i.has(t))return i.get(t);if(Array.isArray(t)){e=[],i.set(t,e);for(var a=0;a1&&void 0!==arguments[1]?arguments[1]:2;return Number.isInteger(t)?t:parseFloat(t.toPrecision(e))}},{key:"randomId",value:function(){return(Math.random()+1).toString(36).substring(4)}},{key:"noExponents",value:function(t){return t.toString().includes("e")?Math.round(t):t}},{key:"elementExists",value:function(t){return!(!t||!t.isConnected)}},{key:"getDimensions",value:function(t){var e=getComputedStyle(t,null),i=t.clientHeight,a=t.clientWidth;return i-=parseFloat(e.paddingTop)+parseFloat(e.paddingBottom),[a-=parseFloat(e.paddingLeft)+parseFloat(e.paddingRight),i]}},{key:"getBoundingClientRect",value:function(t){var e=t.getBoundingClientRect();return{top:e.top,right:e.right,bottom:e.bottom,left:e.left,width:t.clientWidth,height:t.clientHeight,x:e.left,y:e.top}}},{key:"getLargestStringFromArr",value:function(t){return t.reduce((function(t,e){return Array.isArray(e)&&(e=e.reduce((function(t,e){return t.length>e.length?t:e}))),t.length>e.length?t:e}),0)}},{key:"hexToRgba",value:function(){var t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:"#999999",e=arguments.length>1&&void 0!==arguments[1]?arguments[1]:.6;"#"!==t.substring(0,1)&&(t="#999999");var i=t.replace("#","");i=i.match(new RegExp("(.{"+i.length/3+"})","g"));for(var a=0;a1&&void 0!==arguments[1]?arguments[1]:"x",i=t.toString().slice();return i=i.replace(/[` ~!@#$%^&*()|+\=?;:'",.<>{}[\]\\/]/gi,e)}},{key:"negToZero",value:function(t){return t<0?0:t}},{key:"moveIndexInArray",value:function(t,e,i){if(i>=t.length)for(var a=i-t.length+1;a--;)t.push(void 0);return t.splice(i,0,t.splice(e,1)[0]),t}},{key:"extractNumber",value:function(t){return parseFloat(t.replace(/[^\d.]*/g,""))}},{key:"findAncestor",value:function(t,e){for(;(t=t.parentElement)&&!t.classList.contains(e););return t}},{key:"setELstyles",value:function(t,e){for(var i in e)e.hasOwnProperty(i)&&(t.style.key=e[i])}},{key:"preciseAddition",value:function(t,e){var i=(String(t).split(".")[1]||"").length,a=(String(e).split(".")[1]||"").length,s=Math.pow(10,Math.max(i,a));return(Math.round(t*s)+Math.round(e*s))/s}},{key:"isNumber",value:function(t){return!isNaN(t)&&parseFloat(Number(t))===t&&!isNaN(parseInt(t,10))}},{key:"isFloat",value:function(t){return Number(t)===t&&t%1!=0}},{key:"isMsEdge",value:function(){var t=window.navigator.userAgent,e=t.indexOf("Edge/");return e>0&&parseInt(t.substring(e+5,t.indexOf(".",e)),10)}},{key:"getGCD",value:function(t,e){var i=arguments.length>2&&void 0!==arguments[2]?arguments[2]:7,a=Math.pow(10,i-Math.floor(Math.log10(Math.max(t,e))));for(t=Math.round(Math.abs(t)*a),e=Math.round(Math.abs(e)*a);e;){var s=e;e=t%e,t=s}return t/a}},{key:"getPrimeFactors",value:function(t){for(var e=[],i=2;t>=2;)t%i==0?(e.push(i),t/=i):i++;return e}},{key:"mod",value:function(t,e){var i=arguments.length>2&&void 0!==arguments[2]?arguments[2]:7,a=Math.pow(10,i-Math.floor(Math.log10(Math.max(t,e))));return(t=Math.round(Math.abs(t)*a))%(e=Math.round(Math.abs(e)*a))/a}}]),t}(),y=function(){function t(e){i(this,t),this.ctx=e,this.w=e.w}return s(t,[{key:"animateLine",value:function(t,e,i,a){t.attr(e).animate(a).attr(i)}},{key:"animateMarker",value:function(t,e,i,a){t.attr({opacity:0}).animate(e).attr({opacity:1}).after((function(){a()}))}},{key:"animateRect",value:function(t,e,i,a,s){t.attr(e).animate(a).attr(i).after((function(){return s()}))}},{key:"animatePathsGradually",value:function(t){var e=t.el,i=t.realIndex,a=t.j,s=t.fill,r=t.pathFrom,n=t.pathTo,o=t.speed,l=t.delay,h=this.w,c=0;h.config.chart.animations.animateGradually.enabled&&(c=h.config.chart.animations.animateGradually.delay),h.config.chart.animations.dynamicAnimation.enabled&&h.globals.dataChanged&&"bar"!==h.config.chart.type&&(c=0),this.morphSVG(e,i,a,"line"!==h.config.chart.type||h.globals.comboCharts?s:"stroke",r,n,o,l*c)}},{key:"showDelayedElements",value:function(){this.w.globals.delayedElements.forEach((function(t){var e=t.el;e.classList.remove("apexcharts-element-hidden"),e.classList.add("apexcharts-hidden-element-shown")}))}},{key:"animationCompleted",value:function(t){var e=this.w;e.globals.animationEnded||(e.globals.animationEnded=!0,this.showDelayedElements(),"function"==typeof e.config.chart.events.animationEnd&&e.config.chart.events.animationEnd(this.ctx,{el:t,w:e}))}},{key:"morphSVG",value:function(t,e,i,a,s,r,n,o){var l=this,h=this.w;s||(s=t.attr("pathFrom")),r||(r=t.attr("pathTo"));var c=function(t){return"radar"===h.config.chart.type&&(n=1),"M 0 ".concat(h.globals.gridHeight)};(!s||s.indexOf("undefined")>-1||s.indexOf("NaN")>-1)&&(s=c()),(!r.trim()||r.indexOf("undefined")>-1||r.indexOf("NaN")>-1)&&(r=c()),h.globals.shouldAnimate||(n=1),t.plot(s).animate(1,o).plot(s).animate(n,o).plot(r).after((function(){v.isNumber(i)?i===h.globals.series[h.globals.maxValsInArrayIndex].length-2&&h.globals.shouldAnimate&&l.animationCompleted(t):"none"!==a&&h.globals.shouldAnimate&&(!h.globals.comboCharts&&e===h.globals.series.length-1||h.globals.comboCharts)&&l.animationCompleted(t),l.showDelayedElements()}))}}]),t}();const w={},k=[];function A(t,e){if(Array.isArray(t))for(const i of t)A(i,e);else if("object"!=typeof t)S(Object.getOwnPropertyNames(e)),w[t]=Object.assign(w[t]||{},e);else for(const e in t)A(e,t[e])}function C(t){return w[t]||{}}function S(t){k.push(...t)}function L(t,e){let i;const a=t.length,s=[];for(i=0;iz.has(t.nodeName),R=(t,e,i={})=>{const a={...e};for(const t in a)a[t].valueOf()===i[t]&&delete a[t];Object.keys(a).length?t.node.setAttribute("data-svgjs",JSON.stringify(a)):(t.node.removeAttribute("data-svgjs"),t.node.removeAttribute("svgjs:data"))},E="http://www.w3.org/2000/svg",Y="http://www.w3.org/2000/xmlns/",H="http://www.w3.org/1999/xlink",O={window:"undefined"==typeof window?null:window,document:"undefined"==typeof document?null:document};function F(){return O.window}let D=class{};const _={},N="___SYMBOL___ROOT___";function W(t,e=E){return O.document.createElementNS(e,t)}function B(t,e=!1){if(t instanceof D)return t;if("object"==typeof t)return U(t);if(null==t)return new _[N];if("string"==typeof t&&"<"!==t.charAt(0))return U(O.document.querySelector(t));const i=e?O.document.createElement("div"):W("svg");return i.innerHTML=t,t=U(i.firstChild),i.removeChild(i.firstChild),t}function G(t,e){return e&&(e instanceof O.window.Node||e.ownerDocument&&e instanceof e.ownerDocument.defaultView.Node)?e:W(t)}function V(t){if(!t)return null;if(t.instance instanceof D)return t.instance;if("#document-fragment"===t.nodeName)return new _.Fragment(t);let e=P(t.nodeName||"Dom");return"LinearGradient"===e||"RadialGradient"===e?e="Gradient":_[e]||(e="Dom"),new _[e](t)}let U=V;function q(t,e=t.name,i=!1){return _[e]=t,i&&(_[N]=t),S(Object.getOwnPropertyNames(t.prototype)),t}let Z=1e3;function $(t){return"Svgjs"+P(t)+Z++}function J(t){for(let e=t.children.length-1;e>=0;e--)J(t.children[e]);return t.id?(t.id=$(t.nodeName),t):t}function Q(t,e){let i,a;for(a=(t=Array.isArray(t)?t:[t]).length-1;a>=0;a--)for(i in e)t[a].prototype[i]=e[i]}function K(t){return function(...e){const i=e[e.length-1];return!i||i.constructor!==Object||i instanceof Array?t.apply(this,e):t.apply(this,e.slice(0,-1)).attr(i)}}A("Dom",{siblings:function(){return this.parent().children()},position:function(){return this.parent().index(this)},next:function(){return this.siblings()[this.position()+1]},prev:function(){return this.siblings()[this.position()-1]},forward:function(){const t=this.position();return this.parent().add(this.remove(),t+1),this},backward:function(){const t=this.position();return this.parent().add(this.remove(),t?t-1:0),this},front:function(){return this.parent().add(this.remove()),this},back:function(){return this.parent().add(this.remove(),0),this},before:function(t){(t=B(t)).remove();const e=this.position();return this.parent().add(t,e),this},after:function(t){(t=B(t)).remove();const e=this.position();return this.parent().add(t,e+1),this},insertBefore:function(t){return(t=B(t)).before(this),this},insertAfter:function(t){return(t=B(t)).after(this),this}});const tt=/^([+-]?(\d+(\.\d*)?|\.\d+)(e[+-]?\d+)?)([a-z%]*)$/i,et=/^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i,it=/rgb\((\d+),(\d+),(\d+)\)/,at=/(#[a-z_][a-z0-9\-_]*)/i,st=/\)\s*,?\s*/,rt=/\s/g,nt=/^#[a-f0-9]{3}$|^#[a-f0-9]{6}$/i,ot=/^rgb\(/,lt=/^(\s+)?$/,ht=/^[+-]?(\d+(\.\d*)?|\.\d+)(e[+-]?\d+)?$/i,ct=/\.(jpg|jpeg|png|gif|svg)(\?[^=]+.*)?/i,dt=/[\s,]+/,ut=/[MLHVCSQTAZ]/i;function gt(t){const e=Math.round(t),i=Math.max(0,Math.min(255,e)).toString(16);return 1===i.length?"0"+i:i}function pt(t,e){for(let i=e.length;i--;)if(null==t[e[i]])return!1;return!0}function ft(t,e,i){return i<0&&(i+=1),i>1&&(i-=1),i<1/6?t+6*(e-t)*i:i<.5?e:i<2/3?t+(e-t)*(2/3-i)*6:t}A("Dom",{classes:function(){const t=this.attr("class");return null==t?[]:t.trim().split(dt)},hasClass:function(t){return-1!==this.classes().indexOf(t)},addClass:function(t){if(!this.hasClass(t)){const e=this.classes();e.push(t),this.attr("class",e.join(" "))}return this},removeClass:function(t){return this.hasClass(t)&&this.attr("class",this.classes().filter((function(e){return e!==t})).join(" ")),this},toggleClass:function(t){return this.hasClass(t)?this.removeClass(t):this.addClass(t)}}),A("Dom",{css:function(t,e){const i={};if(0===arguments.length)return this.node.style.cssText.split(/\s*;\s*/).filter((function(t){return!!t.length})).forEach((function(t){const e=t.split(/\s*:\s*/);i[e[0]]=e[1]})),i;if(arguments.length<2){if(Array.isArray(t)){for(const e of t){const t=e;i[e]=this.node.style.getPropertyValue(t)}return i}if("string"==typeof t)return this.node.style.getPropertyValue(t);if("object"==typeof t)for(const e in t)this.node.style.setProperty(e,null==t[e]||lt.test(t[e])?"":t[e])}return 2===arguments.length&&this.node.style.setProperty(t,null==e||lt.test(e)?"":e),this},show:function(){return this.css("display","")},hide:function(){return this.css("display","none")},visible:function(){return"none"!==this.css("display")}}),A("Dom",{data:function(t,e,i){if(null==t)return this.data(L(function(t,e){let i;const a=t.length,s=[];for(i=0;i0===t.nodeName.indexOf("data-"))),(t=>t.nodeName.slice(5))));if(t instanceof Array){const e={};for(const i of t)e[i]=this.data(i);return e}if("object"==typeof t)for(e in t)this.data(e,t[e]);else if(arguments.length<2)try{return JSON.parse(this.attr("data-"+t))}catch(e){return this.attr("data-"+t)}else this.attr("data-"+t,null===e?null:!0===i||"string"==typeof e||"number"==typeof e?e:JSON.stringify(e));return this}}),A("Dom",{remember:function(t,e){if("object"==typeof arguments[0])for(const e in t)this.remember(e,t[e]);else{if(1===arguments.length)return this.memory()[t];this.memory()[t]=e}return this},forget:function(){if(0===arguments.length)this._memory={};else for(let t=arguments.length-1;t>=0;t--)delete this.memory()[arguments[t]];return this},memory:function(){return this._memory=this._memory||{}}});class xt{constructor(...t){this.init(...t)}static isColor(t){return t&&(t instanceof xt||this.isRgb(t)||this.test(t))}static isRgb(t){return t&&"number"==typeof t.r&&"number"==typeof t.g&&"number"==typeof t.b}static random(t="vibrant",e){const{random:i,round:a,sin:s,PI:r}=Math;if("vibrant"===t){const t=24*i()+57,e=38*i()+45,a=360*i();return new xt(t,e,a,"lch")}if("sine"===t){const t=a(80*s(2*r*(e=null==e?i():e)/.5+.01)+150),n=a(50*s(2*r*e/.5+4.6)+200),o=a(100*s(2*r*e/.5+2.3)+150);return new xt(t,n,o)}if("pastel"===t){const t=8*i()+86,e=17*i()+9,a=360*i();return new xt(t,e,a,"lch")}if("dark"===t){const t=10+10*i(),e=50*i()+86,a=360*i();return new xt(t,e,a,"lch")}if("rgb"===t){const t=255*i(),e=255*i(),a=255*i();return new xt(t,e,a)}if("lab"===t){const t=100*i(),e=256*i()-128,a=256*i()-128;return new xt(t,e,a,"lab")}if("grey"===t){const t=255*i();return new xt(t,t,t)}throw new Error("Unsupported random color mode")}static test(t){return"string"==typeof t&&(nt.test(t)||ot.test(t))}cmyk(){const{_a:t,_b:e,_c:i}=this.rgb(),[a,s,r]=[t,e,i].map((t=>t/255)),n=Math.min(1-a,1-s,1-r);if(1===n)return new xt(0,0,0,1,"cmyk");return new xt((1-a-n)/(1-n),(1-s-n)/(1-n),(1-r-n)/(1-n),n,"cmyk")}hsl(){const{_a:t,_b:e,_c:i}=this.rgb(),[a,s,r]=[t,e,i].map((t=>t/255)),n=Math.max(a,s,r),o=Math.min(a,s,r),l=(n+o)/2,h=n===o,c=n-o;return new xt(360*(h?0:n===a?((s-r)/c+(s.5?c/(2-n-o):c/(n+o)),100*l,"hsl")}init(t=0,e=0,i=0,a=0,s="rgb"){if(t=t||0,this.space)for(const t in this.space)delete this[this.space[t]];if("number"==typeof t)s="string"==typeof a?a:s,a="string"==typeof a?0:a,Object.assign(this,{_a:t,_b:e,_c:i,_d:a,space:s});else if(t instanceof Array)this.space=e||("string"==typeof t[3]?t[3]:t[4])||"rgb",Object.assign(this,{_a:t[0],_b:t[1],_c:t[2],_d:t[3]||0});else if(t instanceof Object){const i=function(t,e){const i=pt(t,"rgb")?{_a:t.r,_b:t.g,_c:t.b,_d:0,space:"rgb"}:pt(t,"xyz")?{_a:t.x,_b:t.y,_c:t.z,_d:0,space:"xyz"}:pt(t,"hsl")?{_a:t.h,_b:t.s,_c:t.l,_d:0,space:"hsl"}:pt(t,"lab")?{_a:t.l,_b:t.a,_c:t.b,_d:0,space:"lab"}:pt(t,"lch")?{_a:t.l,_b:t.c,_c:t.h,_d:0,space:"lch"}:pt(t,"cmyk")?{_a:t.c,_b:t.m,_c:t.y,_d:t.k,space:"cmyk"}:{_a:0,_b:0,_c:0,space:"rgb"};return i.space=e||i.space,i}(t,e);Object.assign(this,i)}else if("string"==typeof t)if(ot.test(t)){const e=t.replace(rt,""),[i,a,s]=it.exec(e).slice(1,4).map((t=>parseInt(t)));Object.assign(this,{_a:i,_b:a,_c:s,_d:0,space:"rgb"})}else{if(!nt.test(t))throw Error("Unsupported string format, can't construct Color");{const e=t=>parseInt(t,16),[,i,a,s]=et.exec(function(t){return 4===t.length?["#",t.substring(1,2),t.substring(1,2),t.substring(2,3),t.substring(2,3),t.substring(3,4),t.substring(3,4)].join(""):t}(t)).map(e);Object.assign(this,{_a:i,_b:a,_c:s,_d:0,space:"rgb"})}}const{_a:r,_b:n,_c:o,_d:l}=this,h="rgb"===this.space?{r:r,g:n,b:o}:"xyz"===this.space?{x:r,y:n,z:o}:"hsl"===this.space?{h:r,s:n,l:o}:"lab"===this.space?{l:r,a:n,b:o}:"lch"===this.space?{l:r,c:n,h:o}:"cmyk"===this.space?{c:r,m:n,y:o,k:l}:{};Object.assign(this,h)}lab(){const{x:t,y:e,z:i}=this.xyz();return new xt(116*e-16,500*(t-e),200*(e-i),"lab")}lch(){const{l:t,a:e,b:i}=this.lab(),a=Math.sqrt(e**2+i**2);let s=180*Math.atan2(i,e)/Math.PI;s<0&&(s*=-1,s=360-s);return new xt(t,a,s,"lch")}rgb(){if("rgb"===this.space)return this;if("lab"===(t=this.space)||"xyz"===t||"lch"===t){let{x:t,y:e,z:i}=this;if("lab"===this.space||"lch"===this.space){let{l:a,a:s,b:r}=this;if("lch"===this.space){const{c:t,h:e}=this,i=Math.PI/180;s=t*Math.cos(i*e),r=t*Math.sin(i*e)}const n=(a+16)/116,o=s/500+n,l=n-r/200,h=16/116,c=.008856,d=7.787;t=.95047*(o**3>c?o**3:(o-h)/d),e=1*(n**3>c?n**3:(n-h)/d),i=1.08883*(l**3>c?l**3:(l-h)/d)}const a=3.2406*t+-1.5372*e+-.4986*i,s=-.9689*t+1.8758*e+.0415*i,r=.0557*t+-.204*e+1.057*i,n=Math.pow,o=.0031308,l=a>o?1.055*n(a,1/2.4)-.055:12.92*a,h=s>o?1.055*n(s,1/2.4)-.055:12.92*s,c=r>o?1.055*n(r,1/2.4)-.055:12.92*r;return new xt(255*l,255*h,255*c)}if("hsl"===this.space){let{h:t,s:e,l:i}=this;if(t/=360,e/=100,i/=100,0===e){i*=255;return new xt(i,i,i)}const a=i<.5?i*(1+e):i+e-i*e,s=2*i-a,r=255*ft(s,a,t+1/3),n=255*ft(s,a,t),o=255*ft(s,a,t-1/3);return new xt(r,n,o)}if("cmyk"===this.space){const{c:t,m:e,y:i,k:a}=this,s=255*(1-Math.min(1,t*(1-a)+a)),r=255*(1-Math.min(1,e*(1-a)+a)),n=255*(1-Math.min(1,i*(1-a)+a));return new xt(s,r,n)}return this;var t}toArray(){const{_a:t,_b:e,_c:i,_d:a,space:s}=this;return[t,e,i,a,s]}toHex(){const[t,e,i]=this._clamped().map(gt);return`#${t}${e}${i}`}toRgb(){const[t,e,i]=this._clamped();return`rgb(${t},${e},${i})`}toString(){return this.toHex()}xyz(){const{_a:t,_b:e,_c:i}=this.rgb(),[a,s,r]=[t,e,i].map((t=>t/255)),n=a>.04045?Math.pow((a+.055)/1.055,2.4):a/12.92,o=s>.04045?Math.pow((s+.055)/1.055,2.4):s/12.92,l=r>.04045?Math.pow((r+.055)/1.055,2.4):r/12.92,h=(.4124*n+.3576*o+.1805*l)/.95047,c=(.2126*n+.7152*o+.0722*l)/1,d=(.0193*n+.1192*o+.9505*l)/1.08883,u=h>.008856?Math.pow(h,1/3):7.787*h+16/116,g=c>.008856?Math.pow(c,1/3):7.787*c+16/116,p=d>.008856?Math.pow(d,1/3):7.787*d+16/116;return new xt(u,g,p,"xyz")}_clamped(){const{_a:t,_b:e,_c:i}=this.rgb(),{max:a,min:s,round:r}=Math;return[t,e,i].map((t=>a(0,s(r(t),255))))}}class bt{constructor(...t){this.init(...t)}clone(){return new bt(this)}init(t,e){const i=0,a=0,s=Array.isArray(t)?{x:t[0],y:t[1]}:"object"==typeof t?{x:t.x,y:t.y}:{x:t,y:e};return this.x=null==s.x?i:s.x,this.y=null==s.y?a:s.y,this}toArray(){return[this.x,this.y]}transform(t){return this.clone().transformO(t)}transformO(t){vt.isMatrixLike(t)||(t=new vt(t));const{x:e,y:i}=this;return this.x=t.a*e+t.c*i+t.e,this.y=t.b*e+t.d*i+t.f,this}}function mt(t,e,i){return Math.abs(e-t)<(i||1e-6)}class vt{constructor(...t){this.init(...t)}static formatTransforms(t){const e="both"===t.flip||!0===t.flip,i=t.flip&&(e||"x"===t.flip)?-1:1,a=t.flip&&(e||"y"===t.flip)?-1:1,s=t.skew&&t.skew.length?t.skew[0]:isFinite(t.skew)?t.skew:isFinite(t.skewX)?t.skewX:0,r=t.skew&&t.skew.length?t.skew[1]:isFinite(t.skew)?t.skew:isFinite(t.skewY)?t.skewY:0,n=t.scale&&t.scale.length?t.scale[0]*i:isFinite(t.scale)?t.scale*i:isFinite(t.scaleX)?t.scaleX*i:i,o=t.scale&&t.scale.length?t.scale[1]*a:isFinite(t.scale)?t.scale*a:isFinite(t.scaleY)?t.scaleY*a:a,l=t.shear||0,h=t.rotate||t.theta||0,c=new bt(t.origin||t.around||t.ox||t.originX,t.oy||t.originY),d=c.x,u=c.y,g=new bt(t.position||t.px||t.positionX||NaN,t.py||t.positionY||NaN),p=g.x,f=g.y,x=new bt(t.translate||t.tx||t.translateX,t.ty||t.translateY),b=x.x,m=x.y,v=new bt(t.relative||t.rx||t.relativeX,t.ry||t.relativeY);return{scaleX:n,scaleY:o,skewX:s,skewY:r,shear:l,theta:h,rx:v.x,ry:v.y,tx:b,ty:m,ox:d,oy:u,px:p,py:f}}static fromArray(t){return{a:t[0],b:t[1],c:t[2],d:t[3],e:t[4],f:t[5]}}static isMatrixLike(t){return null!=t.a||null!=t.b||null!=t.c||null!=t.d||null!=t.e||null!=t.f}static matrixMultiply(t,e,i){const a=t.a*e.a+t.c*e.b,s=t.b*e.a+t.d*e.b,r=t.a*e.c+t.c*e.d,n=t.b*e.c+t.d*e.d,o=t.e+t.a*e.e+t.c*e.f,l=t.f+t.b*e.e+t.d*e.f;return i.a=a,i.b=s,i.c=r,i.d=n,i.e=o,i.f=l,i}around(t,e,i){return this.clone().aroundO(t,e,i)}aroundO(t,e,i){const a=t||0,s=e||0;return this.translateO(-a,-s).lmultiplyO(i).translateO(a,s)}clone(){return new vt(this)}decompose(t=0,e=0){const i=this.a,a=this.b,s=this.c,r=this.d,n=this.e,o=this.f,l=i*r-a*s,h=l>0?1:-1,c=h*Math.sqrt(i*i+a*a),d=Math.atan2(h*a,h*i),u=180/Math.PI*d,g=Math.cos(d),p=Math.sin(d),f=(i*s+a*r)/l,x=s*c/(f*i-a)||r*c/(f*a+i);return{scaleX:c,scaleY:x,shear:f,rotate:u,translateX:n-t+t*g*c+e*(f*g*c-p*x),translateY:o-e+t*p*c+e*(f*p*c+g*x),originX:t,originY:e,a:this.a,b:this.b,c:this.c,d:this.d,e:this.e,f:this.f}}equals(t){if(t===this)return!0;const e=new vt(t);return mt(this.a,e.a)&&mt(this.b,e.b)&&mt(this.c,e.c)&&mt(this.d,e.d)&&mt(this.e,e.e)&&mt(this.f,e.f)}flip(t,e){return this.clone().flipO(t,e)}flipO(t,e){return"x"===t?this.scaleO(-1,1,e,0):"y"===t?this.scaleO(1,-1,0,e):this.scaleO(-1,-1,t,e||t)}init(t){const e=vt.fromArray([1,0,0,1,0,0]);return t=t instanceof Gt?t.matrixify():"string"==typeof t?vt.fromArray(t.split(dt).map(parseFloat)):Array.isArray(t)?vt.fromArray(t):"object"==typeof t&&vt.isMatrixLike(t)?t:"object"==typeof t?(new vt).transform(t):6===arguments.length?vt.fromArray([].slice.call(arguments)):e,this.a=null!=t.a?t.a:e.a,this.b=null!=t.b?t.b:e.b,this.c=null!=t.c?t.c:e.c,this.d=null!=t.d?t.d:e.d,this.e=null!=t.e?t.e:e.e,this.f=null!=t.f?t.f:e.f,this}inverse(){return this.clone().inverseO()}inverseO(){const t=this.a,e=this.b,i=this.c,a=this.d,s=this.e,r=this.f,n=t*a-e*i;if(!n)throw new Error("Cannot invert "+this);const o=a/n,l=-e/n,h=-i/n,c=t/n,d=-(o*s+h*r),u=-(l*s+c*r);return this.a=o,this.b=l,this.c=h,this.d=c,this.e=d,this.f=u,this}lmultiply(t){return this.clone().lmultiplyO(t)}lmultiplyO(t){const e=t instanceof vt?t:new vt(t);return vt.matrixMultiply(e,this,this)}multiply(t){return this.clone().multiplyO(t)}multiplyO(t){const e=t instanceof vt?t:new vt(t);return vt.matrixMultiply(this,e,this)}rotate(t,e,i){return this.clone().rotateO(t,e,i)}rotateO(t,e=0,i=0){t=M(t);const a=Math.cos(t),s=Math.sin(t),{a:r,b:n,c:o,d:l,e:h,f:c}=this;return this.a=r*a-n*s,this.b=n*a+r*s,this.c=o*a-l*s,this.d=l*a+o*s,this.e=h*a-c*s+i*s-e*a+e,this.f=c*a+h*s-e*s-i*a+i,this}scale(){return this.clone().scaleO(...arguments)}scaleO(t,e=t,i=0,a=0){3===arguments.length&&(a=i,i=e,e=t);const{a:s,b:r,c:n,d:o,e:l,f:h}=this;return this.a=s*t,this.b=r*e,this.c=n*t,this.d=o*e,this.e=l*t-i*t+i,this.f=h*e-a*e+a,this}shear(t,e,i){return this.clone().shearO(t,e,i)}shearO(t,e=0,i=0){const{a:a,b:s,c:r,d:n,e:o,f:l}=this;return this.a=a+s*t,this.c=r+n*t,this.e=o+l*t-i*t,this}skew(){return this.clone().skewO(...arguments)}skewO(t,e=t,i=0,a=0){3===arguments.length&&(a=i,i=e,e=t),t=M(t),e=M(e);const s=Math.tan(t),r=Math.tan(e),{a:n,b:o,c:l,d:h,e:c,f:d}=this;return this.a=n+o*s,this.b=o+n*r,this.c=l+h*s,this.d=h+l*r,this.e=c+d*s-a*s,this.f=d+c*r-i*r,this}skewX(t,e,i){return this.skew(t,0,e,i)}skewY(t,e,i){return this.skew(0,t,e,i)}toArray(){return[this.a,this.b,this.c,this.d,this.e,this.f]}toString(){return"matrix("+this.a+","+this.b+","+this.c+","+this.d+","+this.e+","+this.f+")"}transform(t){if(vt.isMatrixLike(t)){return new vt(t).multiplyO(this)}const e=vt.formatTransforms(t),{x:i,y:a}=new bt(e.ox,e.oy).transform(this),s=(new vt).translateO(e.rx,e.ry).lmultiplyO(this).translateO(-i,-a).scaleO(e.scaleX,e.scaleY).skewO(e.skewX,e.skewY).shearO(e.shear).rotateO(e.theta).translateO(i,a);if(isFinite(e.px)||isFinite(e.py)){const t=new bt(i,a).transform(s),r=isFinite(e.px)?e.px-t.x:0,n=isFinite(e.py)?e.py-t.y:0;s.translateO(r,n)}return s.translateO(e.tx,e.ty),s}translate(t,e){return this.clone().translateO(t,e)}translateO(t,e){return this.e+=t||0,this.f+=e||0,this}valueOf(){return{a:this.a,b:this.b,c:this.c,d:this.d,e:this.e,f:this.f}}}function yt(){if(!yt.nodes){const t=B().size(2,0);t.node.style.cssText=["opacity: 0","position: absolute","left: -100%","top: -100%","overflow: hidden"].join(";"),t.attr("focusable","false"),t.attr("aria-hidden","true");const e=t.path().node;yt.nodes={svg:t,path:e}}if(!yt.nodes.svg.node.parentNode){const t=O.document.body||O.document.documentElement;yt.nodes.svg.addTo(t)}return yt.nodes}function wt(t){return!(t.width||t.height||t.x||t.y)}q(vt,"Matrix");class kt{constructor(...t){this.init(...t)}addOffset(){return this.x+=O.window.pageXOffset,this.y+=O.window.pageYOffset,new kt(this)}init(t){return t="string"==typeof t?t.split(dt).map(parseFloat):Array.isArray(t)?t:"object"==typeof t?[null!=t.left?t.left:t.x,null!=t.top?t.top:t.y,t.width,t.height]:4===arguments.length?[].slice.call(arguments):[0,0,0,0],this.x=t[0]||0,this.y=t[1]||0,this.width=this.w=t[2]||0,this.height=this.h=t[3]||0,this.x2=this.x+this.w,this.y2=this.y+this.h,this.cx=this.x+this.w/2,this.cy=this.y+this.h/2,this}isNulled(){return wt(this)}merge(t){const e=Math.min(this.x,t.x),i=Math.min(this.y,t.y),a=Math.max(this.x+this.width,t.x+t.width)-e,s=Math.max(this.y+this.height,t.y+t.height)-i;return new kt(e,i,a,s)}toArray(){return[this.x,this.y,this.width,this.height]}toString(){return this.x+" "+this.y+" "+this.width+" "+this.height}transform(t){t instanceof vt||(t=new vt(t));let e=1/0,i=-1/0,a=1/0,s=-1/0;return[new bt(this.x,this.y),new bt(this.x2,this.y),new bt(this.x,this.y2),new bt(this.x2,this.y2)].forEach((function(r){r=r.transform(t),e=Math.min(e,r.x),i=Math.max(i,r.x),a=Math.min(a,r.y),s=Math.max(s,r.y)})),new kt(e,a,i-e,s-a)}}function At(t,e,i){let a;try{if(a=e(t.node),wt(a)&&((s=t.node)!==O.document&&!(O.document.documentElement.contains||function(t){for(;t.parentNode;)t=t.parentNode;return t===O.document}).call(O.document.documentElement,s)))throw new Error("Element not in the dom")}catch(e){a=i(t)}var s;return a}A({viewbox:{viewbox(t,e,i,a){return null==t?new kt(this.attr("viewBox")):this.attr("viewBox",new kt(t,e,i,a))},zoom(t,e){let{width:i,height:a}=this.attr(["width","height"]);if((i||a)&&"string"!=typeof i&&"string"!=typeof a||(i=this.node.clientWidth,a=this.node.clientHeight),!i||!a)throw new Error("Impossible to get absolute width and height. Please provide an absolute width and height attribute on the zooming element");const s=this.viewbox(),r=i/s.width,n=a/s.height,o=Math.min(r,n);if(null==t)return o;let l=o/t;l===1/0&&(l=Number.MAX_SAFE_INTEGER/100),e=e||new bt(i/2/r+s.x,a/2/n+s.y);const h=new kt(s).transform(new vt({scale:l,origin:e}));return this.viewbox(h)}}}),q(kt,"Box");class Ct extends Array{constructor(t=[],...e){if(super(t,...e),"number"==typeof t)return this;this.length=0,this.push(...t)}}Q([Ct],{each(t,...e){return"function"==typeof t?this.map(((e,i,a)=>t.call(e,e,i,a))):this.map((i=>i[t](...e)))},toArray(){return Array.prototype.concat.apply([],this)}});const St=["toArray","constructor","each"];function Lt(t,e){return new Ct(L((e||O.document).querySelectorAll(t),(function(t){return V(t)})))}Ct.extend=function(t){t=t.reduce(((t,e)=>(St.includes(e)||"_"===e[0]||(e in Array.prototype&&(t["$"+e]=Array.prototype[e]),t[e]=function(...t){return this.each(e,...t)}),t)),{}),Q([Ct],t)};let Mt=0;const Pt={};function It(t){let e=t.getEventHolder();return e===O.window&&(e=Pt),e.events||(e.events={}),e.events}function Tt(t){return t.getEventTarget()}function zt(t,e,i,a,s){const r=i.bind(a||t),n=B(t),o=It(n),l=Tt(n);e=Array.isArray(e)?e:e.split(dt),i._svgjsListenerId||(i._svgjsListenerId=++Mt),e.forEach((function(t){const e=t.split(".")[0],a=t.split(".")[1]||"*";o[e]=o[e]||{},o[e][a]=o[e][a]||{},o[e][a][i._svgjsListenerId]=r,l.addEventListener(e,r,s||!1)}))}function Xt(t,e,i,a){const s=B(t),r=It(s),n=Tt(s);("function"!=typeof i||(i=i._svgjsListenerId))&&(e=Array.isArray(e)?e:(e||"").split(dt)).forEach((function(t){const e=t&&t.split(".")[0],o=t&&t.split(".")[1];let l,h;if(i)r[e]&&r[e][o||"*"]&&(n.removeEventListener(e,r[e][o||"*"][i],a||!1),delete r[e][o||"*"][i]);else if(e&&o){if(r[e]&&r[e][o]){for(h in r[e][o])Xt(n,[e,o].join("."),h);delete r[e][o]}}else if(o)for(t in r)for(l in r[t])o===l&&Xt(n,[t,o].join("."));else if(e){if(r[e]){for(l in r[e])Xt(n,[e,l].join("."));delete r[e]}}else{for(t in r)Xt(n,t);!function(t){let e=t.getEventHolder();e===O.window&&(e=Pt),e.events&&(e.events={})}(s)}}))}class Rt extends D{addEventListener(){}dispatch(t,e,i){return function(t,e,i,a){const s=Tt(t);return e instanceof O.window.Event||(e=new O.window.CustomEvent(e,{detail:i,cancelable:!0,...a})),s.dispatchEvent(e),e}(this,t,e,i)}dispatchEvent(t){const e=this.getEventHolder().events;if(!e)return!0;const i=e[t.type];for(const e in i)for(const a in i[e])i[e][a](t);return!t.defaultPrevented}fire(t,e,i){return this.dispatch(t,e,i),this}getEventHolder(){return this}getEventTarget(){return this}off(t,e,i){return Xt(this,t,e,i),this}on(t,e,i,a){return zt(this,t,e,i,a),this}removeEventListener(){}}function Et(){}q(Rt,"EventTarget");const Yt=400,Ht=">",Ot=0,Ft={"fill-opacity":1,"stroke-opacity":1,"stroke-width":0,"stroke-linejoin":"miter","stroke-linecap":"butt",fill:"#000000",stroke:"#000000",opacity:1,x:0,y:0,cx:0,cy:0,width:0,height:0,r:0,rx:0,ry:0,offset:0,"stop-opacity":1,"stop-color":"#000000","text-anchor":"start"};class Dt extends Array{constructor(...t){super(...t),this.init(...t)}clone(){return new this.constructor(this)}init(t){return"number"==typeof t||(this.length=0,this.push(...this.parse(t))),this}parse(t=[]){return t instanceof Array?t:t.trim().split(dt).map(parseFloat)}toArray(){return Array.prototype.concat.apply([],this)}toSet(){return new Set(this)}toString(){return this.join(" ")}valueOf(){const t=[];return t.push(...this),t}}class _t{constructor(...t){this.init(...t)}convert(t){return new _t(this.value,t)}divide(t){return t=new _t(t),new _t(this/t,this.unit||t.unit)}init(t,e){return e=Array.isArray(t)?t[1]:e,t=Array.isArray(t)?t[0]:t,this.value=0,this.unit=e||"","number"==typeof t?this.value=isNaN(t)?0:isFinite(t)?t:t<0?-34e37:34e37:"string"==typeof t?(e=t.match(tt))&&(this.value=parseFloat(e[1]),"%"===e[5]?this.value/=100:"s"===e[5]&&(this.value*=1e3),this.unit=e[5]):t instanceof _t&&(this.value=t.valueOf(),this.unit=t.unit),this}minus(t){return t=new _t(t),new _t(this-t,this.unit||t.unit)}plus(t){return t=new _t(t),new _t(this+t,this.unit||t.unit)}times(t){return t=new _t(t),new _t(this*t,this.unit||t.unit)}toArray(){return[this.value,this.unit]}toJSON(){return this.toString()}toString(){return("%"===this.unit?~~(1e8*this.value)/1e6:"s"===this.unit?this.value/1e3:this.value)+this.unit}valueOf(){return this.value}}const Nt=new Set(["fill","stroke","color","bgcolor","stop-color","flood-color","lighting-color"]),Wt=[];class Bt extends Rt{constructor(t,e){super(),this.node=t,this.type=t.nodeName,e&&t!==e&&this.attr(e)}add(t,e){return(t=B(t)).removeNamespace&&this.node instanceof O.window.SVGElement&&t.removeNamespace(),null==e?this.node.appendChild(t.node):t.node!==this.node.childNodes[e]&&this.node.insertBefore(t.node,this.node.childNodes[e]),this}addTo(t,e){return B(t).put(this,e)}children(){return new Ct(L(this.node.children,(function(t){return V(t)})))}clear(){for(;this.node.hasChildNodes();)this.node.removeChild(this.node.lastChild);return this}clone(t=!0,e=!0){this.writeDataToDom();let i=this.node.cloneNode(t);return e&&(i=J(i)),new this.constructor(i)}each(t,e){const i=this.children();let a,s;for(a=0,s=i.length;a=0}html(t,e){return this.xml(t,e,"http://www.w3.org/1999/xhtml")}id(t){return void 0!==t||this.node.id||(this.node.id=$(this.type)),this.attr("id",t)}index(t){return[].slice.call(this.node.childNodes).indexOf(t.node)}last(){return V(this.node.lastChild)}matches(t){const e=this.node,i=e.matches||e.matchesSelector||e.msMatchesSelector||e.mozMatchesSelector||e.webkitMatchesSelector||e.oMatchesSelector||null;return i&&i.call(e,t)}parent(t){let e=this;if(!e.node.parentNode)return null;if(e=V(e.node.parentNode),!t)return e;do{if("string"==typeof t?e.matches(t):e instanceof t)return e}while(e=V(e.node.parentNode));return e}put(t,e){return t=B(t),this.add(t,e),t}putIn(t,e){return B(t).add(this,e)}remove(){return this.parent()&&this.parent().removeElement(this),this}removeElement(t){return this.node.removeChild(t.node),this}replace(t){return t=B(t),this.node.parentNode&&this.node.parentNode.replaceChild(t.node,this.node),t}round(t=2,e=null){const i=10**t,a=this.attr(e);for(const t in a)"number"==typeof a[t]&&(a[t]=Math.round(a[t]*i)/i);return this.attr(a),this}svg(t,e){return this.xml(t,e,E)}toString(){return this.id()}words(t){return this.node.textContent=t,this}wrap(t){const e=this.parent();if(!e)return this.addTo(t);const i=e.index(this);return e.put(t,i).put(this)}writeDataToDom(){return this.each((function(){this.writeDataToDom()})),this}xml(t,e,i){if("boolean"==typeof t&&(i=e,e=t,t=null),null==t||"function"==typeof t){e=null==e||e,this.writeDataToDom();let i=this;if(null!=t){if(i=V(i.node.cloneNode(!0)),e){const e=t(i);if(i=e||i,!1===e)return""}i.each((function(){const e=t(this),i=e||this;!1===e?this.remove():e&&this!==i&&this.replace(i)}),!0)}return e?i.node.outerHTML:i.node.innerHTML}e=null!=e&&e;const a=W("wrapper",i),s=O.document.createDocumentFragment();a.innerHTML=t;for(let t=a.children.length;t--;)s.appendChild(a.firstElementChild);const r=this.parent();return e?this.replace(s)&&r:this.add(s)}}Q(Bt,{attr:function(t,e,i){if(null==t){t={},e=this.node.attributes;for(const i of e)t[i.nodeName]=ht.test(i.nodeValue)?parseFloat(i.nodeValue):i.nodeValue;return t}if(t instanceof Array)return t.reduce(((t,e)=>(t[e]=this.attr(e),t)),{});if("object"==typeof t&&t.constructor===Object)for(e in t)this.attr(e,t[e]);else if(null===e)this.node.removeAttribute(t);else{if(null==e)return null==(e=this.node.getAttribute(t))?Ft[t]:ht.test(e)?parseFloat(e):e;"number"==typeof(e=Wt.reduce(((e,i)=>i(t,e,this)),e))?e=new _t(e):Nt.has(t)&&xt.isColor(e)?e=new xt(e):e.constructor===Array&&(e=new Dt(e)),"leading"===t?this.leading&&this.leading(e):"string"==typeof i?this.node.setAttributeNS(i,t,e.toString()):this.node.setAttribute(t,e.toString()),!this.rebuild||"font-size"!==t&&"x"!==t||this.rebuild()}return this},find:function(t){return Lt(t,this.node)},findOne:function(t){return V(this.node.querySelector(t))}}),q(Bt,"Dom");let Gt=class extends Bt{constructor(t,e){super(t,e),this.dom={},this.node.instance=this,(t.hasAttribute("data-svgjs")||t.hasAttribute("svgjs:data"))&&this.setData(JSON.parse(t.getAttribute("data-svgjs"))??JSON.parse(t.getAttribute("svgjs:data"))??{})}center(t,e){return this.cx(t).cy(e)}cx(t){return null==t?this.x()+this.width()/2:this.x(t-this.width()/2)}cy(t){return null==t?this.y()+this.height()/2:this.y(t-this.height()/2)}defs(){const t=this.root();return t&&t.defs()}dmove(t,e){return this.dx(t).dy(e)}dx(t=0){return this.x(new _t(t).plus(this.x()))}dy(t=0){return this.y(new _t(t).plus(this.y()))}getEventHolder(){return this}height(t){return this.attr("height",t)}move(t,e){return this.x(t).y(e)}parents(t=this.root()){const e="string"==typeof t;e||(t=B(t));const i=new Ct;let a=this;for(;(a=a.parent())&&a.node!==O.document&&"#document-fragment"!==a.nodeName&&(i.push(a),e||a.node!==t.node)&&(!e||!a.matches(t));)if(a.node===this.root().node)return null;return i}reference(t){if(!(t=this.attr(t)))return null;const e=(t+"").match(at);return e?B(e[1]):null}root(){const t=this.parent(function(t){return _[t]}(N));return t&&t.root()}setData(t){return this.dom=t,this}size(t,e){const i=I(this,t,e);return this.width(new _t(i.width)).height(new _t(i.height))}width(t){return this.attr("width",t)}writeDataToDom(){return R(this,this.dom),super.writeDataToDom()}x(t){return this.attr("x",t)}y(t){return this.attr("y",t)}};Q(Gt,{bbox:function(){const t=At(this,(t=>t.getBBox()),(t=>{try{const e=t.clone().addTo(yt().svg).show(),i=e.node.getBBox();return e.remove(),i}catch(e){throw new Error(`Getting bbox of element "${t.node.nodeName}" is not possible: ${e.toString()}`)}}));return new kt(t)},rbox:function(t){const e=At(this,(t=>t.getBoundingClientRect()),(t=>{throw new Error(`Getting rbox of element "${t.node.nodeName}" is not possible`)})),i=new kt(e);return t?i.transform(t.screenCTM().inverseO()):i.addOffset()},inside:function(t,e){const i=this.bbox();return t>i.x&&e>i.y&&t=0;i--)null!=e[jt[t][i]]&&this.attr(jt.prefix(t,jt[t][i]),e[jt[t][i]]);return this},A(["Element","Runner"],e)})),A(["Element","Runner"],{matrix:function(t,e,i,a,s,r){return null==t?new vt(this):this.attr("transform",new vt(t,e,i,a,s,r))},rotate:function(t,e,i){return this.transform({rotate:t,ox:e,oy:i},!0)},skew:function(t,e,i,a){return 1===arguments.length||3===arguments.length?this.transform({skew:t,ox:e,oy:i},!0):this.transform({skew:[t,e],ox:i,oy:a},!0)},shear:function(t,e,i){return this.transform({shear:t,ox:e,oy:i},!0)},scale:function(t,e,i,a){return 1===arguments.length||3===arguments.length?this.transform({scale:t,ox:e,oy:i},!0):this.transform({scale:[t,e],ox:i,oy:a},!0)},translate:function(t,e){return this.transform({translate:[t,e]},!0)},relative:function(t,e){return this.transform({relative:[t,e]},!0)},flip:function(t="both",e="center"){return-1==="xybothtrue".indexOf(t)&&(e=t,t="both"),this.transform({flip:t,origin:e},!0)},opacity:function(t){return this.attr("opacity",t)}}),A("radius",{radius:function(t,e=t){return"radialGradient"===(this._element||this).type?this.attr("r",new _t(t)):this.rx(t).ry(e)}}),A("Path",{length:function(){return this.node.getTotalLength()},pointAt:function(t){return new bt(this.node.getPointAtLength(t))}}),A(["Element","Runner"],{font:function(t,e){if("object"==typeof t){for(e in t)this.font(e,t[e]);return this}return"leading"===t?this.leading(e):"anchor"===t?this.attr("text-anchor",e):"size"===t||"family"===t||"weight"===t||"stretch"===t||"variant"===t||"style"===t?this.attr("font-"+t,e):this.attr(t,e)}});A("Element",["click","dblclick","mousedown","mouseup","mouseover","mouseout","mousemove","mouseenter","mouseleave","touchstart","touchmove","touchleave","touchend","touchcancel","contextmenu","wheel","pointerdown","pointermove","pointerup","pointerleave","pointercancel"].reduce((function(t,e){return t[e]=function(t){return null===t?this.off(e):this.on(e,t),this},t}),{})),A("Element",{untransform:function(){return this.attr("transform",null)},matrixify:function(){const t=(this.attr("transform")||"").split(st).slice(0,-1).map((function(t){const e=t.trim().split("(");return[e[0],e[1].split(dt).map((function(t){return parseFloat(t)}))]})).reverse().reduce((function(t,e){return"matrix"===e[0]?t.lmultiply(vt.fromArray(e[1])):t[e[0]].apply(t,e[1])}),new vt);return t},toParent:function(t,e){if(this===t)return this;if(X(this.node))return this.addTo(t,e);const i=this.screenCTM(),a=t.screenCTM().inverse();return this.addTo(t,e).untransform().transform(a.multiply(i)),this},toRoot:function(t){return this.toParent(this.root(),t)},transform:function(t,e){if(null==t||"string"==typeof t){const e=new vt(this).decompose();return null==t?e:e[t]}vt.isMatrixLike(t)||(t={...t,origin:T(t,this)});const i=new vt(!0===e?this:e||!1).transform(t);return this.attr("transform",i)}});class Vt extends Gt{flatten(){return this.each((function(){if(this instanceof Vt)return this.flatten().ungroup()})),this}ungroup(t=this.parent(),e=t.index(this)){return e=-1===e?t.children().length:e,this.each((function(i,a){return a[a.length-i-1].toParent(t,e)})),this.remove()}}q(Vt,"Container");class Ut extends Vt{constructor(t,e=t){super(G("defs",t),e)}flatten(){return this}ungroup(){return this}}q(Ut,"Defs");class qt extends Gt{}function Zt(t){return this.attr("rx",t)}function $t(t){return this.attr("ry",t)}function Jt(t){return null==t?this.cx()-this.rx():this.cx(t+this.rx())}function Qt(t){return null==t?this.cy()-this.ry():this.cy(t+this.ry())}function Kt(t){return this.attr("cx",t)}function te(t){return this.attr("cy",t)}function ee(t){return null==t?2*this.rx():this.rx(new _t(t).divide(2))}function ie(t){return null==t?2*this.ry():this.ry(new _t(t).divide(2))}q(qt,"Shape");var ae=Object.freeze({__proto__:null,cx:Kt,cy:te,height:ie,rx:Zt,ry:$t,width:ee,x:Jt,y:Qt});class se extends qt{constructor(t,e=t){super(G("ellipse",t),e)}size(t,e){const i=I(this,t,e);return this.rx(new _t(i.width).divide(2)).ry(new _t(i.height).divide(2))}}Q(se,ae),A("Container",{ellipse:K((function(t=0,e=t){return this.put(new se).size(t,e).move(0,0)}))}),q(se,"Ellipse");class re extends Bt{constructor(t=O.document.createDocumentFragment()){super(t)}xml(t,e,i){if("boolean"==typeof t&&(i=e,e=t,t=null),null==t||"function"==typeof t){const t=new Bt(W("wrapper",i));return t.add(this.node.cloneNode(!0)),t.xml(!1,i)}return super.xml(t,!1,i)}}function ne(t,e){return"radialGradient"===(this._element||this).type?this.attr({fx:new _t(t),fy:new _t(e)}):this.attr({x1:new _t(t),y1:new _t(e)})}function oe(t,e){return"radialGradient"===(this._element||this).type?this.attr({cx:new _t(t),cy:new _t(e)}):this.attr({x2:new _t(t),y2:new _t(e)})}q(re,"Fragment");var le=Object.freeze({__proto__:null,from:ne,to:oe});class he extends Vt{constructor(t,e){super(G(t+"Gradient","string"==typeof t?null:t),e)}attr(t,e,i){return"transform"===t&&(t="gradientTransform"),super.attr(t,e,i)}bbox(){return new kt}targets(){return Lt("svg [fill*="+this.id()+"]")}toString(){return this.url()}update(t){return this.clear(),"function"==typeof t&&t.call(this,this),this}url(){return"url(#"+this.id()+")"}}Q(he,le),A({Container:{gradient(...t){return this.defs().gradient(...t)}},Defs:{gradient:K((function(t,e){return this.put(new he(t)).update(e)}))}}),q(he,"Gradient");class ce extends Vt{constructor(t,e=t){super(G("pattern",t),e)}attr(t,e,i){return"transform"===t&&(t="patternTransform"),super.attr(t,e,i)}bbox(){return new kt}targets(){return Lt("svg [fill*="+this.id()+"]")}toString(){return this.url()}update(t){return this.clear(),"function"==typeof t&&t.call(this,this),this}url(){return"url(#"+this.id()+")"}}A({Container:{pattern(...t){return this.defs().pattern(...t)}},Defs:{pattern:K((function(t,e,i){return this.put(new ce).update(i).attr({x:0,y:0,width:t,height:e,patternUnits:"userSpaceOnUse"})}))}}),q(ce,"Pattern");let de=class extends qt{constructor(t,e=t){super(G("image",t),e)}load(t,e){if(!t)return this;const i=new O.window.Image;return zt(i,"load",(function(t){const a=this.parent(ce);0===this.width()&&0===this.height()&&this.size(i.width,i.height),a instanceof ce&&0===a.width()&&0===a.height()&&a.size(this.width(),this.height()),"function"==typeof e&&e.call(this,t)}),this),zt(i,"load error",(function(){Xt(i)})),this.attr("href",i.src=t,H)}};var ue;ue=function(t,e,i){return"fill"!==t&&"stroke"!==t||ct.test(e)&&(e=i.root().defs().image(e)),e instanceof de&&(e=i.root().defs().pattern(0,0,(t=>{t.add(e)}))),e},Wt.push(ue),A({Container:{image:K((function(t,e){return this.put(new de).size(0,0).load(t,e)}))}}),q(de,"Image");class ge extends Dt{bbox(){let t=-1/0,e=-1/0,i=1/0,a=1/0;return this.forEach((function(s){t=Math.max(s[0],t),e=Math.max(s[1],e),i=Math.min(s[0],i),a=Math.min(s[1],a)})),new kt(i,a,t-i,e-a)}move(t,e){const i=this.bbox();if(t-=i.x,e-=i.y,!isNaN(t)&&!isNaN(e))for(let i=this.length-1;i>=0;i--)this[i]=[this[i][0]+t,this[i][1]+e];return this}parse(t=[0,0]){const e=[];(t=t instanceof Array?Array.prototype.concat.apply([],t):t.trim().split(dt).map(parseFloat)).length%2!=0&&t.pop();for(let i=0,a=t.length;i=0;i--)a.width&&(this[i][0]=(this[i][0]-a.x)*t/a.width+a.x),a.height&&(this[i][1]=(this[i][1]-a.y)*e/a.height+a.y);return this}toLine(){return{x1:this[0][0],y1:this[0][1],x2:this[1][0],y2:this[1][1]}}toString(){const t=[];for(let e=0,i=this.length;e":function(t){return-Math.cos(t*Math.PI)/2+.5},">":function(t){return Math.sin(t*Math.PI/2)},"<":function(t){return 1-Math.cos(t*Math.PI/2)},bezier:function(t,e,i,a){return function(s){return s<0?t>0?e/t*s:i>0?a/i*s:0:s>1?i<1?(1-a)/(1-i)*s+(a-i)/(1-i):t<1?(1-e)/(1-t)*s+(e-t)/(1-t):1:3*s*(1-s)**2*e+3*s**2*(1-s)*a+s**3}},steps:function(t,e="end"){e=e.split("-").reverse()[0];let i=t;return"none"===e?--i:"both"===e&&++i,(a,s=!1)=>{let r=Math.floor(a*t);const n=a*r%1==0;return"start"!==e&&"both"!==e||++r,s&&n&&--r,a>=0&&r<0&&(r=0),a<=1&&r>i&&(r=i),r/i}}};class ye{done(){return!1}}class we extends ye{constructor(t=Ht){super(),this.ease=ve[t]||t}step(t,e,i){return"number"!=typeof t?i<1?t:e:t+(e-t)*this.ease(i)}}class ke extends ye{constructor(t){super(),this.stepper=t}done(t){return t.done}step(t,e,i,a){return this.stepper(t,e,i,a)}}function Ae(){const t=(this._duration||500)/1e3,e=this._overshoot||0,i=Math.PI,a=Math.log(e/100+1e-10),s=-a/Math.sqrt(i*i+a*a),r=3.9/(s*t);this.d=2*s*r,this.k=r*r}Q(class extends ke{constructor(t=500,e=0){super(),this.duration(t).overshoot(e)}step(t,e,i,a){if("string"==typeof t)return t;if(a.done=i===1/0,i===1/0)return e;if(0===i)return t;i>100&&(i=16),i/=1e3;const s=a.velocity||0,r=-this.d*s-this.k*(t-e),n=t+s*i+r*i*i/2;return a.velocity=s+r*i,a.done=Math.abs(e-n)+Math.abs(s)<.002,a.done?e:n}},{duration:me("_duration",Ae),overshoot:me("_overshoot",Ae)});Q(class extends ke{constructor(t=.1,e=.01,i=0,a=1e3){super(),this.p(t).i(e).d(i).windup(a)}step(t,e,i,a){if("string"==typeof t)return t;if(a.done=i===1/0,i===1/0)return e;if(0===i)return t;const s=e-t;let r=(a.integral||0)+s*i;const n=(s-(a.error||0))/i,o=this._windup;return!1!==o&&(r=Math.max(-o,Math.min(r,o))),a.error=s,a.integral=r,a.done=Math.abs(s)<.001,a.done?e:t+(this.P*s+this.I*r+this.D*n)}},{windup:me("_windup"),p:me("P"),i:me("I"),d:me("D")});const Ce={M:2,L:2,H:1,V:1,C:6,S:4,Q:4,T:2,A:7,Z:0},Se={M:function(t,e,i){return e.x=i.x=t[0],e.y=i.y=t[1],["M",e.x,e.y]},L:function(t,e){return e.x=t[0],e.y=t[1],["L",t[0],t[1]]},H:function(t,e){return e.x=t[0],["H",t[0]]},V:function(t,e){return e.y=t[0],["V",t[0]]},C:function(t,e){return e.x=t[4],e.y=t[5],["C",t[0],t[1],t[2],t[3],t[4],t[5]]},S:function(t,e){return e.x=t[2],e.y=t[3],["S",t[0],t[1],t[2],t[3]]},Q:function(t,e){return e.x=t[2],e.y=t[3],["Q",t[0],t[1],t[2],t[3]]},T:function(t,e){return e.x=t[0],e.y=t[1],["T",t[0],t[1]]},Z:function(t,e,i){return e.x=i.x,e.y=i.y,["Z"]},A:function(t,e){return e.x=t[5],e.y=t[6],["A",t[0],t[1],t[2],t[3],t[4],t[5],t[6]]}},Le="mlhvqtcsaz".split("");for(let t=0,e=Le.length;t=0;a--)i=this[a][0],"M"===i||"L"===i||"T"===i?(this[a][1]+=t,this[a][2]+=e):"H"===i?this[a][1]+=t:"V"===i?this[a][1]+=e:"C"===i||"S"===i||"Q"===i?(this[a][1]+=t,this[a][2]+=e,this[a][3]+=t,this[a][4]+=e,"C"===i&&(this[a][5]+=t,this[a][6]+=e)):"A"===i&&(this[a][6]+=t,this[a][7]+=e);return this}parse(t="M0 0"){return Array.isArray(t)&&(t=Array.prototype.concat.apply([],t).toString()),function(t,e=!0){let i=0,a="";const s={segment:[],inNumber:!1,number:"",lastToken:"",inSegment:!1,segments:[],pointSeen:!1,hasExponent:!1,absolute:e,p0:new bt,p:new bt};for(;s.lastToken=a,a=t.charAt(i++);)if(s.inSegment||!Pe(s,a))if("."!==a)if(isNaN(parseInt(a)))if(Re.has(a))s.inNumber&&Ie(s,!1);else if("-"!==a&&"+"!==a)if("E"!==a.toUpperCase()){if(ut.test(a)){if(s.inNumber)Ie(s,!1);else{if(!Me(s))throw new Error("parser Error");Te(s)}--i}}else s.number+=a,s.hasExponent=!0;else{if(s.inNumber&&!Xe(s)){Ie(s,!1),--i;continue}s.number+=a,s.inNumber=!0}else{if("0"===s.number||ze(s)){s.inNumber=!0,s.number=a,Ie(s,!0);continue}s.inNumber=!0,s.number+=a}else{if(s.pointSeen||s.hasExponent){Ie(s,!1),--i;continue}s.inNumber=!0,s.pointSeen=!0,s.number+=a}return s.inNumber&&Ie(s,!1),s.inSegment&&Me(s)&&Te(s),s.segments}(t)}size(t,e){const i=this.bbox();let a,s;for(i.width=0===i.width?1:i.width,i.height=0===i.height?1:i.height,a=this.length-1;a>=0;a--)s=this[a][0],"M"===s||"L"===s||"T"===s?(this[a][1]=(this[a][1]-i.x)*t/i.width+i.x,this[a][2]=(this[a][2]-i.y)*e/i.height+i.y):"H"===s?this[a][1]=(this[a][1]-i.x)*t/i.width+i.x:"V"===s?this[a][1]=(this[a][1]-i.y)*e/i.height+i.y:"C"===s||"S"===s||"Q"===s?(this[a][1]=(this[a][1]-i.x)*t/i.width+i.x,this[a][2]=(this[a][2]-i.y)*e/i.height+i.y,this[a][3]=(this[a][3]-i.x)*t/i.width+i.x,this[a][4]=(this[a][4]-i.y)*e/i.height+i.y,"C"===s&&(this[a][5]=(this[a][5]-i.x)*t/i.width+i.x,this[a][6]=(this[a][6]-i.y)*e/i.height+i.y)):"A"===s&&(this[a][1]=this[a][1]*t/i.width,this[a][2]=this[a][2]*e/i.height,this[a][6]=(this[a][6]-i.x)*t/i.width+i.x,this[a][7]=(this[a][7]-i.y)*e/i.height+i.y);return this}toString(){return function(t){let e="";for(let i=0,a=t.length;i{const e=typeof t;return"number"===e?_t:"string"===e?xt.isColor(t)?xt:dt.test(t)?ut.test(t)?Ee:Dt:tt.test(t)?_t:Oe:Ne.indexOf(t.constructor)>-1?t.constructor:Array.isArray(t)?Dt:"object"===e?_e:Oe};class He{constructor(t){this._stepper=t||new we("-"),this._from=null,this._to=null,this._type=null,this._context=null,this._morphObj=null}at(t){return this._morphObj.morph(this._from,this._to,t,this._stepper,this._context)}done(){return this._context.map(this._stepper.done).reduce((function(t,e){return t&&e}),!0)}from(t){return null==t?this._from:(this._from=this._set(t),this)}stepper(t){return null==t?this._stepper:(this._stepper=t,this)}to(t){return null==t?this._to:(this._to=this._set(t),this)}type(t){return null==t?this._type:(this._type=t,this)}_set(t){this._type||this.type(Ye(t));let e=new this._type(t);return this._type===xt&&(e=this._to?e[this._to[4]]():this._from?e[this._from[4]]():e),this._type===_e&&(e=this._to?e.align(this._to):this._from?e.align(this._from):e),e=e.toConsumable(),this._morphObj=this._morphObj||new this._type,this._context=this._context||Array.apply(null,Array(e.length)).map(Object).map((function(t){return t.done=!0,t})),e}}class Oe{constructor(...t){this.init(...t)}init(t){return t=Array.isArray(t)?t[0]:t,this.value=t,this}toArray(){return[this.value]}valueOf(){return this.value}}class Fe{constructor(...t){this.init(...t)}init(t){return Array.isArray(t)&&(t={scaleX:t[0],scaleY:t[1],shear:t[2],rotate:t[3],translateX:t[4],translateY:t[5],originX:t[6],originY:t[7]}),Object.assign(this,Fe.defaults,t),this}toArray(){const t=this;return[t.scaleX,t.scaleY,t.shear,t.rotate,t.translateX,t.translateY,t.originX,t.originY]}}Fe.defaults={scaleX:1,scaleY:1,shear:0,rotate:0,translateX:0,translateY:0,originX:0,originY:0};const De=(t,e)=>t[0]e[0]?1:0;class _e{constructor(...t){this.init(...t)}align(t){const e=this.values;for(let i=0,a=e.length;it.concat(e)),[]),this}toArray(){return this.values}valueOf(){const t={},e=this.values;for(;e.length;){const i=e.shift(),a=e.shift(),s=e.shift(),r=e.splice(0,s);t[i]=new a(r)}return t}}const Ne=[Oe,Fe,_e];class We extends qt{constructor(t,e=t){super(G("path",t),e)}array(){return this._array||(this._array=new Ee(this.attr("d")))}clear(){return delete this._array,this}height(t){return null==t?this.bbox().height:this.size(this.bbox().width,t)}move(t,e){return this.attr("d",this.array().move(t,e))}plot(t){return null==t?this.array():this.clear().attr("d","string"==typeof t?t:this._array=new Ee(t))}size(t,e){const i=I(this,t,e);return this.attr("d",this.array().size(i.width,i.height))}width(t){return null==t?this.bbox().width:this.size(t,this.bbox().height)}x(t){return null==t?this.bbox().x:this.move(t,this.bbox().y)}y(t){return null==t?this.bbox().y:this.move(this.bbox().x,t)}}We.prototype.MorphArray=Ee,A({Container:{path:K((function(t){return this.put(new We).plot(t||new Ee)}))}}),q(We,"Path");var Be=Object.freeze({__proto__:null,array:function(){return this._array||(this._array=new ge(this.attr("points")))},clear:function(){return delete this._array,this},move:function(t,e){return this.attr("points",this.array().move(t,e))},plot:function(t){return null==t?this.array():this.clear().attr("points","string"==typeof t?t:this._array=new ge(t))},size:function(t,e){const i=I(this,t,e);return this.attr("points",this.array().size(i.width,i.height))}});class Ge extends qt{constructor(t,e=t){super(G("polygon",t),e)}}A({Container:{polygon:K((function(t){return this.put(new Ge).plot(t||new ge)}))}}),Q(Ge,fe),Q(Ge,Be),q(Ge,"Polygon");class je extends qt{constructor(t,e=t){super(G("polyline",t),e)}}A({Container:{polyline:K((function(t){return this.put(new je).plot(t||new ge)}))}}),Q(je,fe),Q(je,Be),q(je,"Polyline");class Ve extends qt{constructor(t,e=t){super(G("rect",t),e)}}Q(Ve,{rx:Zt,ry:$t}),A({Container:{rect:K((function(t,e){return this.put(new Ve).size(t,e)}))}}),q(Ve,"Rect");class Ue{constructor(){this._first=null,this._last=null}first(){return this._first&&this._first.value}last(){return this._last&&this._last.value}push(t){const e=void 0!==t.next?t:{value:t,next:null,prev:null};return this._last?(e.prev=this._last,this._last.next=e,this._last=e):(this._last=e,this._first=e),e}remove(t){t.prev&&(t.prev.next=t.next),t.next&&(t.next.prev=t.prev),t===this._last&&(this._last=t.prev),t===this._first&&(this._first=t.next),t.prev=null,t.next=null}shift(){const t=this._first;return t?(this._first=t.next,this._first&&(this._first.prev=null),this._last=this._first?this._last:null,t.value):null}}const qe={nextDraw:null,frames:new Ue,timeouts:new Ue,immediates:new Ue,timer:()=>O.window.performance||O.window.Date,transforms:[],frame(t){const e=qe.frames.push({run:t});return null===qe.nextDraw&&(qe.nextDraw=O.window.requestAnimationFrame(qe._draw)),e},timeout(t,e){e=e||0;const i=qe.timer().now()+e,a=qe.timeouts.push({run:t,time:i});return null===qe.nextDraw&&(qe.nextDraw=O.window.requestAnimationFrame(qe._draw)),a},immediate(t){const e=qe.immediates.push(t);return null===qe.nextDraw&&(qe.nextDraw=O.window.requestAnimationFrame(qe._draw)),e},cancelFrame(t){null!=t&&qe.frames.remove(t)},clearTimeout(t){null!=t&&qe.timeouts.remove(t)},cancelImmediate(t){null!=t&&qe.immediates.remove(t)},_draw(t){let e=null;const i=qe.timeouts.last();for(;(e=qe.timeouts.shift())&&(t>=e.time?e.run():qe.timeouts.push(e),e!==i););let a=null;const s=qe.frames.last();for(;a!==s&&(a=qe.frames.shift());)a.run(t);let r=null;for(;r=qe.immediates.shift();)r();qe.nextDraw=qe.timeouts.first()||qe.frames.first()?O.window.requestAnimationFrame(qe._draw):null}},Ze=function(t){const e=t.start,i=t.runner.duration();return{start:e,duration:i,end:e+i,runner:t.runner}},$e=function(){const t=O.window;return(t.performance||t.Date).now()};class Je extends Rt{constructor(t=$e){super(),this._timeSource=t,this.terminate()}active(){return!!this._nextFrame}finish(){return this.time(this.getEndTimeOfTimeline()+1),this.pause()}getEndTime(){const t=this.getLastRunnerInfo(),e=t?t.runner.duration():0;return(t?t.start:this._time)+e}getEndTimeOfTimeline(){const t=this._runners.map((t=>t.start+t.runner.duration()));return Math.max(0,...t)}getLastRunnerInfo(){return this.getRunnerInfoById(this._lastRunnerId)}getRunnerInfoById(t){return this._runners[this._runnerIds.indexOf(t)]||null}pause(){return this._paused=!0,this._continue()}persist(t){return null==t?this._persist:(this._persist=t,this)}play(){return this._paused=!1,this.updateTime()._continue()}reverse(t){const e=this.speed();if(null==t)return this.speed(-e);const i=Math.abs(e);return this.speed(t?-i:i)}schedule(t,e,i){if(null==t)return this._runners.map(Ze);let a=0;const s=this.getEndTime();if(e=e||0,null==i||"last"===i||"after"===i)a=s;else if("absolute"===i||"start"===i)a=e,e=0;else if("now"===i)a=this._time;else if("relative"===i){const i=this.getRunnerInfoById(t.id);i&&(a=i.start+e,e=0)}else{if("with-last"!==i)throw new Error('Invalid value for the "when" parameter');{const t=this.getLastRunnerInfo();a=t?t.start:this._time}}t.unschedule(),t.timeline(this);const r=t.persist(),n={persist:null===r?this._persist:r,start:a+e,runner:t};return this._lastRunnerId=t.id,this._runners.push(n),this._runners.sort(((t,e)=>t.start-e.start)),this._runnerIds=this._runners.map((t=>t.runner.id)),this.updateTime()._continue(),this}seek(t){return this.time(this._time+t)}source(t){return null==t?this._timeSource:(this._timeSource=t,this)}speed(t){return null==t?this._speed:(this._speed=t,this)}stop(){return this.time(0),this.pause()}time(t){return null==t?this._time:(this._time=t,this._continue(!0))}unschedule(t){const e=this._runnerIds.indexOf(t.id);return e<0||(this._runners.splice(e,1),this._runnerIds.splice(e,1),t.timeline(null)),this}updateTime(){return this.active()||(this._lastSourceTime=this._timeSource()),this}_continue(t=!1){return qe.cancelFrame(this._nextFrame),this._nextFrame=null,t?this._stepImmediate():(this._paused||(this._nextFrame=qe.frame(this._step)),this)}_stepFn(t=!1){const e=this._timeSource();let i=e-this._lastSourceTime;t&&(i=0);const a=this._speed*i+(this._time-this._lastStepTime);this._lastSourceTime=e,t||(this._time+=a,this._time=this._time<0?0:this._time),this._lastStepTime=this._time,this.fire("time",this._time);for(let t=this._runners.length;t--;){const e=this._runners[t],i=e.runner;this._time-e.start<=0&&i.reset()}let s=!1;for(let t=0,e=this._runners.length;t0?this._continue():(this.pause(),this.fire("finished")),this}terminate(){this._startTime=0,this._speed=1,this._persist=0,this._nextFrame=null,this._paused=!0,this._runners=[],this._runnerIds=[],this._lastRunnerId=-1,this._time=0,this._lastSourceTime=0,this._lastStepTime=0,this._step=this._stepFn.bind(this,!1),this._stepImmediate=this._stepFn.bind(this,!0)}}A({Element:{timeline:function(t){return null==t?(this._timeline=this._timeline||new Je,this._timeline):(this._timeline=t,this)}}});class Qe extends Rt{constructor(t){super(),this.id=Qe.id++,t="function"==typeof(t=null==t?Yt:t)?new ke(t):t,this._element=null,this._timeline=null,this.done=!1,this._queue=[],this._duration="number"==typeof t&&t,this._isDeclarative=t instanceof ke,this._stepper=this._isDeclarative?t:new we,this._history={},this.enabled=!0,this._time=0,this._lastTime=0,this._reseted=!0,this.transforms=new vt,this.transformId=1,this._haveReversed=!1,this._reverse=!1,this._loopsDone=0,this._swing=!1,this._wait=0,this._times=1,this._frameId=null,this._persist=!!this._isDeclarative||null}static sanitise(t,e,i){let a=1,s=!1,r=0;return e=e??Ot,i=i||"last","object"!=typeof(t=t??Yt)||t instanceof ye||(e=t.delay??e,i=t.when??i,s=t.swing||s,a=t.times??a,r=t.wait??r,t=t.duration??Yt),{duration:t,delay:e,swing:s,times:a,wait:r,when:i}}active(t){return null==t?this.enabled:(this.enabled=t,this)}addTransform(t){return this.transforms.lmultiplyO(t),this}after(t){return this.on("finished",t)}animate(t,e,i){const a=Qe.sanitise(t,e,i),s=new Qe(a.duration);return this._timeline&&s.timeline(this._timeline),this._element&&s.element(this._element),s.loop(a).schedule(a.delay,a.when)}clearTransform(){return this.transforms=new vt,this}clearTransformsFromQueue(){this.done&&this._timeline&&this._timeline._runnerIds.includes(this.id)||(this._queue=this._queue.filter((t=>!t.isTransform)))}delay(t){return this.animate(0,t)}duration(){return this._times*(this._wait+this._duration)-this._wait}during(t){return this.queue(null,t)}ease(t){return this._stepper=new we(t),this}element(t){return null==t?this._element:(this._element=t,t._prepareRunner(),this)}finish(){return this.step(1/0)}loop(t,e,i){return"object"==typeof t&&(e=t.swing,i=t.wait,t=t.times),this._times=t||1/0,this._swing=e||!1,this._wait=i||0,!0===this._times&&(this._times=1/0),this}loops(t){const e=this._duration+this._wait;if(null==t){const t=Math.floor(this._time/e),i=(this._time-t*e)/this._duration;return Math.min(t+i,this._times)}const i=t%1,a=e*Math.floor(t)+this._duration*i;return this.time(a)}persist(t){return null==t?this._persist:(this._persist=t,this)}position(t){const e=this._time,i=this._duration,a=this._wait,s=this._times,r=this._swing,n=this._reverse;let o;if(null==t){const t=function(t){const e=r*Math.floor(t%(2*(a+i))/(a+i)),s=e&&!n||!e&&n,o=Math.pow(-1,s)*(t%(a+i))/i+s;return Math.max(Math.min(o,1),0)},l=s*(a+i)-a;return o=e<=0?Math.round(t(1e-5)):e=0;this._lastPosition=e;const a=this.duration(),s=this._lastTime<=0&&this._time>0,r=this._lastTime=a;this._lastTime=this._time,s&&this.fire("start",this);const n=this._isDeclarative;this.done=!n&&!r&&this._time>=a,this._reseted=!1;let o=!1;return(i||n)&&(this._initialise(i),this.transforms=new vt,o=this._run(n?t:e),this.fire("step",this)),this.done=this.done||o&&n,r&&this.fire("finished",this),this}time(t){if(null==t)return this._time;const e=t-this._time;return this.step(e),this}timeline(t){return void 0===t?this._timeline:(this._timeline=t,this)}unschedule(){const t=this.timeline();return t&&t.unschedule(this),this}_initialise(t){if(t||this._isDeclarative)for(let e=0,i=this._queue.length;et.lmultiplyO(e),ei=t=>t.transforms;function ii(){const t=this._transformationRunners.runners.map(ei).reduce(ti,new vt);this.transform(t),this._transformationRunners.merge(),1===this._transformationRunners.length()&&(this._frameId=null)}class ai{constructor(){this.runners=[],this.ids=[]}add(t){if(this.runners.includes(t))return;const e=t.id+1;return this.runners.push(t),this.ids.push(e),this}clearBefore(t){const e=this.ids.indexOf(t+1)||1;return this.ids.splice(0,e,0),this.runners.splice(0,e,new Ke).forEach((t=>t.clearTransformsFromQueue())),this}edit(t,e){const i=this.ids.indexOf(t+1);return this.ids.splice(i,1,t+1),this.runners.splice(i,1,e),this}getByID(t){return this.runners[this.ids.indexOf(t+1)]}length(){return this.ids.length}merge(){let t=null;for(let e=0;ee.id<=t.id)).map(ei).reduce(ti,new vt)},_addRunner(t){this._transformationRunners.add(t),qe.cancelImmediate(this._frameId),this._frameId=qe.immediate(ii.bind(this))},_prepareRunner(){null==this._frameId&&(this._transformationRunners=(new ai).add(new Ke(new vt(this))))}}});Q(Qe,{attr(t,e){return this.styleAttr("attr",t,e)},css(t,e){return this.styleAttr("css",t,e)},styleAttr(t,e,i){if("string"==typeof e)return this.styleAttr(t,{[e]:i});let a=e;if(this._tryRetarget(t,a))return this;let s=new He(this._stepper).to(a),r=Object.keys(a);return this.queue((function(){s=s.from(this.element()[t](r))}),(function(e){return this.element()[t](s.at(e).valueOf()),s.done()}),(function(e){const i=Object.keys(e),n=(o=r,i.filter((t=>!o.includes(t))));var o;if(n.length){const e=this.element()[t](n),i=new _e(s.from()).valueOf();Object.assign(i,e),s.from(i)}const l=new _e(s.to()).valueOf();Object.assign(l,e),s.to(l),r=i,a=e})),this._rememberMorpher(t,s),this},zoom(t,e){if(this._tryRetarget("zoom",t,e))return this;let i=new He(this._stepper).to(new _t(t));return this.queue((function(){i=i.from(this.element().zoom())}),(function(t){return this.element().zoom(i.at(t),e),i.done()}),(function(t,a){e=a,i.to(t)})),this._rememberMorpher("zoom",i),this},transform(t,e,i){if(e=t.relative||e,this._isDeclarative&&!e&&this._tryRetarget("transform",t))return this;const a=vt.isMatrixLike(t);i=null!=t.affine?t.affine:null!=i?i:!a;const s=new He(this._stepper).type(i?Fe:vt);let r,n,o,l,h;return this.queue((function(){n=n||this.element(),r=r||T(t,n),h=new vt(e?void 0:n),n._addRunner(this),e||n._clearTransformRunnersBefore(this)}),(function(c){e||this.clearTransform();const{x:d,y:u}=new bt(r).transform(n._currentTransform(this));let g=new vt({...t,origin:[d,u]}),p=this._isDeclarative&&o?o:h;if(i){g=g.decompose(d,u),p=p.decompose(d,u);const t=g.rotate,e=p.rotate,i=[t-360,t,t+360],a=i.map((t=>Math.abs(t-e))),s=Math.min(...a),r=a.indexOf(s);g.rotate=i[r]}e&&(a||(g.rotate=t.rotate||0),this._isDeclarative&&l&&(p.rotate=l)),s.from(p),s.to(g);const f=s.at(c);return l=f.rotate,o=new vt(f),this.addTransform(o),n._addRunner(this),s.done()}),(function(e){(e.origin||"center").toString()!==(t.origin||"center").toString()&&(r=T(e,n)),t={...e,origin:r}}),!0),this._isDeclarative&&this._rememberMorpher("transform",s),this},x(t){return this._queueNumber("x",t)},y(t){return this._queueNumber("y",t)},ax(t){return this._queueNumber("ax",t)},ay(t){return this._queueNumber("ay",t)},dx(t=0){return this._queueNumberDelta("x",t)},dy(t=0){return this._queueNumberDelta("y",t)},dmove(t,e){return this.dx(t).dy(e)},_queueNumberDelta(t,e){if(e=new _t(e),this._tryRetarget(t,e))return this;const i=new He(this._stepper).to(e);let a=null;return this.queue((function(){a=this.element()[t](),i.from(a),i.to(a+e)}),(function(e){return this.element()[t](i.at(e)),i.done()}),(function(t){i.to(a+new _t(t))})),this._rememberMorpher(t,i),this},_queueObject(t,e){if(this._tryRetarget(t,e))return this;const i=new He(this._stepper).to(e);return this.queue((function(){i.from(this.element()[t]())}),(function(e){return this.element()[t](i.at(e)),i.done()})),this._rememberMorpher(t,i),this},_queueNumber(t,e){return this._queueObject(t,new _t(e))},cx(t){return this._queueNumber("cx",t)},cy(t){return this._queueNumber("cy",t)},move(t,e){return this.x(t).y(e)},amove(t,e){return this.ax(t).ay(e)},center(t,e){return this.cx(t).cy(e)},size(t,e){let i;return t&&e||(i=this._element.bbox()),t||(t=i.width/i.height*e),e||(e=i.height/i.width*t),this.width(t).height(e)},width(t){return this._queueNumber("width",t)},height(t){return this._queueNumber("height",t)},plot(t,e,i,a){if(4===arguments.length)return this.plot([t,e,i,a]);if(this._tryRetarget("plot",t))return this;const s=new He(this._stepper).type(this._element.MorphArray).to(t);return this.queue((function(){s.from(this._element.array())}),(function(t){return this._element.plot(s.at(t)),s.done()})),this._rememberMorpher("plot",s),this},leading(t){return this._queueNumber("leading",t)},viewbox(t,e,i,a){return this._queueObject("viewbox",new kt(t,e,i,a))},update(t){return"object"!=typeof t?this.update({offset:arguments[0],color:arguments[1],opacity:arguments[2]}):(null!=t.opacity&&this.attr("stop-opacity",t.opacity),null!=t.color&&this.attr("stop-color",t.color),null!=t.offset&&this.attr("offset",t.offset),this)}}),Q(Qe,{rx:Zt,ry:$t,from:ne,to:oe}),q(Qe,"Runner");class si extends Vt{constructor(t,e=t){super(G("svg",t),e),this.namespace()}defs(){return this.isRoot()?V(this.node.querySelector("defs"))||this.put(new Ut):this.root().defs()}isRoot(){return!this.node.parentNode||!(this.node.parentNode instanceof O.window.SVGElement)&&"#document-fragment"!==this.node.parentNode.nodeName}namespace(){return this.isRoot()?this.attr({xmlns:E,version:"1.1"}).attr("xmlns:xlink",H,Y):this.root().namespace()}removeNamespace(){return this.attr({xmlns:null,version:null}).attr("xmlns:xlink",null,Y).attr("xmlns:svgjs",null,Y)}root(){return this.isRoot()?this:super.root()}}A({Container:{nested:K((function(){return this.put(new si)}))}}),q(si,"Svg",!0);let ri=class extends Vt{constructor(t,e=t){super(G("symbol",t),e)}};A({Container:{symbol:K((function(){return this.put(new ri)}))}}),q(ri,"Symbol");var ni=Object.freeze({__proto__:null,amove:function(t,e){return this.ax(t).ay(e)},ax:function(t){return this.attr("x",t)},ay:function(t){return this.attr("y",t)},build:function(t){return this._build=!!t,this},center:function(t,e,i=this.bbox()){return this.cx(t,i).cy(e,i)},cx:function(t,e=this.bbox()){return null==t?e.cx:this.attr("x",this.attr("x")+t-e.cx)},cy:function(t,e=this.bbox()){return null==t?e.cy:this.attr("y",this.attr("y")+t-e.cy)},length:function(){return this.node.getComputedTextLength()},move:function(t,e,i=this.bbox()){return this.x(t,i).y(e,i)},plain:function(t){return!1===this._build&&this.clear(),this.node.appendChild(O.document.createTextNode(t)),this},x:function(t,e=this.bbox()){return null==t?e.x:this.attr("x",this.attr("x")+t-e.x)},y:function(t,e=this.bbox()){return null==t?e.y:this.attr("y",this.attr("y")+t-e.y)}});class oi extends qt{constructor(t,e=t){super(G("text",t),e),this.dom.leading=this.dom.leading??new _t(1.3),this._rebuild=!0,this._build=!1}leading(t){return null==t?this.dom.leading:(this.dom.leading=new _t(t),this.rebuild())}rebuild(t){if("boolean"==typeof t&&(this._rebuild=t),this._rebuild){const t=this;let e=0;const i=this.dom.leading;this.each((function(a){if(X(this.node))return;const s=O.window.getComputedStyle(this.node).getPropertyValue("font-size"),r=i*new _t(s);this.dom.newLined&&(this.attr("x",t.attr("x")),"\n"===this.text()?e+=r:(this.attr("dy",a?r+e:0),e=0))})),this.fire("rebuild")}return this}setData(t){return this.dom=t,this.dom.leading=new _t(t.leading||1.3),this}writeDataToDom(){return R(this,this.dom,{leading:1.3}),this}text(t){if(void 0===t){const e=this.node.childNodes;let i=0;t="";for(let a=0,s=e.length;a{let a;try{a=i.node instanceof F().SVGSVGElement?new kt(i.attr(["x","y","width","height"])):i.bbox()}catch(t){return}const s=new vt(i),r=s.translate(t,e).transform(s.inverse()),n=new bt(a.x,a.y).transform(r);i.move(n.x,n.y)})),this},dx:function(t){return this.dmove(t,0)},dy:function(t){return this.dmove(0,t)},height:function(t,e=this.bbox()){return null==t?e.height:this.size(e.width,t,e)},move:function(t=0,e=0,i=this.bbox()){const a=t-i.x,s=e-i.y;return this.dmove(a,s)},size:function(t,e,i=this.bbox()){const a=I(this,t,e,i),s=a.width/i.width,r=a.height/i.height;return this.children().forEach((t=>{const e=new bt(i).transform(new vt(t).inverse());t.scale(s,r,e.x,e.y)})),this},width:function(t,e=this.bbox()){return null==t?e.width:this.size(t,e.height,e)},x:function(t,e=this.bbox()){return null==t?e.x:this.move(t,e.y,e)},y:function(t,e=this.bbox()){return null==t?e.y:this.move(e.x,t,e)}});class gi extends Vt{constructor(t,e=t){super(G("g",t),e)}}Q(gi,ui),A({Container:{group:K((function(){return this.put(new gi)}))}}),q(gi,"G");class pi extends Vt{constructor(t,e=t){super(G("a",t),e)}target(t){return this.attr("target",t)}to(t){return this.attr("href",t,H)}}Q(pi,ui),A({Container:{link:K((function(t){return this.put(new pi).to(t)}))},Element:{unlink(){const t=this.linker();if(!t)return this;const e=t.parent();if(!e)return this.remove();const i=e.index(t);return e.add(this,i),t.remove(),this},linkTo(t){let e=this.linker();return e||(e=new pi,this.wrap(e)),"function"==typeof t?t.call(e,e):e.to(t),this},linker(){const t=this.parent();return t&&"a"===t.node.nodeName.toLowerCase()?t:null}}}),q(pi,"A");class fi extends Vt{constructor(t,e=t){super(G("mask",t),e)}remove(){return this.targets().forEach((function(t){t.unmask()})),super.remove()}targets(){return Lt("svg [mask*="+this.id()+"]")}}A({Container:{mask:K((function(){return this.defs().put(new fi)}))},Element:{masker(){return this.reference("mask")},maskWith(t){const e=t instanceof fi?t:this.parent().mask().add(t);return this.attr("mask","url(#"+e.id()+")")},unmask(){return this.attr("mask",null)}}}),q(fi,"Mask");class xi extends Gt{constructor(t,e=t){super(G("stop",t),e)}update(t){return("number"==typeof t||t instanceof _t)&&(t={offset:arguments[0],color:arguments[1],opacity:arguments[2]}),null!=t.opacity&&this.attr("stop-opacity",t.opacity),null!=t.color&&this.attr("stop-color",t.color),null!=t.offset&&this.attr("offset",new _t(t.offset)),this}}A({Gradient:{stop:function(t,e,i){return this.put(new xi).update(t,e,i)}}}),q(xi,"Stop");class bi extends Gt{constructor(t,e=t){super(G("style",t),e)}addText(t=""){return this.node.textContent+=t,this}font(t,e,i={}){return this.rule("@font-face",{fontFamily:t,src:e,...i})}rule(t,e){return this.addText(function(t,e){if(!t)return"";if(!e)return t;let i=t+"{";for(const t in e)i+=t.replace(/([A-Z])/g,(function(t,e){return"-"+e.toLowerCase()}))+":"+e[t]+";";return i+="}",i}(t,e))}}A("Dom",{style(t,e){return this.put(new bi).rule(t,e)},fontface(t,e,i){return this.put(new bi).font(t,e,i)}}),q(bi,"Style");class mi extends oi{constructor(t,e=t){super(G("textPath",t),e)}array(){const t=this.track();return t?t.array():null}plot(t){const e=this.track();let i=null;return e&&(i=e.plot(t)),null==t?i:this}track(){return this.reference("href")}}A({Container:{textPath:K((function(t,e){return t instanceof oi||(t=this.text(t)),t.path(e)}))},Text:{path:K((function(t,e=!0){const i=new mi;let a;if(t instanceof We||(t=this.defs().path(t)),i.attr("href","#"+t,H),e)for(;a=this.node.firstChild;)i.node.appendChild(a);return this.put(i)})),textPath(){return this.findOne("textPath")}},Path:{text:K((function(t){return t instanceof oi||(t=(new oi).addTo(this.parent()).text(t)),t.path(this)})),targets(){return Lt("svg textPath").filter((t=>(t.attr("href")||"").includes(this.id())))}}}),mi.prototype.MorphArray=Ee,q(mi,"TextPath");class vi extends qt{constructor(t,e=t){super(G("use",t),e)}use(t,e){return this.attr("href",(e||"")+"#"+t,H)}}A({Container:{use:K((function(t,e){return this.put(new vi).use(t,e)}))}}),q(vi,"Use");const yi=B;Q([si,ri,de,ce,be],C("viewbox")),Q([xe,je,Ge,We],C("marker")),Q(oi,C("Text")),Q(We,C("Path")),Q(Ut,C("Defs")),Q([oi,li],C("Tspan")),Q([Ve,se,he,Qe],C("radius")),Q(Rt,C("EventTarget")),Q(Bt,C("Dom")),Q(Gt,C("Element")),Q(qt,C("Shape")),Q([Vt,re],C("Container")),Q(he,C("Gradient")),Q(Qe,C("Runner")),Ct.extend([...new Set(k)]),function(t=[]){Ne.push(...[].concat(t))}([_t,xt,kt,vt,Dt,ge,Ee,bt]),Q(Ne,{to(t){return(new He).type(this.constructor).from(this.toArray()).to(t)},fromArray(t){return this.init(t),this},toConsumable(){return this.toArray()},morph(t,e,i,a,s){return this.fromArray(t.map((function(t,r){return a.step(t,e[r],i,s[r],s)})))}});class wi extends Gt{constructor(t){super(G("filter",t),t),this.$source="SourceGraphic",this.$sourceAlpha="SourceAlpha",this.$background="BackgroundImage",this.$backgroundAlpha="BackgroundAlpha",this.$fill="FillPaint",this.$stroke="StrokePaint",this.$autoSetIn=!0}put(t,e){return!(t=super.put(t,e)).attr("in")&&this.$autoSetIn&&t.attr("in",this.$source),t.attr("result")||t.attr("result",t.id()),t}remove(){return this.targets().each("unfilter"),super.remove()}targets(){return Lt('svg [filter*="'+this.id()+'"]')}toString(){return"url(#"+this.id()+")"}}class ki extends Gt{constructor(t,e){super(t,e),this.result(this.id())}in(t){if(null==t){const t=this.attr("in");return this.parent()&&this.parent().find(`[result="${t}"]`)[0]||t}return this.attr("in",t)}result(t){return this.attr("result",t)}toString(){return this.result()}}const Ai=t=>function(...e){for(let i=t.length;i--;)null!=e[i]&&this.attr(t[i],e[i])},Ci={blend:Ai(["in","in2","mode"]),colorMatrix:Ai(["type","values"]),composite:Ai(["in","in2","operator"]),convolveMatrix:function(t){t=new Dt(t).toString(),this.attr({order:Math.sqrt(t.split(" ").length),kernelMatrix:t})},diffuseLighting:Ai(["surfaceScale","lightingColor","diffuseConstant","kernelUnitLength"]),displacementMap:Ai(["in","in2","scale","xChannelSelector","yChannelSelector"]),dropShadow:Ai(["in","dx","dy","stdDeviation"]),flood:Ai(["flood-color","flood-opacity"]),gaussianBlur:function(t=0,e=t){this.attr("stdDeviation",t+" "+e)},image:function(t){this.attr("href",t,H)},morphology:Ai(["operator","radius"]),offset:Ai(["dx","dy"]),specularLighting:Ai(["surfaceScale","lightingColor","diffuseConstant","specularExponent","kernelUnitLength"]),tile:Ai([]),turbulence:Ai(["baseFrequency","numOctaves","seed","stitchTiles","type"])};["blend","colorMatrix","componentTransfer","composite","convolveMatrix","diffuseLighting","displacementMap","dropShadow","flood","gaussianBlur","image","merge","morphology","offset","specularLighting","tile","turbulence"].forEach((t=>{const e=P(t),i=Ci[t];wi[e+"Effect"]=class extends ki{constructor(t){super(G("fe"+e,t),t)}update(t){return i.apply(this,t),this}},wi.prototype[t]=K((function(t,...i){const a=new wi[e+"Effect"];return null==t?this.put(a):("function"==typeof t?t.call(a,a):i.unshift(t),this.put(a).update(i))}))})),Q(wi,{merge(t){const e=this.put(new wi.MergeEffect);if("function"==typeof t)return t.call(e,e),e;return(t instanceof Array?t:[...arguments]).forEach((t=>{t instanceof wi.MergeNode?e.put(t):e.mergeNode(t)})),e},componentTransfer(t={}){const e=this.put(new wi.ComponentTransferEffect);if("function"==typeof t)return t.call(e,e),e;if(!(t.r||t.g||t.b||t.a)){t={r:t,g:t,b:t,a:t}}for(const i in t)e.add(new(wi["Func"+i.toUpperCase()])(t[i]));return e}});["distantLight","pointLight","spotLight","mergeNode","FuncR","FuncG","FuncB","FuncA"].forEach((t=>{const e=P(t);wi[e]=class extends ki{constructor(t){super(G("fe"+e,t),t)}}}));["funcR","funcG","funcB","funcA"].forEach((function(t){const e=wi[P(t)],i=K((function(){return this.put(new e)}));wi.ComponentTransferEffect.prototype[t]=i}));["distantLight","pointLight","spotLight"].forEach((t=>{const e=wi[P(t)],i=K((function(){return this.put(new e)}));wi.DiffuseLightingEffect.prototype[t]=i,wi.SpecularLightingEffect.prototype[t]=i})),Q(wi.MergeEffect,{mergeNode(t){return this.put(new wi.MergeNode).attr("in",t)}}),Q(Ut,{filter:function(t){const e=this.put(new wi);return"function"==typeof t&&t.call(e,e),e}}),Q(Vt,{filter:function(t){return this.defs().filter(t)}}),Q(Gt,{filterWith:function(t){const e=t instanceof wi?t:this.defs().filter(t);return this.attr("filter",e)},unfilter:function(t){return this.attr("filter",null)},filterer(){return this.reference("filter")}});const Si={blend:function(t,e){return this.parent()&&this.parent().blend(this,t,e)},colorMatrix:function(t,e){return this.parent()&&this.parent().colorMatrix(t,e).in(this)},componentTransfer:function(t){return this.parent()&&this.parent().componentTransfer(t).in(this)},composite:function(t,e){return this.parent()&&this.parent().composite(this,t,e)},convolveMatrix:function(t){return this.parent()&&this.parent().convolveMatrix(t).in(this)},diffuseLighting:function(t,e,i,a){return this.parent()&&this.parent().diffuseLighting(t,i,a).in(this)},displacementMap:function(t,e,i,a){return this.parent()&&this.parent().displacementMap(this,t,e,i,a)},dropShadow:function(t,e,i){return this.parent()&&this.parent().dropShadow(this,t,e,i).in(this)},flood:function(t,e){return this.parent()&&this.parent().flood(t,e)},gaussianBlur:function(t,e){return this.parent()&&this.parent().gaussianBlur(t,e).in(this)},image:function(t){return this.parent()&&this.parent().image(t)},merge:function(t){return t=t instanceof Array?t:[...t],this.parent()&&this.parent().merge(this,...t)},morphology:function(t,e){return this.parent()&&this.parent().morphology(t,e).in(this)},offset:function(t,e){return this.parent()&&this.parent().offset(t,e).in(this)},specularLighting:function(t,e,i,a,s){return this.parent()&&this.parent().specularLighting(t,i,a,s).in(this)},tile:function(){return this.parent()&&this.parent().tile().in(this)},turbulence:function(t,e,i,a,s){return this.parent()&&this.parent().turbulence(t,e,i,a,s).in(this)}};Q(ki,Si),Q(wi.MergeEffect,{in:function(t){return t instanceof wi.MergeNode?this.add(t,0):this.add((new wi.MergeNode).in(t),0),this}}),Q([wi.CompositeEffect,wi.BlendEffect,wi.DisplacementMapEffect],{in2:function(t){if(null==t){const t=this.attr("in2");return this.parent()&&this.parent().find(`[result="${t}"]`)[0]||t}return this.attr("in2",t)}}),wi.filter={sepiatone:[.343,.669,.119,0,0,.249,.626,.13,0,0,.172,.334,.111,0,0,0,0,0,1,0]};var Li=function(){function t(e){i(this,t),this.ctx=e,this.w=e.w}return s(t,[{key:"getDefaultFilter",value:function(t,e){var i=this.w;t.unfilter(!0),(new wi).size("120%","180%","-5%","-40%"),i.config.chart.dropShadow.enabled&&this.dropShadow(t,i.config.chart.dropShadow,e)}},{key:"applyFilter",value:function(t,e,i){var a,s=this,r=this.w;if(t.unfilter(!0),"none"!==i){var n,o,l=r.config.chart.dropShadow,h="lighten"===i?2:.3;if(t.filterWith((function(t){t.colorMatrix({type:"matrix",values:"\n ".concat(h," 0 0 0 0\n 0 ").concat(h," 0 0 0\n 0 0 ").concat(h," 0 0\n 0 0 0 1 0\n "),in:"SourceGraphic",result:"brightness"}),l.enabled&&s.addShadow(t,e,l,"brightness")})),!l.noUserSpaceOnUse)null===(n=t.filterer())||void 0===n||null===(o=n.node)||void 0===o||o.setAttribute("filterUnits","userSpaceOnUse");this._scaleFilterSize(null===(a=t.filterer())||void 0===a?void 0:a.node)}else this.getDefaultFilter(t,e)}},{key:"addShadow",value:function(t,e,i,a){var s,r=this.w,n=i.blur,o=i.top,l=i.left,h=i.color,c=i.opacity;if(h=Array.isArray(h)?h[e]:h,(null===(s=r.config.chart.dropShadow.enabledOnSeries)||void 0===s?void 0:s.length)>0&&-1===r.config.chart.dropShadow.enabledOnSeries.indexOf(e))return t;t.offset({in:a,dx:l,dy:o,result:"offset"}),t.gaussianBlur({in:"offset",stdDeviation:n,result:"blur"}),t.flood({"flood-color":h,"flood-opacity":c,result:"flood"}),t.composite({in:"flood",in2:"blur",operator:"in",result:"shadow"}),t.merge(["shadow",a])}},{key:"dropShadow",value:function(t,e){var i,a,s,r,n,o=this,l=arguments.length>2&&void 0!==arguments[2]?arguments[2]:0,h=this.w;if(t.unfilter(!0),v.isMsEdge()&&"radialBar"===h.config.chart.type)return t;if((null===(i=h.config.chart.dropShadow.enabledOnSeries)||void 0===i?void 0:i.length)>0&&-1===(null===(s=h.config.chart.dropShadow.enabledOnSeries)||void 0===s?void 0:s.indexOf(l)))return t;(t.filterWith((function(t){o.addShadow(t,l,e,"SourceGraphic")})),e.noUserSpaceOnUse)||(null===(r=t.filterer())||void 0===r||null===(n=r.node)||void 0===n||n.setAttribute("filterUnits","userSpaceOnUse"));return this._scaleFilterSize(null===(a=t.filterer())||void 0===a?void 0:a.node),t}},{key:"setSelectionFilter",value:function(t,e,i){var a=this.w;if(void 0!==a.globals.selectedDataPoints[e]&&a.globals.selectedDataPoints[e].indexOf(i)>-1){t.node.setAttribute("selected",!0);var s=a.config.states.active.filter;"none"!==s&&this.applyFilter(t,e,s.type)}}},{key:"_scaleFilterSize",value:function(t){if(t){!function(e){for(var i in e)e.hasOwnProperty(i)&&t.setAttribute(i,e[i])}({width:"200%",height:"200%",x:"-50%",y:"-50%"})}}}]),t}(),Mi=function(){function t(e){i(this,t),this.ctx=e,this.w=e.w}return s(t,[{key:"roundPathCorners",value:function(t,e){function i(t,e,i){var s=e.x-t.x,r=e.y-t.y,n=Math.sqrt(s*s+r*r);return a(t,e,Math.min(1,i/n))}function a(t,e,i){return{x:t.x+(e.x-t.x)*i,y:t.y+(e.y-t.y)*i}}function s(t,e){t.length>2&&(t[t.length-2]=e.x,t[t.length-1]=e.y)}function r(t){return{x:parseFloat(t[t.length-2]),y:parseFloat(t[t.length-1])}}t.indexOf("NaN")>-1&&(t="");var n=t.split(/[,\s]/).reduce((function(t,e){var i=e.match(/^([a-zA-Z])(.+)/);return i?(t.push(i[1]),t.push(i[2])):t.push(e),t}),[]).reduce((function(t,e){return parseFloat(e)==e&&t.length?t[t.length-1].push(e):t.push([e]),t}),[]),o=[];if(n.length>1){var l=r(n[0]),h=null;"Z"==n[n.length-1][0]&&n[0].length>2&&(h=["L",l.x,l.y],n[n.length-1]=h),o.push(n[0]);for(var c=1;c2&&"L"==u[0]&&g.length>2&&"L"==g[0]){var p,f,x=r(d),b=r(u),m=r(g);p=i(b,x,e),f=i(b,m,e),s(u,p),u.origPoint=b,o.push(u);var v=a(p,b,.5),y=a(b,f,.5),w=["C",v.x,v.y,y.x,y.y,f.x,f.y];w.origPoint=b,o.push(w)}else o.push(u)}if(h){var k=r(o[o.length-1]);o.push(["Z"]),s(o[0],k)}}else o=n;return o.reduce((function(t,e){return t+e.join(" ")+" "}),"")}},{key:"drawLine",value:function(t,e,i,a){var s=arguments.length>4&&void 0!==arguments[4]?arguments[4]:"#a8a8a8",r=arguments.length>5&&void 0!==arguments[5]?arguments[5]:0,n=arguments.length>6&&void 0!==arguments[6]?arguments[6]:null,o=arguments.length>7&&void 0!==arguments[7]?arguments[7]:"butt";return this.w.globals.dom.Paper.line().attr({x1:t,y1:e,x2:i,y2:a,stroke:s,"stroke-dasharray":r,"stroke-width":n,"stroke-linecap":o})}},{key:"drawRect",value:function(){var t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:0,e=arguments.length>1&&void 0!==arguments[1]?arguments[1]:0,i=arguments.length>2&&void 0!==arguments[2]?arguments[2]:0,a=arguments.length>3&&void 0!==arguments[3]?arguments[3]:0,s=arguments.length>4&&void 0!==arguments[4]?arguments[4]:0,r=arguments.length>5&&void 0!==arguments[5]?arguments[5]:"#fefefe",n=arguments.length>6&&void 0!==arguments[6]?arguments[6]:1,o=arguments.length>7&&void 0!==arguments[7]?arguments[7]:null,l=arguments.length>8&&void 0!==arguments[8]?arguments[8]:null,h=arguments.length>9&&void 0!==arguments[9]?arguments[9]:0,c=this.w.globals.dom.Paper.rect();return c.attr({x:t,y:e,width:i>0?i:0,height:a>0?a:0,rx:s,ry:s,opacity:n,"stroke-width":null!==o?o:0,stroke:null!==l?l:"none","stroke-dasharray":h}),c.node.setAttribute("fill",r),c}},{key:"drawPolygon",value:function(t){var e=arguments.length>1&&void 0!==arguments[1]?arguments[1]:"#e1e1e1",i=arguments.length>2&&void 0!==arguments[2]?arguments[2]:1,a=arguments.length>3&&void 0!==arguments[3]?arguments[3]:"none";return this.w.globals.dom.Paper.polygon(t).attr({fill:a,stroke:e,"stroke-width":i})}},{key:"drawCircle",value:function(t){var e=arguments.length>1&&void 0!==arguments[1]?arguments[1]:null;t<0&&(t=0);var i=this.w.globals.dom.Paper.circle(2*t);return null!==e&&i.attr(e),i}},{key:"drawPath",value:function(t){var e=t.d,i=void 0===e?"":e,a=t.stroke,s=void 0===a?"#a8a8a8":a,r=t.strokeWidth,n=void 0===r?1:r,o=t.fill,l=t.fillOpacity,h=void 0===l?1:l,c=t.strokeOpacity,d=void 0===c?1:c,u=t.classes,g=t.strokeLinecap,p=void 0===g?null:g,f=t.strokeDashArray,x=void 0===f?0:f,b=this.w;return null===p&&(p=b.config.stroke.lineCap),(i.indexOf("undefined")>-1||i.indexOf("NaN")>-1)&&(i="M 0 ".concat(b.globals.gridHeight)),b.globals.dom.Paper.path(i).attr({fill:o,"fill-opacity":h,stroke:s,"stroke-opacity":d,"stroke-linecap":p,"stroke-width":n,"stroke-dasharray":x,class:u})}},{key:"group",value:function(){var t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:null,e=this.w.globals.dom.Paper.group();return null!==t&&e.attr(t),e}},{key:"move",value:function(t,e){var i=["M",t,e].join(" ");return i}},{key:"line",value:function(t,e){var i=arguments.length>2&&void 0!==arguments[2]?arguments[2]:null,a=null;return null===i?a=[" L",t,e].join(" "):"H"===i?a=[" H",t].join(" "):"V"===i&&(a=[" V",e].join(" ")),a}},{key:"curve",value:function(t,e,i,a,s,r){var n=["C",t,e,i,a,s,r].join(" ");return n}},{key:"quadraticCurve",value:function(t,e,i,a){return["Q",t,e,i,a].join(" ")}},{key:"arc",value:function(t,e,i,a,s,r,n){var o="A";arguments.length>7&&void 0!==arguments[7]&&arguments[7]&&(o="a");var l=[o,t,e,i,a,s,r,n].join(" ");return l}},{key:"renderPaths",value:function(t){var e,i=t.j,a=t.realIndex,s=t.pathFrom,r=t.pathTo,n=t.stroke,o=t.strokeWidth,l=t.strokeLinecap,h=t.fill,c=t.animationDelay,d=t.initialSpeed,g=t.dataChangeSpeed,p=t.className,f=t.chartType,x=t.shouldClipToGrid,b=void 0===x||x,m=t.bindEventsOnPaths,v=void 0===m||m,w=t.drawShadow,k=void 0===w||w,A=this.w,C=new Li(this.ctx),S=new y(this.ctx),L=this.w.config.chart.animations.enabled,M=L&&this.w.config.chart.animations.dynamicAnimation.enabled;if(s&&s.startsWith("M 0 0")&&r){var P=r.match(/^M\s+[\d.-]+\s+[\d.-]+/);P&&(s=s.replace(/^M\s+0\s+0/,P[0]))}var I=!!(L&&!A.globals.resized||M&&A.globals.dataChanged&&A.globals.shouldAnimate);I?e=s:(e=r,A.globals.animationEnded=!0);var T=A.config.stroke.dashArray,z=0;z=Array.isArray(T)?T[a]:A.config.stroke.dashArray;var X=this.drawPath({d:e,stroke:n,strokeWidth:o,fill:h,fillOpacity:1,classes:p,strokeLinecap:l,strokeDashArray:z});X.attr("index",a),b&&("bar"===f&&!A.globals.isHorizontal||A.globals.comboCharts?X.attr({"clip-path":"url(#gridRectBarMask".concat(A.globals.cuid,")")}):X.attr({"clip-path":"url(#gridRectMask".concat(A.globals.cuid,")")})),A.config.chart.dropShadow.enabled&&k&&C.dropShadow(X,A.config.chart.dropShadow,a),v&&(X.node.addEventListener("mouseenter",this.pathMouseEnter.bind(this,X)),X.node.addEventListener("mouseleave",this.pathMouseLeave.bind(this,X)),X.node.addEventListener("mousedown",this.pathMouseDown.bind(this,X))),X.attr({pathTo:r,pathFrom:s});var R={el:X,j:i,realIndex:a,pathFrom:s,pathTo:r,fill:h,strokeWidth:o,delay:c};return!L||A.globals.resized||A.globals.dataChanged?!A.globals.resized&&A.globals.dataChanged||S.showDelayedElements():S.animatePathsGradually(u(u({},R),{},{speed:d})),A.globals.dataChanged&&M&&I&&S.animatePathsGradually(u(u({},R),{},{speed:g})),X}},{key:"drawPattern",value:function(t,e,i){var a=arguments.length>3&&void 0!==arguments[3]?arguments[3]:"#a8a8a8",s=arguments.length>4&&void 0!==arguments[4]?arguments[4]:0;return this.w.globals.dom.Paper.pattern(e,i,(function(r){"horizontalLines"===t?r.line(0,0,i,0).stroke({color:a,width:s+1}):"verticalLines"===t?r.line(0,0,0,e).stroke({color:a,width:s+1}):"slantedLines"===t?r.line(0,0,e,i).stroke({color:a,width:s}):"squares"===t?r.rect(e,i).fill("none").stroke({color:a,width:s}):"circles"===t&&r.circle(e).fill("none").stroke({color:a,width:s})}))}},{key:"drawGradient",value:function(t,e,i,a,s){var r,n=arguments.length>5&&void 0!==arguments[5]?arguments[5]:null,o=arguments.length>6&&void 0!==arguments[6]?arguments[6]:null,l=arguments.length>7&&void 0!==arguments[7]?arguments[7]:[],h=arguments.length>8&&void 0!==arguments[8]?arguments[8]:0,c=this.w;e.length<9&&0===e.indexOf("#")&&(e=v.hexToRgba(e,a)),i.length<9&&0===i.indexOf("#")&&(i=v.hexToRgba(i,s));var d=0,u=1,g=1,p=null;null!==o&&(d=void 0!==o[0]?o[0]/100:0,u=void 0!==o[1]?o[1]/100:1,g=void 0!==o[2]?o[2]/100:1,p=void 0!==o[3]?o[3]/100:null);var f=!("donut"!==c.config.chart.type&&"pie"!==c.config.chart.type&&"polarArea"!==c.config.chart.type&&"bubble"!==c.config.chart.type);if(r=l&&0!==l.length?c.globals.dom.Paper.gradient(f?"radial":"linear",(function(t){(Array.isArray(l[h])?l[h]:l).forEach((function(e){t.stop(e.offset/100,e.color,e.opacity)}))})):c.globals.dom.Paper.gradient(f?"radial":"linear",(function(t){t.stop(d,e,a),t.stop(u,i,s),t.stop(g,i,s),null!==p&&t.stop(p,e,a)})),f){var x=c.globals.gridWidth/2,b=c.globals.gridHeight/2;"bubble"!==c.config.chart.type?r.attr({gradientUnits:"userSpaceOnUse",cx:x,cy:b,r:n}):r.attr({cx:.5,cy:.5,r:.8,fx:.2,fy:.2})}else"vertical"===t?r.from(0,0).to(0,1):"diagonal"===t?r.from(0,0).to(1,1):"horizontal"===t?r.from(0,1).to(1,1):"diagonal2"===t&&r.from(1,0).to(0,1);return r}},{key:"getTextBasedOnMaxWidth",value:function(t){var e=t.text,i=t.maxWidth,a=t.fontSize,s=t.fontFamily,r=this.getTextRects(e,a,s),n=r.width/e.length,o=Math.floor(i/n);return i-1){var o=i.globals.selectedDataPoints[s].indexOf(r);i.globals.selectedDataPoints[s].splice(o,1)}}else{if(!i.config.states.active.allowMultipleDataPointsSelection&&i.globals.selectedDataPoints.length>0){i.globals.selectedDataPoints=[];var l=i.globals.dom.Paper.find(".apexcharts-series path:not(.apexcharts-decoration-element)"),h=i.globals.dom.Paper.find(".apexcharts-series circle:not(.apexcharts-decoration-element), .apexcharts-series rect:not(.apexcharts-decoration-element)"),c=function(t){Array.prototype.forEach.call(t,(function(t){t.node.setAttribute("selected","false"),a.getDefaultFilter(t,s)}))};c(l),c(h)}t.node.setAttribute("selected","true"),n="true",void 0===i.globals.selectedDataPoints[s]&&(i.globals.selectedDataPoints[s]=[]),i.globals.selectedDataPoints[s].push(r)}if("true"===n){var d=i.config.states.active.filter;if("none"!==d)a.applyFilter(t,s,d.type);else if("none"!==i.config.states.hover.filter&&!i.globals.isTouchDevice){var u=i.config.states.hover.filter;a.applyFilter(t,s,u.type)}}else if("none"!==i.config.states.active.filter.type)if("none"===i.config.states.hover.filter.type||i.globals.isTouchDevice)a.getDefaultFilter(t,s);else{u=i.config.states.hover.filter;a.applyFilter(t,s,u.type)}"function"==typeof i.config.chart.events.dataPointSelection&&i.config.chart.events.dataPointSelection(e,this.ctx,{selectedDataPoints:i.globals.selectedDataPoints,seriesIndex:s,dataPointIndex:r,w:i}),e&&this.ctx.events.fireEvent("dataPointSelection",[e,this.ctx,{selectedDataPoints:i.globals.selectedDataPoints,seriesIndex:s,dataPointIndex:r,w:i}])}},{key:"rotateAroundCenter",value:function(t){var e={};return t&&"function"==typeof t.getBBox&&(e=t.getBBox()),{x:e.x+e.width/2,y:e.y+e.height/2}}},{key:"getTextRects",value:function(t,e,i,a){var s=!(arguments.length>4&&void 0!==arguments[4])||arguments[4],r=this.w,n=this.drawText({x:-200,y:-200,text:t,textAnchor:"start",fontSize:e,fontFamily:i,foreColor:"#fff",opacity:0});a&&n.attr("transform",a),r.globals.dom.Paper.add(n);var o=n.bbox();return s||(o=n.node.getBoundingClientRect()),n.remove(),{width:o.width,height:o.height}}},{key:"placeTextWithEllipsis",value:function(t,e,i){if("function"==typeof t.getComputedTextLength&&(t.textContent=e,e.length>0&&t.getComputedTextLength()>=i/1.1)){for(var a=e.length-3;a>0;a-=3)if(t.getSubStringLength(0,a)<=i/1.1)return void(t.textContent=e.substring(0,a)+"...");t.textContent="."}}}],[{key:"setAttrs",value:function(t,e){for(var i in e)e.hasOwnProperty(i)&&t.setAttribute(i,e[i])}}]),t}(),Pi=function(){function t(e){i(this,t),this.ctx=e,this.w=e.w}return s(t,[{key:"getStackedSeriesTotals",value:function(){var t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:[],e=this.w,i=[];if(0===e.globals.series.length)return i;for(var a=0;a0&&void 0!==arguments[0]?arguments[0]:null;return null===t?this.w.config.series.reduce((function(t,e){return t+e}),0):this.w.globals.series[t].reduce((function(t,e){return t+e}),0)}},{key:"getStackedSeriesTotalsByGroups",value:function(){var t=this,e=this.w,i=[];return e.globals.seriesGroups.forEach((function(a){var s=[];e.config.series.forEach((function(t,i){a.indexOf(e.globals.seriesNames[i])>-1&&s.push(i)}));var r=e.globals.series.map((function(t,e){return-1===s.indexOf(e)?e:-1})).filter((function(t){return-1!==t}));i.push(t.getStackedSeriesTotals(r))})),i}},{key:"setSeriesYAxisMappings",value:function(){var t=this.w.globals,e=this.w.config,i=[],a=[],s=[],r=t.series.length>e.yaxis.length||e.yaxis.some((function(t){return Array.isArray(t.seriesName)}));e.series.forEach((function(t,e){s.push(e),a.push(null)})),e.yaxis.forEach((function(t,e){i[e]=[]}));var n=[];e.yaxis.forEach((function(t,a){var o=!1;if(t.seriesName){var l=[];Array.isArray(t.seriesName)?l=t.seriesName:l.push(t.seriesName),l.forEach((function(t){e.series.forEach((function(e,n){if(e.name===t){var l=n;a===n||r?!r||s.indexOf(n)>-1?i[a].push([a,n]):console.warn("Series '"+e.name+"' referenced more than once in what looks like the new style. That is, when using either seriesName: [], or when there are more series than yaxes."):(i[n].push([n,a]),l=a),o=!0,-1!==(l=s.indexOf(l))&&s.splice(l,1)}}))}))}o||n.push(a)})),i=i.map((function(t,e){var i=[];return t.forEach((function(t){a[t[1]]=t[0],i.push(t[1])})),i}));for(var o=e.yaxis.length-1,l=0;l0&&void 0!==arguments[0]?arguments[0]:null;return 0===(null===t?this.w.config.series.filter((function(t){return null!==t})):this.w.config.series[t].data.filter((function(t){return null!==t}))).length}},{key:"seriesHaveSameValues",value:function(t){return this.w.globals.series[t].every((function(t,e,i){return t===i[0]}))}},{key:"getCategoryLabels",value:function(t){var e=this.w,i=t.slice();return e.config.xaxis.convertedCatToNumeric&&(i=t.map((function(t,i){return e.config.xaxis.labels.formatter(t-e.globals.minX+1)}))),i}},{key:"getLargestSeries",value:function(){var t=this.w;t.globals.maxValsInArrayIndex=t.globals.series.map((function(t){return t.length})).indexOf(Math.max.apply(Math,t.globals.series.map((function(t){return t.length}))))}},{key:"getLargestMarkerSize",value:function(){var t=this.w,e=0;return t.globals.markers.size.forEach((function(t){e=Math.max(e,t)})),t.config.markers.discrete&&t.config.markers.discrete.length&&t.config.markers.discrete.forEach((function(t){e=Math.max(e,t.size)})),e>0&&(t.config.markers.hover.size>0?e=t.config.markers.hover.size:e+=t.config.markers.hover.sizeOffset),t.globals.markers.largestSize=e,e}},{key:"getSeriesTotals",value:function(){var t=this.w;t.globals.seriesTotals=t.globals.series.map((function(t,e){var i=0;if(Array.isArray(t))for(var a=0;at&&i.globals.seriesX[s][n]0){var g=function(t,e){var i=s.config.yaxis[s.globals.seriesYAxisReverseMap[e]],r=t<0?-1:1;return t=Math.abs(t),i.logarithmic&&(t=a.getBaseLog(i.logBase,t)),-r*t/n[e]};if(r.isMultipleYAxis){l=[];for(var p=0;p0&&e.forEach((function(e){var n=[],o=[];t.i.forEach((function(i,a){s.config.series[i].group===e&&(n.push(t.series[a]),o.push(i))})),n.length>0&&r.push(a.draw(n,i,o))})),r}}],[{key:"checkComboSeries",value:function(t,e){var i=!1,a=0,s=0;return void 0===e&&(e="line"),t.length&&void 0!==t[0].type&&t.forEach((function(t){"bar"!==t.type&&"column"!==t.type&&"candlestick"!==t.type&&"boxPlot"!==t.type||a++,void 0!==t.type&&t.type!==e&&s++})),s>0&&(i=!0),{comboBarCount:a,comboCharts:i}}},{key:"extendArrayProps",value:function(t,e,i){var a,s,r,n,o,l;(null!==(a=e)&&void 0!==a&&a.yaxis&&(e=t.extendYAxis(e,i)),null!==(s=e)&&void 0!==s&&s.annotations)&&(e.annotations.yaxis&&(e=t.extendYAxisAnnotations(e)),null!==(r=e)&&void 0!==r&&null!==(n=r.annotations)&&void 0!==n&&n.xaxis&&(e=t.extendXAxisAnnotations(e)),null!==(o=e)&&void 0!==o&&null!==(l=o.annotations)&&void 0!==l&&l.points&&(e=t.extendPointAnnotations(e)));return e}}]),t}(),Ii=function(){function t(e){i(this,t),this.w=e.w,this.annoCtx=e}return s(t,[{key:"setOrientations",value:function(t){var e=arguments.length>1&&void 0!==arguments[1]?arguments[1]:null,i=this.w;if("vertical"===t.label.orientation){var a=null!==e?e:0,s=i.globals.dom.baseEl.querySelector(".apexcharts-xaxis-annotations .apexcharts-xaxis-annotation-label[rel='".concat(a,"']"));if(null!==s){var r=s.getBoundingClientRect();s.setAttribute("x",parseFloat(s.getAttribute("x"))-r.height+4);var n="top"===t.label.position?r.width:-r.width;s.setAttribute("y",parseFloat(s.getAttribute("y"))+n);var o=this.annoCtx.graphics.rotateAroundCenter(s),l=o.x,h=o.y;s.setAttribute("transform","rotate(-90 ".concat(l," ").concat(h,")"))}}}},{key:"addBackgroundToAnno",value:function(t,e){var i=this.w;if(!t||!e.label.text||!String(e.label.text).trim())return null;var a=i.globals.dom.baseEl.querySelector(".apexcharts-grid").getBoundingClientRect(),s=t.getBoundingClientRect(),r=e.label.style.padding,n=r.left,o=r.right,l=r.top,h=r.bottom;if("vertical"===e.label.orientation){var c=[n,o,l,h];l=c[0],h=c[1],n=c[2],o=c[3]}var d=s.left-a.left-n,u=s.top-a.top-l,g=this.annoCtx.graphics.drawRect(d-i.globals.barPadForNumericAxis,u,s.width+n+o,s.height+l+h,e.label.borderRadius,e.label.style.background,1,e.label.borderWidth,e.label.borderColor,0);return e.id&&g.node.classList.add(e.id),g}},{key:"annotationsBackground",value:function(){var t=this,e=this.w,i=function(i,a,s){var r=e.globals.dom.baseEl.querySelector(".apexcharts-".concat(s,"-annotations .apexcharts-").concat(s,"-annotation-label[rel='").concat(a,"']"));if(r){var n=r.parentNode,o=t.addBackgroundToAnno(r,i);o&&(n.insertBefore(o.node,r),i.label.mouseEnter&&o.node.addEventListener("mouseenter",i.label.mouseEnter.bind(t,i)),i.label.mouseLeave&&o.node.addEventListener("mouseleave",i.label.mouseLeave.bind(t,i)),i.label.click&&o.node.addEventListener("click",i.label.click.bind(t,i)))}};e.config.annotations.xaxis.forEach((function(t,e){return i(t,e,"xaxis")})),e.config.annotations.yaxis.forEach((function(t,e){return i(t,e,"yaxis")})),e.config.annotations.points.forEach((function(t,e){return i(t,e,"point")}))}},{key:"getY1Y2",value:function(t,e){var i,a=this.w,s="y1"===t?e.y:e.y2,r=!1;if(this.annoCtx.invertAxis){var n=a.config.xaxis.convertedCatToNumeric?a.globals.categoryLabels:a.globals.labels,o=n.indexOf(s),l=a.globals.dom.baseEl.querySelector(".apexcharts-yaxis-texts-g text:nth-child(".concat(o+1,")"));i=l?parseFloat(l.getAttribute("y")):(a.globals.gridHeight/n.length-1)*(o+1)-a.globals.barHeight,void 0!==e.seriesIndex&&a.globals.barHeight&&(i-=a.globals.barHeight/2*(a.globals.series.length-1)-a.globals.barHeight*e.seriesIndex)}else{var h,c=a.globals.seriesYAxisMap[e.yAxisIndex][0],d=a.config.yaxis[e.yAxisIndex].logarithmic?new Pi(this.annoCtx.ctx).getLogVal(a.config.yaxis[e.yAxisIndex].logBase,s,c)/a.globals.yLogRatio[c]:(s-a.globals.minYArr[c])/(a.globals.yRange[c]/a.globals.gridHeight);i=a.globals.gridHeight-Math.min(Math.max(d,0),a.globals.gridHeight),r=d>a.globals.gridHeight||d<0,!e.marker||void 0!==e.y&&null!==e.y||(i=0),null!==(h=a.config.yaxis[e.yAxisIndex])&&void 0!==h&&h.reversed&&(i=d)}return"string"==typeof s&&s.includes("px")&&(i=parseFloat(s)),{yP:i,clipped:r}}},{key:"getX1X2",value:function(t,e){var i=this.w,a="x1"===t?e.x:e.x2,s=this.annoCtx.invertAxis?i.globals.minY:i.globals.minX,r=this.annoCtx.invertAxis?i.globals.maxY:i.globals.maxX,n=this.annoCtx.invertAxis?i.globals.yRange[0]:i.globals.xRange,o=!1,l=this.annoCtx.inversedReversedAxis?(r-a)/(n/i.globals.gridWidth):(a-s)/(n/i.globals.gridWidth);return"category"!==i.config.xaxis.type&&!i.config.xaxis.convertedCatToNumeric||this.annoCtx.invertAxis||i.globals.dataFormatXNumeric||i.config.chart.sparkline.enabled||(l=this.getStringX(a)),"string"==typeof a&&a.includes("px")&&(l=parseFloat(a)),null==a&&e.marker&&(l=i.globals.gridWidth),void 0!==e.seriesIndex&&i.globals.barWidth&&!this.annoCtx.invertAxis&&(l-=i.globals.barWidth/2*(i.globals.series.length-1)-i.globals.barWidth*e.seriesIndex),"number"!=typeof l&&(l=0,o=!0),parseFloat(l.toFixed(10))>parseFloat(i.globals.gridWidth.toFixed(10))?(l=i.globals.gridWidth,o=!0):l<0&&(l=0,o=!0),{x:l,clipped:o}}},{key:"getStringX",value:function(t){var e=this.w,i=t;e.config.xaxis.convertedCatToNumeric&&e.globals.categoryLabels.length&&(t=e.globals.categoryLabels.indexOf(t)+1);var a=e.globals.labels.map((function(t){return Array.isArray(t)?t.join(" "):t})).indexOf(t),s=e.globals.dom.baseEl.querySelector(".apexcharts-xaxis-texts-g text:nth-child(".concat(a+1,")"));return s&&(i=parseFloat(s.getAttribute("x"))),i}}]),t}(),Ti=function(){function t(e){i(this,t),this.w=e.w,this.annoCtx=e,this.invertAxis=this.annoCtx.invertAxis,this.helpers=new Ii(this.annoCtx)}return s(t,[{key:"addXaxisAnnotation",value:function(t,e,i){var a,s=this.w,r=this.helpers.getX1X2("x1",t),n=r.x,o=r.clipped,l=!0,h=t.label.text,c=t.strokeDashArray;if(v.isNumber(n)){if(null===t.x2||void 0===t.x2){if(!o){var d=this.annoCtx.graphics.drawLine(n+t.offsetX,0+t.offsetY,n+t.offsetX,s.globals.gridHeight+t.offsetY,t.borderColor,c,t.borderWidth);e.appendChild(d.node),t.id&&d.node.classList.add(t.id)}}else{var u=this.helpers.getX1X2("x2",t);if(a=u.x,l=u.clipped,a12?u-12:0===u?12:u;e=(e=(e=(e=e.replace(/(^|[^\\])HH+/g,"$1"+l(u))).replace(/(^|[^\\])H/g,"$1"+u)).replace(/(^|[^\\])hh+/g,"$1"+l(g))).replace(/(^|[^\\])h/g,"$1"+g);var p=a?t.getUTCMinutes():t.getMinutes();e=(e=e.replace(/(^|[^\\])mm+/g,"$1"+l(p))).replace(/(^|[^\\])m/g,"$1"+p);var x=a?t.getUTCSeconds():t.getSeconds();e=(e=e.replace(/(^|[^\\])ss+/g,"$1"+l(x))).replace(/(^|[^\\])s/g,"$1"+x);var b=a?t.getUTCMilliseconds():t.getMilliseconds();e=e.replace(/(^|[^\\])fff+/g,"$1"+l(b,3)),b=Math.round(b/10),e=e.replace(/(^|[^\\])ff/g,"$1"+l(b)),b=Math.round(b/10);var m=u<12?"AM":"PM";e=(e=(e=e.replace(/(^|[^\\])f/g,"$1"+b)).replace(/(^|[^\\])TT+/g,"$1"+m)).replace(/(^|[^\\])T/g,"$1"+m.charAt(0));var v=m.toLowerCase();e=(e=e.replace(/(^|[^\\])tt+/g,"$1"+v)).replace(/(^|[^\\])t/g,"$1"+v.charAt(0));var y=-t.getTimezoneOffset(),w=a||!y?"Z":y>0?"+":"-";if(!a){var k=(y=Math.abs(y))%60;w+=l(Math.floor(y/60))+":"+l(k)}e=e.replace(/(^|[^\\])K/g,"$1"+w);var A=(a?t.getUTCDay():t.getDay())+1;return e=(e=(e=(e=(e=e.replace(new RegExp(n[0],"g"),n[A])).replace(new RegExp(o[0],"g"),o[A])).replace(new RegExp(s[0],"g"),s[c])).replace(new RegExp(r[0],"g"),r[c])).replace(/\\(.)/g,"$1")}},{key:"getTimeUnitsfromTimestamp",value:function(t,e,i){var a=this.w;void 0!==a.config.xaxis.min&&(t=a.config.xaxis.min),void 0!==a.config.xaxis.max&&(e=a.config.xaxis.max);var s=this.getDate(t),r=this.getDate(e),n=this.formatDate(s,"yyyy MM dd HH mm ss fff").split(" "),o=this.formatDate(r,"yyyy MM dd HH mm ss fff").split(" ");return{minMillisecond:parseInt(n[6],10),maxMillisecond:parseInt(o[6],10),minSecond:parseInt(n[5],10),maxSecond:parseInt(o[5],10),minMinute:parseInt(n[4],10),maxMinute:parseInt(o[4],10),minHour:parseInt(n[3],10),maxHour:parseInt(o[3],10),minDate:parseInt(n[2],10),maxDate:parseInt(o[2],10),minMonth:parseInt(n[1],10)-1,maxMonth:parseInt(o[1],10)-1,minYear:parseInt(n[0],10),maxYear:parseInt(o[0],10)}}},{key:"isLeapYear",value:function(t){return t%4==0&&t%100!=0||t%400==0}},{key:"calculcateLastDaysOfMonth",value:function(t,e,i){return this.determineDaysOfMonths(t,e)-i}},{key:"determineDaysOfYear",value:function(t){var e=365;return this.isLeapYear(t)&&(e=366),e}},{key:"determineRemainingDaysOfYear",value:function(t,e,i){var a=this.daysCntOfYear[e]+i;return e>1&&this.isLeapYear()&&a++,a}},{key:"determineDaysOfMonths",value:function(t,e){var i=30;switch(t=v.monthMod(t),!0){case this.months30.indexOf(t)>-1:2===t&&(i=this.isLeapYear(e)?29:28);break;case this.months31.indexOf(t)>-1:default:i=31}return i}}]),t}(),Xi=function(){function t(e){i(this,t),this.ctx=e,this.w=e.w,this.tooltipKeyFormat="dd MMM"}return s(t,[{key:"xLabelFormat",value:function(t,e,i,a){var s=this.w;if("datetime"===s.config.xaxis.type&&void 0===s.config.xaxis.labels.formatter&&void 0===s.config.tooltip.x.formatter){var r=new zi(this.ctx);return r.formatDate(r.getDate(e),s.config.tooltip.x.format)}return t(e,i,a)}},{key:"defaultGeneralFormatter",value:function(t){return Array.isArray(t)?t.map((function(t){return t})):t}},{key:"defaultYFormatter",value:function(t,e,i){var a=this.w;if(v.isNumber(t))if(0!==a.globals.yValueDecimal)t=t.toFixed(void 0!==e.decimalsInFloat?e.decimalsInFloat:a.globals.yValueDecimal);else{var s=t.toFixed(0);t=t==s?s:t.toFixed(1)}return t}},{key:"setLabelFormatters",value:function(){var t=this,e=this.w;return e.globals.xaxisTooltipFormatter=function(e){return t.defaultGeneralFormatter(e)},e.globals.ttKeyFormatter=function(e){return t.defaultGeneralFormatter(e)},e.globals.ttZFormatter=function(t){return t},e.globals.legendFormatter=function(e){return t.defaultGeneralFormatter(e)},void 0!==e.config.xaxis.labels.formatter?e.globals.xLabelFormatter=e.config.xaxis.labels.formatter:e.globals.xLabelFormatter=function(t){if(v.isNumber(t)){if(!e.config.xaxis.convertedCatToNumeric&&"numeric"===e.config.xaxis.type){if(v.isNumber(e.config.xaxis.decimalsInFloat))return t.toFixed(e.config.xaxis.decimalsInFloat);var i=e.globals.maxX-e.globals.minX;return i>0&&i<100?t.toFixed(1):t.toFixed(0)}if(e.globals.isBarHorizontal)if(e.globals.maxY-e.globals.minYArr<4)return t.toFixed(1);return t.toFixed(0)}return t},"function"==typeof e.config.tooltip.x.formatter?e.globals.ttKeyFormatter=e.config.tooltip.x.formatter:e.globals.ttKeyFormatter=e.globals.xLabelFormatter,"function"==typeof e.config.xaxis.tooltip.formatter&&(e.globals.xaxisTooltipFormatter=e.config.xaxis.tooltip.formatter),(Array.isArray(e.config.tooltip.y)||void 0!==e.config.tooltip.y.formatter)&&(e.globals.ttVal=e.config.tooltip.y),void 0!==e.config.tooltip.z.formatter&&(e.globals.ttZFormatter=e.config.tooltip.z.formatter),void 0!==e.config.legend.formatter&&(e.globals.legendFormatter=e.config.legend.formatter),e.config.yaxis.forEach((function(i,a){void 0!==i.labels.formatter?e.globals.yLabelFormatters[a]=i.labels.formatter:e.globals.yLabelFormatters[a]=function(s){return e.globals.xyCharts?Array.isArray(s)?s.map((function(e){return t.defaultYFormatter(e,i,a)})):t.defaultYFormatter(s,i,a):s}})),e.globals}},{key:"heatmapLabelFormatters",value:function(){var t=this.w;if("heatmap"===t.config.chart.type){t.globals.yAxisScale[0].result=t.globals.seriesNames.slice();var e=t.globals.seriesNames.reduce((function(t,e){return t.length>e.length?t:e}),0);t.globals.yAxisScale[0].niceMax=e,t.globals.yAxisScale[0].niceMin=e}}}]),t}(),Ri=function(){function t(e){i(this,t),this.ctx=e,this.w=e.w}return s(t,[{key:"getLabel",value:function(t,e,i,a){var s=arguments.length>4&&void 0!==arguments[4]?arguments[4]:[],r=arguments.length>5&&void 0!==arguments[5]?arguments[5]:"12px",n=!(arguments.length>6&&void 0!==arguments[6])||arguments[6],o=this.w,l=void 0===t[a]?"":t[a],h=l,c=o.globals.xLabelFormatter,d=o.config.xaxis.labels.formatter,u=!1,g=new Xi(this.ctx),p=l;n&&(h=g.xLabelFormat(c,l,p,{i:a,dateFormatter:new zi(this.ctx).formatDate,w:o}),void 0!==d&&(h=d(l,t[a],{i:a,dateFormatter:new zi(this.ctx).formatDate,w:o})));var f,x;e.length>0?(f=e[a].unit,x=null,e.forEach((function(t){"month"===t.unit?x="year":"day"===t.unit?x="month":"hour"===t.unit?x="day":"minute"===t.unit&&(x="hour")})),u=x===f,i=e[a].position,h=e[a].value):"datetime"===o.config.xaxis.type&&void 0===d&&(h=""),void 0===h&&(h=""),h=Array.isArray(h)?h:h.toString();var b=new Mi(this.ctx),m={};m=o.globals.rotateXLabels&&n?b.getTextRects(h,parseInt(r,10),null,"rotate(".concat(o.config.xaxis.labels.rotate," 0 0)"),!1):b.getTextRects(h,parseInt(r,10));var v=!o.config.xaxis.labels.showDuplicates&&this.ctx.timeScale;return!Array.isArray(h)&&("NaN"===String(h)||s.indexOf(h)>=0&&v)&&(h=""),{x:i,text:h,textRect:m,isBold:u}}},{key:"checkLabelBasedOnTickamount",value:function(t,e,i){var a=this.w,s=a.config.xaxis.tickAmount;return"dataPoints"===s&&(s=Math.round(a.globals.gridWidth/120)),s>i||t%Math.round(i/(s+1))==0||(e.text=""),e}},{key:"checkForOverflowingLabels",value:function(t,e,i,a,s){var r=this.w;if(0===t&&r.globals.skipFirstTimelinelabel&&(e.text=""),t===i-1&&r.globals.skipLastTimelinelabel&&(e.text=""),r.config.xaxis.labels.hideOverlappingLabels&&a.length>0){var n=s[s.length-1];if(r.config.xaxis.labels.trim&&"datetime"!==r.config.xaxis.type)return e;e.xa.length||a.some((function(t){return Array.isArray(t.seriesName)}))?t:i.seriesYAxisReverseMap[t]}},{key:"isYAxisHidden",value:function(t){var e=this.w,i=e.config.yaxis[t];if(!i.show||this.yAxisAllSeriesCollapsed(t))return!0;if(!i.showForNullSeries){var a=e.globals.seriesYAxisMap[t],s=new Pi(this.ctx);return a.every((function(t){return s.isSeriesNull(t)}))}return!1}},{key:"getYAxisForeColor",value:function(t,e){var i=this.w;return Array.isArray(t)&&i.globals.yAxisScale[e]&&this.ctx.theme.pushExtraColors(t,i.globals.yAxisScale[e].result.length,!1),t}},{key:"drawYAxisTicks",value:function(t,e,i,a,s,r,n){var o=this.w,l=new Mi(this.ctx),h=o.globals.translateY+o.config.yaxis[s].labels.offsetY;if(o.globals.isBarHorizontal?h=0:"heatmap"===o.config.chart.type&&(h+=r/2),a.show&&e>0){!0===o.config.yaxis[s].opposite&&(t+=a.width);for(var c=e;c>=0;c--){var d=l.drawLine(t+i.offsetX-a.width+a.offsetX,h+a.offsetY,t+i.offsetX+a.offsetX,h+a.offsetY,a.color);n.add(d),h+=r}}}}]),t}(),Ei=function(){function t(e){i(this,t),this.w=e.w,this.annoCtx=e,this.helpers=new Ii(this.annoCtx),this.axesUtils=new Ri(this.annoCtx)}return s(t,[{key:"addYaxisAnnotation",value:function(t,e,i){var a,s=this.w,r=t.strokeDashArray,n=this.helpers.getY1Y2("y1",t),o=n.yP,l=n.clipped,h=!0,c=!1,d=t.label.text;if(null===t.y2||void 0===t.y2){if(!l){c=!0;var u=this.annoCtx.graphics.drawLine(0+t.offsetX,o+t.offsetY,this._getYAxisAnnotationWidth(t),o+t.offsetY,t.borderColor,r,t.borderWidth);e.appendChild(u.node),t.id&&u.node.classList.add(t.id)}}else{if(a=(n=this.helpers.getY1Y2("y2",t)).yP,h=n.clipped,a>o){var g=o;o=a,a=g}if(!l||!h){c=!0;var p=this.annoCtx.graphics.drawRect(0+t.offsetX,a+t.offsetY,this._getYAxisAnnotationWidth(t),o-a,0,t.fillColor,t.opacity,1,t.borderColor,r);p.node.classList.add("apexcharts-annotation-rect"),p.attr("clip-path","url(#gridRectMask".concat(s.globals.cuid,")")),e.appendChild(p.node),t.id&&p.node.classList.add(t.id)}}if(c){var f="right"===t.label.position?s.globals.gridWidth:"center"===t.label.position?s.globals.gridWidth/2:0,x=this.annoCtx.graphics.drawText({x:f+t.label.offsetX,y:(null!=a?a:o)+t.label.offsetY-3,text:d,textAnchor:t.label.textAnchor,fontSize:t.label.style.fontSize,fontFamily:t.label.style.fontFamily,fontWeight:t.label.style.fontWeight,foreColor:t.label.style.color,cssClass:"apexcharts-yaxis-annotation-label ".concat(t.label.style.cssClass," ").concat(t.id?t.id:"")});x.attr({rel:i}),e.appendChild(x.node)}}},{key:"_getYAxisAnnotationWidth",value:function(t){var e=this.w;e.globals.gridWidth;return(t.width.indexOf("%")>-1?e.globals.gridWidth*parseInt(t.width,10)/100:parseInt(t.width,10))+t.offsetX}},{key:"drawYAxisAnnotations",value:function(){var t=this,e=this.w,i=this.annoCtx.graphics.group({class:"apexcharts-yaxis-annotations"});return e.config.annotations.yaxis.forEach((function(e,a){e.yAxisIndex=t.axesUtils.translateYAxisIndex(e.yAxisIndex),t.axesUtils.isYAxisHidden(e.yAxisIndex)&&t.axesUtils.yAxisAllSeriesCollapsed(e.yAxisIndex)||t.addYaxisAnnotation(e,i.node,a)})),i}}]),t}(),Yi=function(){function t(e){i(this,t),this.w=e.w,this.annoCtx=e,this.helpers=new Ii(this.annoCtx)}return s(t,[{key:"addPointAnnotation",value:function(t,e,i){if(!(this.w.globals.collapsedSeriesIndices.indexOf(t.seriesIndex)>-1)){var a=this.helpers.getX1X2("x1",t),s=a.x,r=a.clipped,n=(a=this.helpers.getY1Y2("y1",t)).yP,o=a.clipped;if(v.isNumber(s)&&!o&&!r){var l={pSize:t.marker.size,pointStrokeWidth:t.marker.strokeWidth,pointFillColor:t.marker.fillColor,pointStrokeColor:t.marker.strokeColor,shape:t.marker.shape,pRadius:t.marker.radius,class:"apexcharts-point-annotation-marker ".concat(t.marker.cssClass," ").concat(t.id?t.id:"")},h=this.annoCtx.graphics.drawMarker(s+t.marker.offsetX,n+t.marker.offsetY,l);e.appendChild(h.node);var c=t.label.text?t.label.text:"",d=this.annoCtx.graphics.drawText({x:s+t.label.offsetX,y:n+t.label.offsetY-t.marker.size-parseFloat(t.label.style.fontSize)/1.6,text:c,textAnchor:t.label.textAnchor,fontSize:t.label.style.fontSize,fontFamily:t.label.style.fontFamily,fontWeight:t.label.style.fontWeight,foreColor:t.label.style.color,cssClass:"apexcharts-point-annotation-label ".concat(t.label.style.cssClass," ").concat(t.id?t.id:"")});if(d.attr({rel:i}),e.appendChild(d.node),t.customSVG.SVG){var u=this.annoCtx.graphics.group({class:"apexcharts-point-annotations-custom-svg "+t.customSVG.cssClass});u.attr({transform:"translate(".concat(s+t.customSVG.offsetX,", ").concat(n+t.customSVG.offsetY,")")}),u.node.innerHTML=t.customSVG.SVG,e.appendChild(u.node)}if(t.image.path){var g=t.image.width?t.image.width:20,p=t.image.height?t.image.height:20;h=this.annoCtx.addImage({x:s+t.image.offsetX-g/2,y:n+t.image.offsetY-p/2,width:g,height:p,path:t.image.path,appendTo:".apexcharts-point-annotations"})}t.mouseEnter&&h.node.addEventListener("mouseenter",t.mouseEnter.bind(this,t)),t.mouseLeave&&h.node.addEventListener("mouseleave",t.mouseLeave.bind(this,t)),t.click&&h.node.addEventListener("click",t.click.bind(this,t))}}}},{key:"drawPointAnnotations",value:function(){var t=this,e=this.w,i=this.annoCtx.graphics.group({class:"apexcharts-point-annotations"});return e.config.annotations.points.map((function(e,a){t.addPointAnnotation(e,i.node,a)})),i}}]),t}();var Hi={name:"en",options:{months:["January","February","March","April","May","June","July","August","September","October","November","December"],shortMonths:["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"],days:["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"],shortDays:["Sun","Mon","Tue","Wed","Thu","Fri","Sat"],toolbar:{exportToSVG:"Download SVG",exportToPNG:"Download PNG",exportToCSV:"Download CSV",menu:"Menu",selection:"Selection",selectionZoom:"Selection Zoom",zoomIn:"Zoom In",zoomOut:"Zoom Out",pan:"Panning",reset:"Reset Zoom"}}},Oi=function(){function t(){i(this,t),this.yAxis={show:!0,showAlways:!1,showForNullSeries:!0,seriesName:void 0,opposite:!1,reversed:!1,logarithmic:!1,logBase:10,tickAmount:void 0,stepSize:void 0,forceNiceScale:!1,max:void 0,min:void 0,floating:!1,decimalsInFloat:void 0,labels:{show:!0,showDuplicates:!1,minWidth:0,maxWidth:160,offsetX:0,offsetY:0,align:void 0,rotate:0,padding:20,style:{colors:[],fontSize:"11px",fontWeight:400,fontFamily:void 0,cssClass:""},formatter:void 0},axisBorder:{show:!1,color:"#e0e0e0",width:1,offsetX:0,offsetY:0},axisTicks:{show:!1,color:"#e0e0e0",width:6,offsetX:0,offsetY:0},title:{text:void 0,rotate:-90,offsetY:0,offsetX:0,style:{color:void 0,fontSize:"11px",fontWeight:900,fontFamily:void 0,cssClass:""}},tooltip:{enabled:!1,offsetX:0},crosshairs:{show:!0,position:"front",stroke:{color:"#b6b6b6",width:1,dashArray:0}}},this.pointAnnotation={id:void 0,x:0,y:null,yAxisIndex:0,seriesIndex:void 0,mouseEnter:void 0,mouseLeave:void 0,click:void 0,marker:{size:4,fillColor:"#fff",strokeWidth:2,strokeColor:"#333",shape:"circle",offsetX:0,offsetY:0,cssClass:""},label:{borderColor:"#c2c2c2",borderWidth:1,borderRadius:2,text:void 0,textAnchor:"middle",offsetX:0,offsetY:0,mouseEnter:void 0,mouseLeave:void 0,click:void 0,style:{background:"#fff",color:void 0,fontSize:"11px",fontFamily:void 0,fontWeight:400,cssClass:"",padding:{left:5,right:5,top:2,bottom:2}}},customSVG:{SVG:void 0,cssClass:void 0,offsetX:0,offsetY:0},image:{path:void 0,width:20,height:20,offsetX:0,offsetY:0}},this.yAxisAnnotation={id:void 0,y:0,y2:null,strokeDashArray:1,fillColor:"#c2c2c2",borderColor:"#c2c2c2",borderWidth:1,opacity:.3,offsetX:0,offsetY:0,width:"100%",yAxisIndex:0,label:{borderColor:"#c2c2c2",borderWidth:1,borderRadius:2,text:void 0,textAnchor:"end",position:"right",offsetX:0,offsetY:-3,mouseEnter:void 0,mouseLeave:void 0,click:void 0,style:{background:"#fff",color:void 0,fontSize:"11px",fontFamily:void 0,fontWeight:400,cssClass:"",padding:{left:5,right:5,top:2,bottom:2}}}},this.xAxisAnnotation={id:void 0,x:0,x2:null,strokeDashArray:1,fillColor:"#c2c2c2",borderColor:"#c2c2c2",borderWidth:1,opacity:.3,offsetX:0,offsetY:0,label:{borderColor:"#c2c2c2",borderWidth:1,borderRadius:2,text:void 0,textAnchor:"middle",orientation:"vertical",position:"top",offsetX:0,offsetY:0,mouseEnter:void 0,mouseLeave:void 0,click:void 0,style:{background:"#fff",color:void 0,fontSize:"11px",fontFamily:void 0,fontWeight:400,cssClass:"",padding:{left:5,right:5,top:2,bottom:2}}}},this.text={x:0,y:0,text:"",textAnchor:"start",foreColor:void 0,fontSize:"13px",fontFamily:void 0,fontWeight:400,appendTo:".apexcharts-annotations",backgroundColor:"transparent",borderColor:"#c2c2c2",borderRadius:0,borderWidth:0,paddingLeft:4,paddingRight:4,paddingTop:2,paddingBottom:2}}return s(t,[{key:"init",value:function(){return{annotations:{yaxis:[this.yAxisAnnotation],xaxis:[this.xAxisAnnotation],points:[this.pointAnnotation],texts:[],images:[],shapes:[]},chart:{animations:{enabled:!0,speed:800,animateGradually:{delay:150,enabled:!0},dynamicAnimation:{enabled:!0,speed:350}},background:"",locales:[Hi],defaultLocale:"en",dropShadow:{enabled:!1,enabledOnSeries:void 0,top:2,left:2,blur:4,color:"#000",opacity:.7},events:{animationEnd:void 0,beforeMount:void 0,mounted:void 0,updated:void 0,click:void 0,mouseMove:void 0,mouseLeave:void 0,xAxisLabelClick:void 0,legendClick:void 0,markerClick:void 0,selection:void 0,dataPointSelection:void 0,dataPointMouseEnter:void 0,dataPointMouseLeave:void 0,beforeZoom:void 0,beforeResetZoom:void 0,zoomed:void 0,scrolled:void 0,brushScrolled:void 0},foreColor:"#373d3f",fontFamily:"Helvetica, Arial, sans-serif",height:"auto",parentHeightOffset:15,redrawOnParentResize:!0,redrawOnWindowResize:!0,id:void 0,group:void 0,nonce:void 0,offsetX:0,offsetY:0,injectStyleSheet:!0,selection:{enabled:!1,type:"x",fill:{color:"#24292e",opacity:.1},stroke:{width:1,color:"#24292e",opacity:.4,dashArray:3},xaxis:{min:void 0,max:void 0},yaxis:{min:void 0,max:void 0}},sparkline:{enabled:!1},brush:{enabled:!1,autoScaleYaxis:!0,target:void 0,targets:void 0},stacked:!1,stackOnlyBar:!0,stackType:"normal",toolbar:{show:!0,offsetX:0,offsetY:0,tools:{download:!0,selection:!0,zoom:!0,zoomin:!0,zoomout:!0,pan:!0,reset:!0,customIcons:[]},export:{csv:{filename:void 0,columnDelimiter:",",headerCategory:"category",headerValue:"value",categoryFormatter:void 0,valueFormatter:void 0},png:{filename:void 0},svg:{filename:void 0},scale:void 0,width:void 0},autoSelected:"zoom"},type:"line",width:"100%",zoom:{enabled:!0,type:"x",autoScaleYaxis:!1,allowMouseWheelZoom:!0,zoomedArea:{fill:{color:"#90CAF9",opacity:.4},stroke:{color:"#0D47A1",opacity:.4,width:1}}}},parsing:{x:void 0,y:void 0},plotOptions:{line:{isSlopeChart:!1,colors:{threshold:0,colorAboveThreshold:void 0,colorBelowThreshold:void 0}},area:{fillTo:"origin"},bar:{horizontal:!1,columnWidth:"70%",barHeight:"70%",distributed:!1,borderRadius:0,borderRadiusApplication:"around",borderRadiusWhenStacked:"last",rangeBarOverlap:!0,rangeBarGroupRows:!1,hideZeroBarsWhenGrouped:!1,isDumbbell:!1,dumbbellColors:void 0,isFunnel:!1,isFunnel3d:!0,colors:{ranges:[],backgroundBarColors:[],backgroundBarOpacity:1,backgroundBarRadius:0},dataLabels:{position:"top",maxItems:100,hideOverflowingLabels:!0,orientation:"horizontal",total:{enabled:!1,formatter:void 0,offsetX:0,offsetY:0,style:{color:"#373d3f",fontSize:"12px",fontFamily:void 0,fontWeight:600}}}},bubble:{zScaling:!0,minBubbleRadius:void 0,maxBubbleRadius:void 0},candlestick:{colors:{upward:"#00B746",downward:"#EF403C"},wick:{useFillColor:!0}},boxPlot:{colors:{upper:"#00E396",lower:"#008FFB"}},heatmap:{radius:2,enableShades:!0,shadeIntensity:.5,reverseNegativeShade:!1,distributed:!1,useFillColorAsStroke:!1,colorScale:{inverse:!1,ranges:[],min:void 0,max:void 0}},treemap:{enableShades:!0,shadeIntensity:.5,distributed:!1,reverseNegativeShade:!1,useFillColorAsStroke:!1,borderRadius:4,dataLabels:{format:"scale"},colorScale:{inverse:!1,ranges:[],min:void 0,max:void 0},seriesTitle:{show:!0,offsetY:1,offsetX:1,borderColor:"#000",borderWidth:1,borderRadius:2,style:{background:"rgba(0, 0, 0, 0.6)",color:"#fff",fontSize:"12px",fontFamily:void 0,fontWeight:400,cssClass:"",padding:{left:6,right:6,top:2,bottom:2}}}},radialBar:{inverseOrder:!1,startAngle:0,endAngle:360,offsetX:0,offsetY:0,hollow:{margin:5,size:"50%",background:"transparent",image:void 0,imageWidth:150,imageHeight:150,imageOffsetX:0,imageOffsetY:0,imageClipped:!0,position:"front",dropShadow:{enabled:!1,top:0,left:0,blur:3,color:"#000",opacity:.5}},track:{show:!0,startAngle:void 0,endAngle:void 0,background:"#f2f2f2",strokeWidth:"97%",opacity:1,margin:5,dropShadow:{enabled:!1,top:0,left:0,blur:3,color:"#000",opacity:.5}},dataLabels:{show:!0,name:{show:!0,fontSize:"16px",fontFamily:void 0,fontWeight:600,color:void 0,offsetY:0,formatter:function(t){return t}},value:{show:!0,fontSize:"14px",fontFamily:void 0,fontWeight:400,color:void 0,offsetY:16,formatter:function(t){return t+"%"}},total:{show:!1,label:"Total",fontSize:"16px",fontWeight:600,fontFamily:void 0,color:void 0,formatter:function(t){return t.globals.seriesTotals.reduce((function(t,e){return t+e}),0)/t.globals.series.length+"%"}}},barLabels:{enabled:!1,offsetX:0,offsetY:0,useSeriesColors:!0,fontFamily:void 0,fontWeight:600,fontSize:"16px",formatter:function(t){return t},onClick:void 0}},pie:{customScale:1,offsetX:0,offsetY:0,startAngle:0,endAngle:360,expandOnClick:!0,dataLabels:{offset:0,minAngleToShowLabel:10},donut:{size:"65%",background:"transparent",labels:{show:!1,name:{show:!0,fontSize:"16px",fontFamily:void 0,fontWeight:600,color:void 0,offsetY:-10,formatter:function(t){return t}},value:{show:!0,fontSize:"20px",fontFamily:void 0,fontWeight:400,color:void 0,offsetY:10,formatter:function(t){return t}},total:{show:!1,showAlways:!1,label:"Total",fontSize:"16px",fontWeight:400,fontFamily:void 0,color:void 0,formatter:function(t){return t.globals.seriesTotals.reduce((function(t,e){return t+e}),0)}}}}},polarArea:{rings:{strokeWidth:1,strokeColor:"#e8e8e8"},spokes:{strokeWidth:1,connectorColors:"#e8e8e8"}},radar:{size:void 0,offsetX:0,offsetY:0,polygons:{strokeWidth:1,strokeColors:"#e8e8e8",connectorColors:"#e8e8e8",fill:{colors:void 0}}}},colors:void 0,dataLabels:{enabled:!0,enabledOnSeries:void 0,formatter:function(t){return null!==t?t:""},textAnchor:"middle",distributed:!1,offsetX:0,offsetY:0,style:{fontSize:"12px",fontFamily:void 0,fontWeight:600,colors:void 0},background:{enabled:!0,foreColor:"#fff",backgroundColor:void 0,borderRadius:2,padding:4,opacity:.9,borderWidth:1,borderColor:"#fff",dropShadow:{enabled:!1,top:1,left:1,blur:1,color:"#000",opacity:.8}},dropShadow:{enabled:!1,top:1,left:1,blur:1,color:"#000",opacity:.8}},fill:{type:"solid",colors:void 0,opacity:.85,gradient:{shade:"dark",type:"horizontal",shadeIntensity:.5,gradientToColors:void 0,inverseColors:!0,opacityFrom:1,opacityTo:1,stops:[0,50,100],colorStops:[]},image:{src:[],width:void 0,height:void 0},pattern:{style:"squares",width:6,height:6,strokeWidth:2}},forecastDataPoints:{count:0,fillOpacity:.5,strokeWidth:void 0,dashArray:4},grid:{show:!0,borderColor:"#e0e0e0",strokeDashArray:0,position:"back",xaxis:{lines:{show:!1}},yaxis:{lines:{show:!0}},row:{colors:void 0,opacity:.5},column:{colors:void 0,opacity:.5},padding:{top:0,right:10,bottom:0,left:12}},labels:[],legend:{show:!0,showForSingleSeries:!1,showForNullSeries:!0,showForZeroSeries:!0,floating:!1,position:"bottom",horizontalAlign:"center",inverseOrder:!1,fontSize:"12px",fontFamily:void 0,fontWeight:400,width:void 0,height:void 0,formatter:void 0,tooltipHoverFormatter:void 0,offsetX:-20,offsetY:4,customLegendItems:[],clusterGroupedSeries:!0,clusterGroupedSeriesOrientation:"vertical",labels:{colors:void 0,useSeriesColors:!1},markers:{size:7,fillColors:void 0,strokeWidth:1,shape:void 0,offsetX:0,offsetY:0,customHTML:void 0,onClick:void 0},itemMargin:{horizontal:5,vertical:4},onItemClick:{toggleDataSeries:!0},onItemHover:{highlightDataSeries:!0}},markers:{discrete:[],size:0,colors:void 0,strokeColors:"#fff",strokeWidth:2,strokeOpacity:.9,strokeDashArray:0,fillOpacity:1,shape:"circle",offsetX:0,offsetY:0,showNullDataPoints:!0,onClick:void 0,onDblClick:void 0,hover:{size:void 0,sizeOffset:3}},noData:{text:void 0,align:"center",verticalAlign:"middle",offsetX:0,offsetY:0,style:{color:void 0,fontSize:"14px",fontFamily:void 0}},responsive:[],series:void 0,states:{hover:{filter:{type:"lighten"}},active:{allowMultipleDataPointsSelection:!1,filter:{type:"darken"}}},title:{text:void 0,align:"left",margin:5,offsetX:0,offsetY:0,floating:!1,style:{fontSize:"14px",fontWeight:900,fontFamily:void 0,color:void 0}},subtitle:{text:void 0,align:"left",margin:5,offsetX:0,offsetY:30,floating:!1,style:{fontSize:"12px",fontWeight:400,fontFamily:void 0,color:void 0}},stroke:{show:!0,curve:"smooth",lineCap:"butt",width:2,colors:void 0,dashArray:0,fill:{type:"solid",colors:void 0,opacity:.85,gradient:{shade:"dark",type:"horizontal",shadeIntensity:.5,gradientToColors:void 0,inverseColors:!0,opacityFrom:1,opacityTo:1,stops:[0,50,100],colorStops:[]}}},tooltip:{enabled:!0,enabledOnSeries:void 0,shared:!0,hideEmptySeries:!1,followCursor:!1,intersect:!1,inverseOrder:!1,custom:void 0,fillSeriesColor:!1,theme:"light",cssClass:"",style:{fontSize:"12px",fontFamily:void 0},onDatasetHover:{highlightDataSeries:!1},x:{show:!0,format:"dd MMM",formatter:void 0},y:{formatter:void 0,title:{formatter:function(t){return t?t+": ":""}}},z:{formatter:void 0,title:"Size: "},marker:{show:!0,fillColors:void 0},items:{display:"flex"},fixed:{enabled:!1,position:"topRight",offsetX:0,offsetY:0}},xaxis:{type:"category",categories:[],convertedCatToNumeric:!1,offsetX:0,offsetY:0,overwriteCategories:void 0,labels:{show:!0,rotate:-45,rotateAlways:!1,hideOverlappingLabels:!0,trim:!1,minHeight:void 0,maxHeight:120,showDuplicates:!0,style:{colors:[],fontSize:"12px",fontWeight:400,fontFamily:void 0,cssClass:""},offsetX:0,offsetY:0,format:void 0,formatter:void 0,datetimeUTC:!0,datetimeFormatter:{year:"yyyy",month:"MMM 'yy",day:"dd MMM",hour:"HH:mm",minute:"HH:mm:ss",second:"HH:mm:ss"}},group:{groups:[],style:{colors:[],fontSize:"12px",fontWeight:400,fontFamily:void 0,cssClass:""}},axisBorder:{show:!0,color:"#e0e0e0",width:"100%",height:1,offsetX:0,offsetY:0},axisTicks:{show:!0,color:"#e0e0e0",height:6,offsetX:0,offsetY:0},stepSize:void 0,tickAmount:void 0,tickPlacement:"on",min:void 0,max:void 0,range:void 0,floating:!1,decimalsInFloat:void 0,position:"bottom",title:{text:void 0,offsetX:0,offsetY:0,style:{color:void 0,fontSize:"12px",fontWeight:900,fontFamily:void 0,cssClass:""}},crosshairs:{show:!0,width:1,position:"back",opacity:.9,stroke:{color:"#b6b6b6",width:1,dashArray:3},fill:{type:"solid",color:"#B1B9C4",gradient:{colorFrom:"#D8E3F0",colorTo:"#BED1E6",stops:[0,100],opacityFrom:.4,opacityTo:.5}},dropShadow:{enabled:!1,left:0,top:0,blur:1,opacity:.8}},tooltip:{enabled:!0,offsetY:0,formatter:void 0,style:{fontSize:"12px",fontFamily:void 0}}},yaxis:this.yAxis,theme:{mode:"",palette:"palette1",monochrome:{enabled:!1,color:"#008FFB",shadeTo:"light",shadeIntensity:.65}}}}}]),t}(),Fi=function(){function t(e){i(this,t),this.ctx=e,this.w=e.w,this.graphics=new Mi(this.ctx),this.w.globals.isBarHorizontal&&(this.invertAxis=!0),this.helpers=new Ii(this),this.xAxisAnnotations=new Ti(this),this.yAxisAnnotations=new Ei(this),this.pointsAnnotations=new Yi(this),this.w.globals.isBarHorizontal&&this.w.config.yaxis[0].reversed&&(this.inversedReversedAxis=!0),this.xDivision=this.w.globals.gridWidth/this.w.globals.dataPoints}return s(t,[{key:"drawAxesAnnotations",value:function(){var t=this.w;if(t.globals.axisCharts&&t.globals.dataPoints){for(var e=this.yAxisAnnotations.drawYAxisAnnotations(),i=this.xAxisAnnotations.drawXAxisAnnotations(),a=this.pointsAnnotations.drawPointAnnotations(),s=t.config.chart.animations.enabled,r=[e,i,a],n=[i.node,e.node,a.node],o=0;o<3;o++)t.globals.dom.elGraphical.add(r[o]),!s||t.globals.resized||t.globals.dataChanged||"scatter"!==t.config.chart.type&&"bubble"!==t.config.chart.type&&t.globals.dataPoints>1&&n[o].classList.add("apexcharts-element-hidden"),t.globals.delayedElements.push({el:n[o],index:0});this.helpers.annotationsBackground()}}},{key:"drawImageAnnos",value:function(){var t=this;this.w.config.annotations.images.map((function(e,i){t.addImage(e,i)}))}},{key:"drawTextAnnos",value:function(){var t=this;this.w.config.annotations.texts.map((function(e,i){t.addText(e,i)}))}},{key:"addXaxisAnnotation",value:function(t,e,i){this.xAxisAnnotations.addXaxisAnnotation(t,e,i)}},{key:"addYaxisAnnotation",value:function(t,e,i){this.yAxisAnnotations.addYaxisAnnotation(t,e,i)}},{key:"addPointAnnotation",value:function(t,e,i){this.pointsAnnotations.addPointAnnotation(t,e,i)}},{key:"addText",value:function(t,e){var i=t.x,a=t.y,s=t.text,r=t.textAnchor,n=t.foreColor,o=t.fontSize,l=t.fontFamily,h=t.fontWeight,c=t.cssClass,d=t.backgroundColor,u=t.borderWidth,g=t.strokeDashArray,p=t.borderRadius,f=t.borderColor,x=t.appendTo,b=void 0===x?".apexcharts-svg":x,m=t.paddingLeft,v=void 0===m?4:m,y=t.paddingRight,w=void 0===y?4:y,k=t.paddingBottom,A=void 0===k?2:k,C=t.paddingTop,S=void 0===C?2:C,L=this.w,M=this.graphics.drawText({x:i,y:a,text:s,textAnchor:r||"start",fontSize:o||"12px",fontWeight:h||"regular",fontFamily:l||L.config.chart.fontFamily,foreColor:n||L.config.chart.foreColor,cssClass:c}),P=L.globals.dom.baseEl.querySelector(b);P&&P.appendChild(M.node);var I=M.bbox();if(s){var T=this.graphics.drawRect(I.x-v,I.y-S,I.width+v+w,I.height+A+S,p,d||"transparent",1,u,f,g);P.insertBefore(T.node,M.node)}}},{key:"addImage",value:function(t,e){var i=this.w,a=t.path,s=t.x,r=void 0===s?0:s,n=t.y,o=void 0===n?0:n,l=t.width,h=void 0===l?20:l,c=t.height,d=void 0===c?20:c,u=t.appendTo,g=void 0===u?".apexcharts-svg":u,p=i.globals.dom.Paper.image(a);p.size(h,d).move(r,o);var f=i.globals.dom.baseEl.querySelector(g);return f&&f.appendChild(p.node),p}},{key:"addXaxisAnnotationExternal",value:function(t,e,i){return this.addAnnotationExternal({params:t,pushToMemory:e,context:i,type:"xaxis",contextMethod:i.addXaxisAnnotation}),i}},{key:"addYaxisAnnotationExternal",value:function(t,e,i){return this.addAnnotationExternal({params:t,pushToMemory:e,context:i,type:"yaxis",contextMethod:i.addYaxisAnnotation}),i}},{key:"addPointAnnotationExternal",value:function(t,e,i){return void 0===this.invertAxis&&(this.invertAxis=i.w.globals.isBarHorizontal),this.addAnnotationExternal({params:t,pushToMemory:e,context:i,type:"point",contextMethod:i.addPointAnnotation}),i}},{key:"addAnnotationExternal",value:function(t){var e=t.params,i=t.pushToMemory,a=t.context,s=t.type,r=t.contextMethod,n=a,o=n.w,l=o.globals.dom.baseEl.querySelector(".apexcharts-".concat(s,"-annotations")),h=l.childNodes.length+1,c=new Oi,d=Object.assign({},"xaxis"===s?c.xAxisAnnotation:"yaxis"===s?c.yAxisAnnotation:c.pointAnnotation),u=v.extend(d,e);switch(s){case"xaxis":this.addXaxisAnnotation(u,l,h);break;case"yaxis":this.addYaxisAnnotation(u,l,h);break;case"point":this.addPointAnnotation(u,l,h)}var g=o.globals.dom.baseEl.querySelector(".apexcharts-".concat(s,"-annotations .apexcharts-").concat(s,"-annotation-label[rel='").concat(h,"']")),p=this.helpers.addBackgroundToAnno(g,u);return p&&l.insertBefore(p.node,g),i&&o.globals.memory.methodsToExec.push({context:n,id:u.id?u.id:v.randomId(),method:r,label:"addAnnotation",params:e}),a}},{key:"clearAnnotations",value:function(t){for(var e=t.w,i=e.globals.dom.baseEl.querySelectorAll(".apexcharts-yaxis-annotations, .apexcharts-xaxis-annotations, .apexcharts-point-annotations"),a=e.globals.memory.methodsToExec.length-1;a>=0;a--)"addText"!==e.globals.memory.methodsToExec[a].label&&"addAnnotation"!==e.globals.memory.methodsToExec[a].label||e.globals.memory.methodsToExec.splice(a,1);i=v.listToArray(i),Array.prototype.forEach.call(i,(function(t){for(;t.firstChild;)t.removeChild(t.firstChild)}))}},{key:"removeAnnotation",value:function(t,e){var i=t.w,a=i.globals.dom.baseEl.querySelectorAll(".".concat(e));a&&(i.globals.memory.methodsToExec.map((function(t,a){t.id===e&&i.globals.memory.methodsToExec.splice(a,1)})),Object.keys(i.config.annotations).forEach((function(t){var a=i.config.annotations[t];Array.isArray(a)&&(i.config.annotations[t]=a.filter((function(t){return t.id!==e})))})),Array.prototype.forEach.call(a,(function(t){t.parentElement.removeChild(t)})))}}]),t}(),Di=function(t){var e,i=t.isTimeline,a=t.ctx,s=t.seriesIndex,r=t.dataPointIndex,n=t.y1,o=t.y2,l=t.w,h=l.globals.seriesRangeStart[s][r],c=l.globals.seriesRangeEnd[s][r],d=l.globals.labels[r],u=l.config.series[s].name?l.config.series[s].name:"",g=l.globals.ttKeyFormatter,p=l.config.tooltip.y.title.formatter,f={w:l,seriesIndex:s,dataPointIndex:r,start:h,end:c};("function"==typeof p&&(u=p(u,f)),null!==(e=l.config.series[s].data[r])&&void 0!==e&&e.x&&(d=l.config.series[s].data[r].x),i)||"datetime"===l.config.xaxis.type&&(d=new Xi(a).xLabelFormat(l.globals.ttKeyFormatter,d,d,{i:void 0,dateFormatter:new zi(a).formatDate,w:l}));"function"==typeof g&&(d=g(d,f)),Number.isFinite(n)&&Number.isFinite(o)&&(h=n,c=o);var x="",b="",m=l.globals.colors[s];if(void 0===l.config.tooltip.x.formatter)if("datetime"===l.config.xaxis.type){var v=new zi(a);x=v.formatDate(v.getDate(h),l.config.tooltip.x.format),b=v.formatDate(v.getDate(c),l.config.tooltip.x.format)}else x=h,b=c;else x=l.config.tooltip.x.formatter(h),b=l.config.tooltip.x.formatter(c);return{start:h,end:c,startVal:x,endVal:b,ylabel:d,color:m,seriesName:u}},_i=function(t){var e=t.color,i=t.seriesName,a=t.ylabel,s=t.start,r=t.end,n=t.seriesIndex,o=t.dataPointIndex,l=t.ctx.tooltip.tooltipLabels.getFormatters(n);s=l.yLbFormatter(s),r=l.yLbFormatter(r);var h=l.yLbFormatter(t.w.globals.series[n][o]),c='\n '.concat(s,'\n - \n ').concat(r,"\n ");return'
'+(i||"")+'
'+a+": "+(t.w.globals.comboCharts?"rangeArea"===t.w.config.series[n].type||"rangeBar"===t.w.config.series[n].type?c:"".concat(h,""):c)+"
"},Ni=function(){function t(e){i(this,t),this.opts=e}return s(t,[{key:"hideYAxis",value:function(){this.opts.yaxis[0].show=!1,this.opts.yaxis[0].title.text="",this.opts.yaxis[0].axisBorder.show=!1,this.opts.yaxis[0].axisTicks.show=!1,this.opts.yaxis[0].floating=!0}},{key:"line",value:function(){return{dataLabels:{enabled:!1},stroke:{width:5,curve:"straight"},markers:{size:0,hover:{sizeOffset:6}},xaxis:{crosshairs:{width:1}}}}},{key:"sparkline",value:function(t){this.hideYAxis();return v.extend(t,{grid:{show:!1,padding:{left:0,right:0,top:0,bottom:0}},legend:{show:!1},xaxis:{labels:{show:!1},tooltip:{enabled:!1},axisBorder:{show:!1},axisTicks:{show:!1}},chart:{toolbar:{show:!1},zoom:{enabled:!1}},dataLabels:{enabled:!1}})}},{key:"slope",value:function(){return this.hideYAxis(),{chart:{toolbar:{show:!1},zoom:{enabled:!1}},dataLabels:{enabled:!0,formatter:function(t,e){var i=e.w.config.series[e.seriesIndex].name;return null!==t?i+": "+t:""},background:{enabled:!1},offsetX:-5},grid:{xaxis:{lines:{show:!0}},yaxis:{lines:{show:!1}}},xaxis:{position:"top",labels:{style:{fontSize:14,fontWeight:900}},tooltip:{enabled:!1},crosshairs:{show:!1}},markers:{size:8,hover:{sizeOffset:1}},legend:{show:!1},tooltip:{shared:!1,intersect:!0,followCursor:!0},stroke:{width:5,curve:"straight"}}}},{key:"bar",value:function(){return{chart:{stacked:!1},plotOptions:{bar:{dataLabels:{position:"center"}}},dataLabels:{style:{colors:["#fff"]},background:{enabled:!1}},stroke:{width:0,lineCap:"square"},fill:{opacity:.85},legend:{markers:{shape:"square"}},tooltip:{shared:!1,intersect:!0},xaxis:{tooltip:{enabled:!1},tickPlacement:"between",crosshairs:{width:"barWidth",position:"back",fill:{type:"gradient"},dropShadow:{enabled:!1},stroke:{width:0}}}}}},{key:"funnel",value:function(){return this.hideYAxis(),u(u({},this.bar()),{},{chart:{animations:{speed:800,animateGradually:{enabled:!1}}},plotOptions:{bar:{horizontal:!0,borderRadiusApplication:"around",borderRadius:0,dataLabels:{position:"center"}}},grid:{show:!1,padding:{left:0,right:0}},xaxis:{labels:{show:!1},tooltip:{enabled:!1},axisBorder:{show:!1},axisTicks:{show:!1}}})}},{key:"candlestick",value:function(){var t=this;return{stroke:{width:1},fill:{opacity:1},dataLabels:{enabled:!1},tooltip:{shared:!0,custom:function(e){var i=e.seriesIndex,a=e.dataPointIndex,s=e.w;return t._getBoxTooltip(s,i,a,["Open","High","","Low","Close"],"candlestick")}},states:{active:{filter:{type:"none"}}},xaxis:{crosshairs:{width:1}}}}},{key:"boxPlot",value:function(){var t=this;return{chart:{animations:{dynamicAnimation:{enabled:!1}}},stroke:{width:1,colors:["#24292e"]},dataLabels:{enabled:!1},tooltip:{shared:!0,custom:function(e){var i=e.seriesIndex,a=e.dataPointIndex,s=e.w;return t._getBoxTooltip(s,i,a,["Minimum","Q1","Median","Q3","Maximum"],"boxPlot")}},markers:{size:7,strokeWidth:1,strokeColors:"#111"},xaxis:{crosshairs:{width:1}}}}},{key:"rangeBar",value:function(){return{chart:{animations:{animateGradually:!1}},stroke:{width:0,lineCap:"square"},plotOptions:{bar:{borderRadius:0,dataLabels:{position:"center"}}},dataLabels:{enabled:!1,formatter:function(t,e){e.ctx;var i=e.seriesIndex,a=e.dataPointIndex,s=e.w,r=function(){var t=s.globals.seriesRangeStart[i][a];return s.globals.seriesRangeEnd[i][a]-t};return s.globals.comboCharts?"rangeBar"===s.config.series[i].type||"rangeArea"===s.config.series[i].type?r():t:r()},background:{enabled:!1},style:{colors:["#fff"]}},markers:{size:10},tooltip:{shared:!1,followCursor:!0,custom:function(t){return t.w.config.plotOptions&&t.w.config.plotOptions.bar&&t.w.config.plotOptions.bar.horizontal?function(t){var e=Di(u(u({},t),{},{isTimeline:!0})),i=e.color,a=e.seriesName,s=e.ylabel,r=e.startVal,n=e.endVal;return _i(u(u({},t),{},{color:i,seriesName:a,ylabel:s,start:r,end:n}))}(t):function(t){var e=Di(t),i=e.color,a=e.seriesName,s=e.ylabel,r=e.start,n=e.end;return _i(u(u({},t),{},{color:i,seriesName:a,ylabel:s,start:r,end:n}))}(t)}},xaxis:{tickPlacement:"between",tooltip:{enabled:!1},crosshairs:{stroke:{width:0}}}}}},{key:"dumbbell",value:function(t){var e,i;return null!==(e=t.plotOptions.bar)&&void 0!==e&&e.barHeight||(t.plotOptions.bar.barHeight=2),null!==(i=t.plotOptions.bar)&&void 0!==i&&i.columnWidth||(t.plotOptions.bar.columnWidth=2),t}},{key:"area",value:function(){return{stroke:{width:4,fill:{type:"solid",gradient:{inverseColors:!1,shade:"light",type:"vertical",opacityFrom:.65,opacityTo:.5,stops:[0,100,100]}}},fill:{type:"gradient",gradient:{inverseColors:!1,shade:"light",type:"vertical",opacityFrom:.65,opacityTo:.5,stops:[0,100,100]}},markers:{size:0,hover:{sizeOffset:6}},tooltip:{followCursor:!1}}}},{key:"rangeArea",value:function(){return{stroke:{curve:"straight",width:0},fill:{type:"solid",opacity:.6},markers:{size:0},states:{hover:{filter:{type:"none"}},active:{filter:{type:"none"}}},tooltip:{intersect:!1,shared:!0,followCursor:!0,custom:function(t){return function(t){var e=Di(t),i=e.color,a=e.seriesName,s=e.ylabel,r=e.start,n=e.end;return _i(u(u({},t),{},{color:i,seriesName:a,ylabel:s,start:r,end:n}))}(t)}}}}},{key:"brush",value:function(t){return v.extend(t,{chart:{toolbar:{autoSelected:"selection",show:!1},zoom:{enabled:!1}},dataLabels:{enabled:!1},stroke:{width:1},tooltip:{enabled:!1},xaxis:{tooltip:{enabled:!1}}})}},{key:"stacked100",value:function(t){t.dataLabels=t.dataLabels||{},t.dataLabels.formatter=t.dataLabels.formatter||void 0;var e=t.dataLabels.formatter;return t.yaxis.forEach((function(e,i){t.yaxis[i].min=0,t.yaxis[i].max=100})),"bar"===t.chart.type&&(t.dataLabels.formatter=e||function(t){return"number"==typeof t&&t?t.toFixed(0)+"%":t}),t}},{key:"stackedBars",value:function(){var t=this.bar();return u(u({},t),{},{plotOptions:u(u({},t.plotOptions),{},{bar:u(u({},t.plotOptions.bar),{},{borderRadiusApplication:"end",borderRadiusWhenStacked:"last"})})})}},{key:"convertCatToNumeric",value:function(t){return t.xaxis.convertedCatToNumeric=!0,t}},{key:"convertCatToNumericXaxis",value:function(t,e,i){t.xaxis.type="numeric",t.xaxis.labels=t.xaxis.labels||{},t.xaxis.labels.formatter=t.xaxis.labels.formatter||function(t){return v.isNumber(t)?Math.floor(t):t};var a=t.xaxis.labels.formatter,s=t.xaxis.categories&&t.xaxis.categories.length?t.xaxis.categories:t.labels;return i&&i.length&&(s=i.map((function(t){return Array.isArray(t)?t:String(t)}))),s&&s.length&&(t.xaxis.labels.formatter=function(t){return v.isNumber(t)?a(s[Math.floor(t)-1]):a(t)}),t.xaxis.categories=[],t.labels=[],t.xaxis.tickAmount=t.xaxis.tickAmount||"dataPoints",t}},{key:"bubble",value:function(){return{dataLabels:{style:{colors:["#fff"]}},tooltip:{shared:!1,intersect:!0},xaxis:{crosshairs:{width:0}},fill:{type:"solid",gradient:{shade:"light",inverse:!0,shadeIntensity:.55,opacityFrom:.4,opacityTo:.8}}}}},{key:"scatter",value:function(){return{dataLabels:{enabled:!1},tooltip:{shared:!1,intersect:!0},markers:{size:6,strokeWidth:1,hover:{sizeOffset:2}}}}},{key:"heatmap",value:function(){return{chart:{stacked:!1},fill:{opacity:1},dataLabels:{style:{colors:["#fff"]}},stroke:{colors:["#fff"]},tooltip:{followCursor:!0,marker:{show:!1},x:{show:!1}},legend:{position:"top",markers:{shape:"square"}},grid:{padding:{right:20}}}}},{key:"treemap",value:function(){return{chart:{zoom:{enabled:!1}},dataLabels:{style:{fontSize:14,fontWeight:600,colors:["#fff"]}},stroke:{show:!0,width:2,colors:["#fff"]},legend:{show:!1},fill:{opacity:1,gradient:{stops:[0,100]}},tooltip:{followCursor:!0,x:{show:!1}},grid:{padding:{left:0,right:0}},xaxis:{crosshairs:{show:!1},tooltip:{enabled:!1}}}}},{key:"pie",value:function(){return{chart:{toolbar:{show:!1}},plotOptions:{pie:{donut:{labels:{show:!1}}}},dataLabels:{formatter:function(t){return t.toFixed(1)+"%"},style:{colors:["#fff"]},background:{enabled:!1},dropShadow:{enabled:!0}},stroke:{colors:["#fff"]},fill:{opacity:1,gradient:{shade:"light",stops:[0,100]}},tooltip:{theme:"dark",fillSeriesColor:!0},legend:{position:"right"},grid:{padding:{left:0,right:0,top:0,bottom:0}}}}},{key:"donut",value:function(){return{chart:{toolbar:{show:!1}},dataLabels:{formatter:function(t){return t.toFixed(1)+"%"},style:{colors:["#fff"]},background:{enabled:!1},dropShadow:{enabled:!0}},stroke:{colors:["#fff"]},fill:{opacity:1,gradient:{shade:"light",shadeIntensity:.35,stops:[80,100],opacityFrom:1,opacityTo:1}},tooltip:{theme:"dark",fillSeriesColor:!0},legend:{position:"right"},grid:{padding:{left:0,right:0,top:0,bottom:0}}}}},{key:"polarArea",value:function(){return{chart:{toolbar:{show:!1}},dataLabels:{formatter:function(t){return t.toFixed(1)+"%"},enabled:!1},stroke:{show:!0,width:2},fill:{opacity:.7},tooltip:{theme:"dark",fillSeriesColor:!0},legend:{position:"right"},grid:{padding:{left:0,right:0,top:0,bottom:0}}}}},{key:"radar",value:function(){return this.opts.yaxis[0].labels.offsetY=this.opts.yaxis[0].labels.offsetY?this.opts.yaxis[0].labels.offsetY:6,{dataLabels:{enabled:!1,style:{fontSize:"11px"}},stroke:{width:2},markers:{size:5,strokeWidth:1,strokeOpacity:1},fill:{opacity:.2},tooltip:{shared:!1,intersect:!0,followCursor:!0},grid:{show:!1,padding:{left:0,right:0,top:0,bottom:0}},xaxis:{labels:{formatter:function(t){return t},style:{colors:["#a8a8a8"],fontSize:"11px"}},tooltip:{enabled:!1},crosshairs:{show:!1}}}}},{key:"radialBar",value:function(){return{chart:{animations:{dynamicAnimation:{enabled:!0,speed:800}},toolbar:{show:!1}},fill:{gradient:{shade:"dark",shadeIntensity:.4,inverseColors:!1,type:"diagonal2",opacityFrom:1,opacityTo:1,stops:[70,98,100]}},legend:{show:!1,position:"right"},tooltip:{enabled:!1,fillSeriesColor:!0},grid:{padding:{left:0,right:0,top:0,bottom:0}}}}},{key:"_getBoxTooltip",value:function(t,e,i,a,s){var r=t.globals.seriesCandleO[e][i],n=t.globals.seriesCandleH[e][i],o=t.globals.seriesCandleM[e][i],l=t.globals.seriesCandleL[e][i],h=t.globals.seriesCandleC[e][i];return t.config.series[e].type&&t.config.series[e].type!==s?'
\n '.concat(t.config.series[e].name?t.config.series[e].name:"series-"+(e+1),": ").concat(t.globals.series[e][i],"\n
"):'
')+"
".concat(a[0],': ')+r+"
"+"
".concat(a[1],': ')+n+"
"+(o?"
".concat(a[2],': ')+o+"
":"")+"
".concat(a[3],': ')+l+"
"+"
".concat(a[4],': ')+h+"
"}}]),t}(),Wi=function(){function t(e){i(this,t),this.opts=e}return s(t,[{key:"init",value:function(t){var e=t.responsiveOverride,i=this.opts,a=new Oi,s=new Ni(i);this.chartType=i.chart.type,i=this.extendYAxis(i),i=this.extendAnnotations(i);var r=a.init(),n={};if(i&&"object"===b(i)){var o,l,h,c,d,u,g,p,f,x,m={};m=-1!==["line","area","bar","candlestick","boxPlot","rangeBar","rangeArea","bubble","scatter","heatmap","treemap","pie","polarArea","donut","radar","radialBar"].indexOf(i.chart.type)?s[i.chart.type]():s.line(),null!==(o=i.plotOptions)&&void 0!==o&&null!==(l=o.bar)&&void 0!==l&&l.isFunnel&&(m=s.funnel()),i.chart.stacked&&"bar"===i.chart.type&&(m=s.stackedBars()),null!==(h=i.chart.brush)&&void 0!==h&&h.enabled&&(m=s.brush(m)),null!==(c=i.plotOptions)&&void 0!==c&&null!==(d=c.line)&&void 0!==d&&d.isSlopeChart&&(m=s.slope()),i.chart.stacked&&"100%"===i.chart.stackType&&(i=s.stacked100(i)),null!==(u=i.plotOptions)&&void 0!==u&&null!==(g=u.bar)&&void 0!==g&&g.isDumbbell&&(i=s.dumbbell(i)),this.checkForDarkTheme(window.Apex),this.checkForDarkTheme(i),i.xaxis=i.xaxis||window.Apex.xaxis||{},e||(i.xaxis.convertedCatToNumeric=!1),(null!==(p=(i=this.checkForCatToNumericXAxis(this.chartType,m,i)).chart.sparkline)&&void 0!==p&&p.enabled||null!==(f=window.Apex.chart)&&void 0!==f&&null!==(x=f.sparkline)&&void 0!==x&&x.enabled)&&(m=s.sparkline(m)),n=v.extend(r,m)}var y=v.extend(n,window.Apex);return r=v.extend(y,i),r=this.handleUserInputErrors(r)}},{key:"checkForCatToNumericXAxis",value:function(t,e,i){var a,s,r=new Ni(i),n=("bar"===t||"boxPlot"===t)&&(null===(a=i.plotOptions)||void 0===a||null===(s=a.bar)||void 0===s?void 0:s.horizontal),o="pie"===t||"polarArea"===t||"donut"===t||"radar"===t||"radialBar"===t||"heatmap"===t,l="datetime"!==i.xaxis.type&&"numeric"!==i.xaxis.type,h=i.xaxis.tickPlacement?i.xaxis.tickPlacement:e.xaxis&&e.xaxis.tickPlacement;return n||o||!l||"between"===h||(i=r.convertCatToNumeric(i)),i}},{key:"extendYAxis",value:function(t,e){var i=new Oi;(void 0===t.yaxis||!t.yaxis||Array.isArray(t.yaxis)&&0===t.yaxis.length)&&(t.yaxis={}),t.yaxis.constructor!==Array&&window.Apex.yaxis&&window.Apex.yaxis.constructor!==Array&&(t.yaxis=v.extend(t.yaxis,window.Apex.yaxis)),t.yaxis.constructor!==Array?t.yaxis=[v.extend(i.yAxis,t.yaxis)]:t.yaxis=v.extendArray(t.yaxis,i.yAxis);var a=!1;t.yaxis.forEach((function(t){t.logarithmic&&(a=!0)}));var s=t.series;return e&&!s&&(s=e.config.series),a&&s.length!==t.yaxis.length&&s.length&&(t.yaxis=s.map((function(e,a){if(e.name||(s[a].name="series-".concat(a+1)),t.yaxis[a])return t.yaxis[a].seriesName=s[a].name,t.yaxis[a];var r=v.extend(i.yAxis,t.yaxis[0]);return r.show=!1,r}))),a&&s.length>1&&s.length!==t.yaxis.length&&console.warn("A multi-series logarithmic chart should have equal number of series and y-axes"),t}},{key:"extendAnnotations",value:function(t){return void 0===t.annotations&&(t.annotations={},t.annotations.yaxis=[],t.annotations.xaxis=[],t.annotations.points=[]),t=this.extendYAxisAnnotations(t),t=this.extendXAxisAnnotations(t),t=this.extendPointAnnotations(t)}},{key:"extendYAxisAnnotations",value:function(t){var e=new Oi;return t.annotations.yaxis=v.extendArray(void 0!==t.annotations.yaxis?t.annotations.yaxis:[],e.yAxisAnnotation),t}},{key:"extendXAxisAnnotations",value:function(t){var e=new Oi;return t.annotations.xaxis=v.extendArray(void 0!==t.annotations.xaxis?t.annotations.xaxis:[],e.xAxisAnnotation),t}},{key:"extendPointAnnotations",value:function(t){var e=new Oi;return t.annotations.points=v.extendArray(void 0!==t.annotations.points?t.annotations.points:[],e.pointAnnotation),t}},{key:"checkForDarkTheme",value:function(t){t.theme&&"dark"===t.theme.mode&&(t.tooltip||(t.tooltip={}),"light"!==t.tooltip.theme&&(t.tooltip.theme="dark"),t.chart.foreColor||(t.chart.foreColor="#f6f7f8"),t.theme.palette||(t.theme.palette="palette4"))}},{key:"handleUserInputErrors",value:function(t){var e=t;if(e.tooltip.shared&&e.tooltip.intersect)throw new Error("tooltip.shared cannot be enabled when tooltip.intersect is true. Turn off any other option by setting it to false.");if("bar"===e.chart.type&&e.plotOptions.bar.horizontal){if(e.yaxis.length>1)throw new Error("Multiple Y Axis for bars are not supported. Switch to column chart by setting plotOptions.bar.horizontal=false");e.yaxis[0].reversed&&(e.yaxis[0].opposite=!0),e.xaxis.tooltip.enabled=!1,e.yaxis[0].tooltip.enabled=!1,e.chart.zoom.enabled=!1}return"bar"!==e.chart.type&&"rangeBar"!==e.chart.type||e.tooltip.shared&&"barWidth"===e.xaxis.crosshairs.width&&e.series.length>1&&(e.xaxis.crosshairs.width="tickWidth"),"candlestick"!==e.chart.type&&"boxPlot"!==e.chart.type||e.yaxis[0].reversed&&(console.warn("Reversed y-axis in ".concat(e.chart.type," chart is not supported.")),e.yaxis[0].reversed=!1),e}}]),t}(),Bi=function(){function t(){i(this,t)}return s(t,[{key:"initGlobalVars",value:function(t){t.series=[],t.seriesCandleO=[],t.seriesCandleH=[],t.seriesCandleM=[],t.seriesCandleL=[],t.seriesCandleC=[],t.seriesRangeStart=[],t.seriesRangeEnd=[],t.seriesRange=[],t.seriesPercent=[],t.seriesGoals=[],t.seriesX=[],t.seriesZ=[],t.seriesNames=[],t.seriesTotals=[],t.seriesLog=[],t.seriesColors=[],t.stackedSeriesTotals=[],t.seriesXvalues=[],t.seriesYvalues=[],t.dataWasParsed=!1,t.originalSeries=null,t.labels=[],t.hasXaxisGroups=!1,t.groups=[],t.barGroups=[],t.lineGroups=[],t.areaGroups=[],t.hasSeriesGroups=!1,t.seriesGroups=[],t.categoryLabels=[],t.timescaleLabels=[],t.noLabelsProvided=!1,t.resizeTimer=null,t.selectionResizeTimer=null,t.lastWheelExecution=0,t.delayedElements=[],t.pointsArray=[],t.dataLabelsRects=[],t.isXNumeric=!1,t.skipLastTimelinelabel=!1,t.skipFirstTimelinelabel=!1,t.isDataXYZ=!1,t.isMultiLineX=!1,t.isMultipleYAxis=!1,t.maxY=-Number.MAX_VALUE,t.minY=Number.MIN_VALUE,t.minYArr=[],t.maxYArr=[],t.maxX=-Number.MAX_VALUE,t.minX=Number.MAX_VALUE,t.initialMaxX=-Number.MAX_VALUE,t.initialMinX=Number.MAX_VALUE,t.maxDate=0,t.minDate=Number.MAX_VALUE,t.minZ=Number.MAX_VALUE,t.maxZ=-Number.MAX_VALUE,t.minXDiff=Number.MAX_VALUE,t.yAxisScale=[],t.xAxisScale=null,t.xAxisTicksPositions=[],t.yLabelsCoords=[],t.yTitleCoords=[],t.barPadForNumericAxis=0,t.padHorizontal=0,t.xRange=0,t.yRange=[],t.zRange=0,t.dataPoints=0,t.xTickAmount=0,t.multiAxisTickAmount=0}},{key:"globalVars",value:function(t){return{chartID:null,cuid:null,events:{beforeMount:[],mounted:[],updated:[],clicked:[],selection:[],dataPointSelection:[],zoomed:[],scrolled:[]},colors:[],clientX:null,clientY:null,fill:{colors:[]},stroke:{colors:[]},dataLabels:{style:{colors:[]}},radarPolygons:{fill:{colors:[]}},markers:{colors:[],size:t.markers.size,largestSize:0},animationEnded:!1,isTouchDevice:"ontouchstart"in window||navigator.msMaxTouchPoints,isDirty:!1,isExecCalled:!1,initialConfig:null,initialSeries:[],lastXAxis:[],lastYAxis:[],columnSeries:null,labels:[],timescaleLabels:[],noLabelsProvided:!1,allSeriesCollapsed:!1,collapsedSeries:[],collapsedSeriesIndices:[],ancillaryCollapsedSeries:[],ancillaryCollapsedSeriesIndices:[],risingSeries:[],dataFormatXNumeric:!1,capturedSeriesIndex:-1,capturedDataPointIndex:-1,selectedDataPoints:[],invalidLogScale:!1,ignoreYAxisIndexes:[],maxValsInArrayIndex:0,radialSize:0,selection:void 0,zoomEnabled:"zoom"===t.chart.toolbar.autoSelected&&t.chart.toolbar.tools.zoom&&t.chart.zoom.enabled,panEnabled:"pan"===t.chart.toolbar.autoSelected&&t.chart.toolbar.tools.pan,selectionEnabled:"selection"===t.chart.toolbar.autoSelected&&t.chart.toolbar.tools.selection,yaxis:null,mousedown:!1,lastClientPosition:{},visibleXRange:void 0,yValueDecimal:0,total:0,SVGNS:"http://www.w3.org/2000/svg",svgWidth:0,svgHeight:0,noData:!1,locale:{},dom:{},memory:{methodsToExec:[]},shouldAnimate:!0,skipLastTimelinelabel:!1,skipFirstTimelinelabel:!1,delayedElements:[],axisCharts:!0,isDataXYZ:!1,isSlopeChart:t.plotOptions.line.isSlopeChart,resized:!1,resizeTimer:null,comboCharts:!1,dataChanged:!1,previousPaths:[],allSeriesHasEqualX:!0,pointsArray:[],dataLabelsRects:[],lastDrawnDataLabelsIndexes:[],hasNullValues:!1,zoomed:!1,gridWidth:0,gridHeight:0,rotateXLabels:!1,defaultLabels:!1,xLabelFormatter:void 0,yLabelFormatters:[],xaxisTooltipFormatter:void 0,ttKeyFormatter:void 0,ttVal:void 0,ttZFormatter:void 0,LINE_HEIGHT_RATIO:1.618,xAxisLabelsHeight:0,xAxisGroupLabelsHeight:0,xAxisLabelsWidth:0,yAxisLabelsWidth:0,scaleX:1,scaleY:1,translateX:0,translateY:0,translateYAxisX:[],yAxisWidths:[],translateXAxisY:0,translateXAxisX:0,tooltip:null,niceScaleAllowedMagMsd:[[1,1,2,5,5,5,10,10,10,10,10],[1,1,2,5,5,5,10,10,10,10,10]],niceScaleDefaultTicks:[1,2,4,4,6,6,6,6,6,6,6,6,6,6,6,6,6,6,12,12,12,12,12,12,12,12,12,24],seriesYAxisMap:[],seriesYAxisReverseMap:[]}}},{key:"init",value:function(t){var e=this.globalVars(t);return this.initGlobalVars(e),e.initialConfig=v.extend({},t),e.initialSeries=v.clone(t.series),e.lastXAxis=v.clone(e.initialConfig.xaxis),e.lastYAxis=v.clone(e.initialConfig.yaxis),e}}]),t}(),Gi=function(){function t(e){i(this,t),this.opts=e}return s(t,[{key:"init",value:function(){var t=new Wi(this.opts).init({responsiveOverride:!1});return{config:t,globals:(new Bi).init(t)}}}]),t}(),ji=function(){function t(e){i(this,t),this.ctx=e,this.w=e.w,this.opts=null,this.seriesIndex=0,this.patternIDs=[]}return s(t,[{key:"clippedImgArea",value:function(t){var e=this.w,i=e.config,a=parseInt(e.globals.gridWidth,10),s=parseInt(e.globals.gridHeight,10),r=a>s?a:s,n=t.image,o=0,l=0;void 0===t.width&&void 0===t.height?void 0!==i.fill.image.width&&void 0!==i.fill.image.height?(o=i.fill.image.width+1,l=i.fill.image.height):(o=r+1,l=r):(o=t.width,l=t.height);var h=document.createElementNS(e.globals.SVGNS,"pattern");Mi.setAttrs(h,{id:t.patternID,patternUnits:t.patternUnits?t.patternUnits:"userSpaceOnUse",width:o+"px",height:l+"px"});var c=document.createElementNS(e.globals.SVGNS,"image");h.appendChild(c),c.setAttributeNS(window.SVG.xlink,"href",n),Mi.setAttrs(c,{x:0,y:0,preserveAspectRatio:"none",width:o+"px",height:l+"px"}),c.style.opacity=t.opacity,e.globals.dom.elDefs.node.appendChild(h)}},{key:"getSeriesIndex",value:function(t){var e=this.w,i=e.config.chart.type;return("bar"===i||"rangeBar"===i)&&e.config.plotOptions.bar.distributed||"heatmap"===i||"treemap"===i?this.seriesIndex=t.seriesNumber:this.seriesIndex=t.seriesNumber%e.globals.series.length,this.seriesIndex}},{key:"computeColorStops",value:function(t,e){var i,a=this.w,s=null,n=null,o=r(t);try{for(o.s();!(i=o.n()).done;){var l=i.value;l>=e.threshold?(null===s||l>s)&&(s=l):(null===n||l-1?x=v.getOpacityFromRGBA(c):m=v.hexToRgba(v.rgb2hex(c),x),t.opacity&&(x=t.opacity),"pattern"===p&&(n=this.handlePatternFill({fillConfig:t.fillConfig,patternFill:n,fillColor:c,fillOpacity:x,defaultColor:m})),b){var y=f(l.fill.gradient.colorStops)||[],w=l.fill.gradient.type;h&&(y[this.seriesIndex]=this.computeColorStops(s.globals.series[this.seriesIndex],l.plotOptions.line.colors),w="vertical"),o=this.handleGradientFill({type:w,fillConfig:t.fillConfig,fillColor:c,fillOpacity:x,colorStops:y,i:this.seriesIndex})}if("image"===p){var k=l.fill.image.src,A=t.patternID?t.patternID:"",C="pattern".concat(s.globals.cuid).concat(t.seriesNumber+1).concat(A);-1===this.patternIDs.indexOf(C)&&(this.clippedImgArea({opacity:x,image:Array.isArray(k)?t.seriesNumber-1&&(p=v.getOpacityFromRGBA(g));var f=void 0===o.gradient.opacityTo?a:Array.isArray(o.gradient.opacityTo)?o.gradient.opacityTo[n]:o.gradient.opacityTo;if(void 0===o.gradient.gradientToColors||0===o.gradient.gradientToColors.length)d="dark"===o.gradient.shade?c.shadeColor(-1*parseFloat(o.gradient.shadeIntensity),i.indexOf("rgb")>-1?v.rgb2hex(i):i):c.shadeColor(parseFloat(o.gradient.shadeIntensity),i.indexOf("rgb")>-1?v.rgb2hex(i):i);else if(o.gradient.gradientToColors[l.seriesNumber]){var x=o.gradient.gradientToColors[l.seriesNumber];d=x,x.indexOf("rgba")>-1&&(f=v.getOpacityFromRGBA(x))}else d=i;if(o.gradient.gradientFrom&&(g=o.gradient.gradientFrom),o.gradient.gradientTo&&(d=o.gradient.gradientTo),o.gradient.inverseColors){var b=g;g=d,d=b}return g.indexOf("rgb")>-1&&(g=v.rgb2hex(g)),d.indexOf("rgb")>-1&&(d=v.rgb2hex(d)),h.drawGradient(e,g,d,p,f,l.size,o.gradient.stops,r,n)}}]),t}(),Vi=function(){function t(e,a){i(this,t),this.ctx=e,this.w=e.w}return s(t,[{key:"setGlobalMarkerSize",value:function(){var t=this.w;if(t.globals.markers.size=Array.isArray(t.config.markers.size)?t.config.markers.size:[t.config.markers.size],t.globals.markers.size.length>0){if(t.globals.markers.size.length0:h.config.markers.size>0)||n||p){m||(y+=" w".concat(v.randomId()));var w=this.getMarkerConfig({cssClass:y,seriesIndex:i,dataPointIndex:b});if(h.config.series[c].data[b]&&(h.config.series[c].data[b].fillColor&&(w.pointFillColor=h.config.series[c].data[b].fillColor),h.config.series[c].data[b].strokeColor&&(w.pointStrokeColor=h.config.series[c].data[b].strokeColor)),void 0!==s&&(w.pSize=s),(d.x[f]<-h.globals.markers.largestSize||d.x[f]>h.globals.gridWidth+h.globals.markers.largestSize||d.y[f]<-h.globals.markers.largestSize||d.y[f]>h.globals.gridHeight+h.globals.markers.largestSize)&&(w.pSize=0),!m)(h.globals.markers.size[i]>0||n||p)&&!u&&(u=g.group({class:n||p?"":"apexcharts-series-markers"})).attr("clip-path","url(#gridRectMarkerMask".concat(h.globals.cuid,")")),(x=g.drawMarker(d.x[f],d.y[f],w)).attr("rel",b),x.attr("j",b),x.attr("index",i),x.node.setAttribute("default-marker-size",w.pSize),new Li(this.ctx).setSelectionFilter(x,i,b),this.addEvents(x),u&&u.add(x)}else void 0===h.globals.pointsArray[i]&&(h.globals.pointsArray[i]=[]),h.globals.pointsArray[i].push([d.x[f],d.y[f]])}return u}},{key:"getMarkerConfig",value:function(t){var e=t.cssClass,i=t.seriesIndex,a=t.dataPointIndex,s=void 0===a?null:a,r=t.radius,n=void 0===r?null:r,o=t.size,l=void 0===o?null:o,h=t.strokeWidth,c=void 0===h?null:h,d=this.w,u=this.getMarkerStyle(i),g=null===l?d.globals.markers.size[i]:l,p=d.config.markers;return null!==s&&p.discrete.length&&p.discrete.map((function(t){t.seriesIndex===i&&t.dataPointIndex===s&&(u.pointStrokeColor=t.strokeColor,u.pointFillColor=t.fillColor,g=t.size,u.pointShape=t.shape)})),{pSize:null===n?g:n,pRadius:null!==n?n:p.radius,pointStrokeWidth:null!==c?c:Array.isArray(p.strokeWidth)?p.strokeWidth[i]:p.strokeWidth,pointStrokeColor:u.pointStrokeColor,pointFillColor:u.pointFillColor,shape:u.pointShape||(Array.isArray(p.shape)?p.shape[i]:p.shape),class:e,pointStrokeOpacity:Array.isArray(p.strokeOpacity)?p.strokeOpacity[i]:p.strokeOpacity,pointStrokeDashArray:Array.isArray(p.strokeDashArray)?p.strokeDashArray[i]:p.strokeDashArray,pointFillOpacity:Array.isArray(p.fillOpacity)?p.fillOpacity[i]:p.fillOpacity,seriesIndex:i}}},{key:"addEvents",value:function(t){var e=this.w,i=new Mi(this.ctx);t.node.addEventListener("mouseenter",i.pathMouseEnter.bind(this.ctx,t)),t.node.addEventListener("mouseleave",i.pathMouseLeave.bind(this.ctx,t)),t.node.addEventListener("mousedown",i.pathMouseDown.bind(this.ctx,t)),t.node.addEventListener("click",e.config.markers.onClick),t.node.addEventListener("dblclick",e.config.markers.onDblClick),t.node.addEventListener("touchstart",i.pathMouseDown.bind(this.ctx,t),{passive:!0})}},{key:"getMarkerStyle",value:function(t){var e=this.w,i=e.globals.markers.colors,a=e.config.markers.strokeColor||e.config.markers.strokeColors;return{pointStrokeColor:Array.isArray(a)?a[t]:a,pointFillColor:Array.isArray(i)?i[t]:i}}}]),t}(),Ui=function(){function t(e){i(this,t),this.ctx=e,this.w=e.w,this.initialAnim=this.w.config.chart.animations.enabled}return s(t,[{key:"draw",value:function(t,e,i){var a=this.w,s=new Mi(this.ctx),r=i.realIndex,n=i.pointsPos,o=i.zRatio,l=i.elParent,h=s.group({class:"apexcharts-series-markers apexcharts-series-".concat(a.config.chart.type)});if(h.attr("clip-path","url(#gridRectMarkerMask".concat(a.globals.cuid,")")),Array.isArray(n.x))for(var c=0;cp.maxBubbleRadius&&(g=p.maxBubbleRadius)}var f=n.x[c],x=n.y[c];if(g=g||0,null!==x&&void 0!==a.globals.series[r][d]||(u=!1),u){var b=this.drawPoint(f,x,g,r,d,e);h.add(b)}l.add(h)}}},{key:"drawPoint",value:function(t,e,i,a,s,r){var n=this.w,o=a,l=new y(this.ctx),h=new Li(this.ctx),c=new ji(this.ctx),d=new Vi(this.ctx),u=new Mi(this.ctx),g=d.getMarkerConfig({cssClass:"apexcharts-marker",seriesIndex:o,dataPointIndex:s,radius:"bubble"===n.config.chart.type||n.globals.comboCharts&&n.config.series[a]&&"bubble"===n.config.series[a].type?i:null}),p=c.fillPath({seriesNumber:a,dataPointIndex:s,color:g.pointFillColor,patternUnits:"objectBoundingBox",value:n.globals.series[a][r]}),f=u.drawMarker(t,e,g);if(n.config.series[o].data[s]&&n.config.series[o].data[s].fillColor&&(p=n.config.series[o].data[s].fillColor),f.attr({fill:p}),n.config.chart.dropShadow.enabled){var x=n.config.chart.dropShadow;h.dropShadow(f,x,a)}if(!this.initialAnim||n.globals.dataChanged||n.globals.resized)n.globals.animationEnded=!0;else{var b=n.config.chart.animations.speed;l.animateMarker(f,b,n.globals.easing,(function(){window.setTimeout((function(){l.animationCompleted(f)}),100)}))}return f.attr({rel:s,j:s,index:a,"default-marker-size":g.pSize}),h.setSelectionFilter(f,a,s),d.addEvents(f),f.node.classList.add("apexcharts-marker"),f}},{key:"centerTextInBubble",value:function(t){var e=this.w;return{y:t+=parseInt(e.config.dataLabels.style.fontSize,10)/4}}}]),t}(),qi=function(){function t(e){i(this,t),this.ctx=e,this.w=e.w}return s(t,[{key:"dataLabelsCorrection",value:function(t,e,i,a,s,r,n){var o=this.w,l=!1,h=new Mi(this.ctx).getTextRects(i,n),c=h.width,d=h.height;e<0&&(e=0),e>o.globals.gridHeight+d&&(e=o.globals.gridHeight+d/2),void 0===o.globals.dataLabelsRects[a]&&(o.globals.dataLabelsRects[a]=[]),o.globals.dataLabelsRects[a].push({x:t,y:e,width:c,height:d});var u=o.globals.dataLabelsRects[a].length-2,g=void 0!==o.globals.lastDrawnDataLabelsIndexes[a]?o.globals.lastDrawnDataLabelsIndexes[a][o.globals.lastDrawnDataLabelsIndexes[a].length-1]:0;if(void 0!==o.globals.dataLabelsRects[a][u]){var p=o.globals.dataLabelsRects[a][g];(t>p.x+p.width||e>p.y+p.height||e+de.globals.gridWidth+b.textRects.width+30)&&(o="");var m=e.globals.dataLabels.style.colors[r];(("bar"===e.config.chart.type||"rangeBar"===e.config.chart.type)&&e.config.plotOptions.bar.distributed||e.config.dataLabels.distributed)&&(m=e.globals.dataLabels.style.colors[n]),"function"==typeof m&&(m=m({series:e.globals.series,seriesIndex:r,dataPointIndex:n,w:e})),u&&(m=u);var v=d.offsetX,y=d.offsetY;if("bar"!==e.config.chart.type&&"rangeBar"!==e.config.chart.type||(v=0,y=0),e.globals.isSlopeChart&&(0!==n&&(v=-2*d.offsetX+5),0!==n&&n!==e.config.series[r].data.length-1&&(v=0)),b.drawnextLabel){if("middle"===l&&a===e.globals.gridWidth&&(l="end"),(x=i.drawText({width:100,height:parseInt(d.style.fontSize,10),x:a+v,y:s+y,foreColor:m,textAnchor:l||d.textAnchor,text:o,fontSize:h||d.style.fontSize,fontFamily:d.style.fontFamily,fontWeight:d.style.fontWeight||"normal"})).attr({class:f||"apexcharts-datalabel",cx:a,cy:s}),d.dropShadow.enabled){var w=d.dropShadow;new Li(this.ctx).dropShadow(x,w)}c.add(x),void 0===e.globals.lastDrawnDataLabelsIndexes[r]&&(e.globals.lastDrawnDataLabelsIndexes[r]=[]),e.globals.lastDrawnDataLabelsIndexes[r].push(n)}return x}},{key:"addBackgroundToDataLabel",value:function(t,e){var i=this.w,a=i.config.dataLabels.background,s=a.padding,r=a.padding/2,n=e.width,o=e.height,l=new Mi(this.ctx).drawRect(e.x-s,e.y-r/2,n+2*s,o+r,a.borderRadius,"transparent"!==i.config.chart.background&&i.config.chart.background?i.config.chart.background:"#fff",a.opacity,a.borderWidth,a.borderColor);a.dropShadow.enabled&&new Li(this.ctx).dropShadow(l,a.dropShadow);return l}},{key:"dataLabelsBackground",value:function(){var t=this.w;if("bubble"!==t.config.chart.type)for(var e=t.globals.dom.baseEl.querySelectorAll(".apexcharts-datalabels text"),i=0;i0&&void 0!==arguments[0])||arguments[0],e=!(arguments.length>1&&void 0!==arguments[1])||arguments[1],i=!(arguments.length>2&&void 0!==arguments[2])||arguments[2],a=this.w,s=v.clone(a.globals.initialSeries);a.globals.previousPaths=[],i?(a.globals.collapsedSeries=[],a.globals.ancillaryCollapsedSeries=[],a.globals.collapsedSeriesIndices=[],a.globals.ancillaryCollapsedSeriesIndices=[]):s=this.emptyCollapsedSeries(s),a.config.series=s,t&&(e&&(a.globals.zoomed=!1,this.ctx.updateHelpers.revertDefaultAxisMinMax()),this.ctx.updateHelpers._updateSeries(s,a.config.chart.animations.dynamicAnimation.enabled))}},{key:"emptyCollapsedSeries",value:function(t){for(var e=this.w,i=0;i-1&&(t[i].data=[]);return t}},{key:"highlightSeries",value:function(t){var e=this.w,i=this.getSeriesByName(t),a=parseInt(null==i?void 0:i.getAttribute("data:realIndex"),10),s=e.globals.dom.baseEl.querySelectorAll(".apexcharts-series, .apexcharts-datalabels, .apexcharts-yaxis"),r=null,n=null,o=null;if(e.globals.axisCharts||"radialBar"===e.config.chart.type)if(e.globals.axisCharts){r=e.globals.dom.baseEl.querySelector(".apexcharts-series[data\\:realIndex='".concat(a,"']")),n=e.globals.dom.baseEl.querySelector(".apexcharts-datalabels[data\\:realIndex='".concat(a,"']"));var l=e.globals.seriesYAxisReverseMap[a];o=e.globals.dom.baseEl.querySelector(".apexcharts-yaxis[rel='".concat(l,"']"))}else r=e.globals.dom.baseEl.querySelector(".apexcharts-series[rel='".concat(a+1,"']"));else r=e.globals.dom.baseEl.querySelector(".apexcharts-series[rel='".concat(a+1,"'] path"));for(var h=0;h=t.from&&(r0&&void 0!==arguments[0]?arguments[0]:"asc",e=arguments.length>1&&void 0!==arguments[1]?arguments[1]:[],i=this.w,a=0;if(i.config.series.length>1)for(var s=i.config.series.map((function(t,a){return t.data&&t.data.length>0&&-1===i.globals.collapsedSeriesIndices.indexOf(a)&&(!i.globals.comboCharts||0===e.length||e.length&&e.indexOf(i.config.series[a].type)>-1)?a:-1})),r="asc"===t?0:s.length-1;"asc"===t?r=0;"asc"===t?r++:r--)if(-1!==s[r]){a=s[r];break}return a}},{key:"getBarSeriesIndices",value:function(){return this.w.globals.comboCharts?this.w.config.series.map((function(t,e){return"bar"===t.type||"column"===t.type?e:-1})).filter((function(t){return-1!==t})):this.w.config.series.map((function(t,e){return e}))}},{key:"getPreviousPaths",value:function(){var t=this.w;function e(e,i,a){for(var s=e[i].childNodes,r={type:a,paths:[],realIndex:e[i].getAttribute("data:realIndex")},n=0;n0)for(var a=function(e){for(var i=t.globals.dom.baseEl.querySelectorAll(".apexcharts-".concat(t.config.chart.type," .apexcharts-series[data\\:realIndex='").concat(e,"'] rect")),a=[],s=function(t){var e=function(e){return i[t].getAttribute(e)},s={x:parseFloat(e("x")),y:parseFloat(e("y")),width:parseFloat(e("width")),height:parseFloat(e("height"))};a.push({rect:s,color:i[t].getAttribute("color")})},r=0;r0?t:[]}));return t}}]),t}(),Ji=function(){function t(e){i(this,t),this.ctx=e,this.w=e.w,this.twoDSeries=[],this.threeDSeries=[],this.twoDSeriesX=[],this.seriesGoals=[],this.coreUtils=new Pi(this.ctx)}return s(t,[{key:"isMultiFormat",value:function(){return this.isFormatXY()||this.isFormat2DArray()}},{key:"isFormatXY",value:function(){var t=this.w.config.series.slice(),e=new $i(this.ctx);if(this.activeSeriesIndex=e.getActiveConfigSeriesIndex(),void 0!==t[this.activeSeriesIndex].data&&t[this.activeSeriesIndex].data.length>0&&null!==t[this.activeSeriesIndex].data[0]&&void 0!==t[this.activeSeriesIndex].data[0].x&&null!==t[this.activeSeriesIndex].data[0])return!0}},{key:"isFormat2DArray",value:function(){var t=this.w.config.series.slice(),e=new $i(this.ctx);if(this.activeSeriesIndex=e.getActiveConfigSeriesIndex(),void 0!==t[this.activeSeriesIndex].data&&t[this.activeSeriesIndex].data.length>0&&void 0!==t[this.activeSeriesIndex].data[0]&&null!==t[this.activeSeriesIndex].data[0]&&t[this.activeSeriesIndex].data[0].constructor===Array)return!0}},{key:"handleFormat2DArray",value:function(t,e){for(var i=this.w.config,a=this.w.globals,s="boxPlot"===i.chart.type||"boxPlot"===i.series[e].type,r=0;r=5?this.twoDSeries.push(v.parseNumber(t[e].data[r][4])):this.twoDSeries.push(v.parseNumber(t[e].data[r][1])),a.dataFormatXNumeric=!0),"datetime"===i.xaxis.type){var n=new Date(t[e].data[r][0]);n=new Date(n).getTime(),this.twoDSeriesX.push(n)}else this.twoDSeriesX.push(t[e].data[r][0]);for(var o=0;o-1&&(r=this.activeSeriesIndex);for(var n=0;n1&&void 0!==arguments[1]?arguments[1]:this.ctx,a=this.w.config,s=this.w.globals,r=new zi(i),n=a.labels.length>0?a.labels.slice():a.xaxis.categories.slice();s.isRangeBar="rangeBar"===a.chart.type&&s.isBarHorizontal,s.hasXaxisGroups="category"===a.xaxis.type&&a.xaxis.group.groups.length>0,s.hasXaxisGroups&&(s.groups=a.xaxis.group.groups),t.forEach((function(t,e){void 0!==t.name?s.seriesNames.push(t.name):s.seriesNames.push("series-"+parseInt(e+1,10))})),this.coreUtils.setSeriesYAxisMappings();var o=[],l=f(new Set(a.series.map((function(t){return t.group}))));a.series.forEach((function(t,e){var i=l.indexOf(t.group);o[i]||(o[i]=[]),o[i].push(s.seriesNames[e])})),s.seriesGroups=o;for(var h=function(){for(var t=0;t0&&(this.twoDSeriesX=n,s.seriesX.push(this.twoDSeriesX))),s.labels.push(this.twoDSeriesX);var d=t[c].data.map((function(t){return v.parseNumber(t)}));s.series.push(d)}s.seriesZ.push(this.threeDSeries),void 0!==t[c].color?s.seriesColors.push(t[c].color):s.seriesColors.push(void 0)}return this.w}},{key:"parseDataNonAxisCharts",value:function(t){var e=this.w.globals,i=this.w.config,a=Array.isArray(t)&&t.every((function(t){return"number"==typeof t}))&&i.labels.length>0,s=Array.isArray(t)&&t.some((function(t){return t&&"object"===b(t)&&t.data||t&&"object"===b(t)&&t.parsing}));if(a&&s&&console.warn("ApexCharts: Both old format (numeric series + labels) and new format (series objects with data/parsing) detected. Using old format for backward compatibility."),a){e.series=t.slice(),e.seriesNames=i.labels.slice();for(var r=0;r100&&console.warn("ApexCharts: RadialBar value ".concat(e," > 100, consider using percentage values (0-100)")),e})));for(var l=0;l0)i.labels=e.xaxis.categories;else if(e.labels.length>0)i.labels=e.labels.slice();else if(this.fallbackToCategory){if(i.labels=i.labels[0],i.seriesRange.length&&(i.seriesRange.map((function(t){t.forEach((function(t){i.labels.indexOf(t.x)<0&&t.x&&i.labels.push(t.x)}))})),i.labels=Array.from(new Set(i.labels.map(JSON.stringify)),JSON.parse)),e.xaxis.convertedCatToNumeric)new Ni(e).convertCatToNumericXaxis(e,this.ctx,i.seriesX[0]),this._generateExternalLabels(t)}else this._generateExternalLabels(t)}},{key:"_generateExternalLabels",value:function(t){var e=this.w.globals,i=this.w.config,a=[];if(e.axisCharts){if(e.series.length>0)if(this.isFormatXY())for(var s=i.series.map((function(t,e){return t.data.filter((function(t,e,i){return i.findIndex((function(e){return e.x===t.x}))===e}))})),r=s.reduce((function(t,e,i,a){return a[t].length>e.length?t:i}),0),n=0;n0&&s==i.length&&e.push(a)})),t.globals.ignoreYAxisIndexes=e.map((function(t){return t}))}}]),t}(),Qi=function(){function t(e){i(this,t),this.ctx=e,this.w=e.w}return s(t,[{key:"svgStringToNode",value:function(t){return(new DOMParser).parseFromString(t,"image/svg+xml").documentElement}},{key:"scaleSvgNode",value:function(t,e){var i=parseFloat(t.getAttributeNS(null,"width")),a=parseFloat(t.getAttributeNS(null,"height"));t.setAttributeNS(null,"width",i*e),t.setAttributeNS(null,"height",a*e),t.setAttributeNS(null,"viewBox","0 0 "+i+" "+a)}},{key:"getSvgString",value:function(t){var e=this;return new Promise((function(i){var a=e.w,s=t||a.config.chart.toolbar.export.scale||a.config.chart.toolbar.export.width/a.globals.svgWidth;s||(s=1);var r=a.globals.svgWidth*s,n=a.globals.svgHeight*s,o=a.globals.dom.elWrap.cloneNode(!0);o.style.width=r+"px",o.style.height=n+"px";var l=(new XMLSerializer).serializeToString(o),h="\n .apexcharts-tooltip, .apexcharts-toolbar, .apexcharts-xaxistooltip, .apexcharts-yaxistooltip, .apexcharts-xcrosshairs, .apexcharts-ycrosshairs, .apexcharts-zoom-rect, .apexcharts-selection-rect {\n display: none;\n }\n ";a.config.legend.show&&a.globals.dom.elLegendWrap&&a.globals.dom.elLegendWrap.children.length>0&&(h+=Zi);var c='\n \n \n
\n \n ").concat(l,"\n
\n
\n
\n "),d=e.svgStringToNode(c);1!==s&&e.scaleSvgNode(d,s),e.convertImagesToBase64(d).then((function(){c=(new XMLSerializer).serializeToString(d),i(c.replace(/ /g," "))}))}))}},{key:"convertImagesToBase64",value:function(t){var e=this,i=t.getElementsByTagName("image"),a=Array.from(i).map((function(t){var i=t.getAttributeNS("http://www.w3.org/1999/xlink","href");return i&&!i.startsWith("data:")?e.getBase64FromUrl(i).then((function(e){t.setAttributeNS("http://www.w3.org/1999/xlink","href",e)})).catch((function(t){console.error("Error converting image to base64:",t)})):Promise.resolve()}));return Promise.all(a)}},{key:"getBase64FromUrl",value:function(t){return new Promise((function(e,i){var a=new Image;a.crossOrigin="Anonymous",a.onload=function(){var t=document.createElement("canvas");t.width=a.width,t.height=a.height,t.getContext("2d").drawImage(a,0,0),e(t.toDataURL())},a.onerror=i,a.src=t}))}},{key:"svgUrl",value:function(){var t=this;return new Promise((function(e){t.getSvgString().then((function(t){var i=new Blob([t],{type:"image/svg+xml;charset=utf-8"});e(URL.createObjectURL(i))}))}))}},{key:"dataURI",value:function(t){var e=this;return new Promise((function(i){var a=e.w,s=t?t.scale||t.width/a.globals.svgWidth:1,r=document.createElement("canvas");r.width=a.globals.svgWidth*s,r.height=parseInt(a.globals.dom.elWrap.style.height,10)*s;var n="transparent"!==a.config.chart.background&&a.config.chart.background?a.config.chart.background:"#fff",o=r.getContext("2d");o.fillStyle=n,o.fillRect(0,0,r.width*s,r.height*s),e.getSvgString(s).then((function(t){var e="data:image/svg+xml,"+encodeURIComponent(t),a=new Image;a.crossOrigin="anonymous",a.onload=function(){if(o.drawImage(a,0,0),r.msToBlob){var t=r.msToBlob();i({blob:t})}else{var e=r.toDataURL("image/png");i({imgURI:e})}},a.src=e}))}))}},{key:"exportToSVG",value:function(){var t=this;this.svgUrl().then((function(e){t.triggerDownload(e,t.w.config.chart.toolbar.export.svg.filename,".svg")}))}},{key:"exportToPng",value:function(){var t=this,e=this.w.config.chart.toolbar.export.scale,i=this.w.config.chart.toolbar.export.width,a=e?{scale:e}:i?{width:i}:void 0;this.dataURI(a).then((function(e){var i=e.imgURI,a=e.blob;a?navigator.msSaveOrOpenBlob(a,t.w.globals.chartID+".png"):t.triggerDownload(i,t.w.config.chart.toolbar.export.png.filename,".png")}))}},{key:"exportToCSV",value:function(t){var e=this,i=t.series,a=t.fileName,s=t.columnDelimiter,r=void 0===s?",":s,n=t.lineDelimiter,o=void 0===n?"\n":n,l=this.w;i||(i=l.config.series);var h=[],c=[],d="",u=l.globals.series.map((function(t,e){return-1===l.globals.collapsedSeriesIndices.indexOf(e)?t:[]})),g=function(t){return"function"==typeof l.config.chart.toolbar.export.csv.categoryFormatter?l.config.chart.toolbar.export.csv.categoryFormatter(t):"datetime"===l.config.xaxis.type&&String(t).length>=10?new Date(t).toDateString():v.isNumber(t)?t:t.split(r).join("")},p=function(t){return"function"==typeof l.config.chart.toolbar.export.csv.valueFormatter?l.config.chart.toolbar.export.csv.valueFormatter(t):t},x=Math.max.apply(Math,f(i.map((function(t){return t.data?t.data.length:0})))),b=new Ji(this.ctx),m=new Ri(this.ctx),y=function(t){var i="";if(l.globals.axisCharts){if("category"===l.config.xaxis.type||l.config.xaxis.convertedCatToNumeric)if(l.globals.isBarHorizontal){var a=l.globals.yLabelFormatters[0],s=new $i(e.ctx).getActiveConfigSeriesIndex();i=a(l.globals.labels[t],{seriesIndex:s,dataPointIndex:t,w:l})}else i=m.getLabel(l.globals.labels,l.globals.timescaleLabels,0,t).text;"datetime"===l.config.xaxis.type&&(l.config.xaxis.categories.length?i=l.config.xaxis.categories[t]:l.config.labels.length&&(i=l.config.labels[t]))}else i=l.config.labels[t];return null===i?"nullvalue":(Array.isArray(i)&&(i=i.join(" ")),v.isNumber(i)?i:i.split(r).join(""))},w=function(t,e){if(h.length&&0===e&&c.push(h.join(r)),t.data){t.data=t.data.length&&t.data||f(Array(x)).map((function(){return""}));for(var a=0;a0&&!s.globals.isBarHorizontal&&(this.xaxisLabels=s.globals.timescaleLabels.slice()),s.config.xaxis.overwriteCategories&&(this.xaxisLabels=s.config.xaxis.overwriteCategories),this.drawnLabels=[],this.drawnLabelsRects=[],"top"===s.config.xaxis.position?this.offY=0:this.offY=s.globals.gridHeight,this.offY=this.offY+s.config.xaxis.axisBorder.offsetY,this.isCategoryBarHorizontal="bar"===s.config.chart.type&&s.config.plotOptions.bar.horizontal,this.xaxisFontSize=s.config.xaxis.labels.style.fontSize,this.xaxisFontFamily=s.config.xaxis.labels.style.fontFamily,this.xaxisForeColors=s.config.xaxis.labels.style.colors,this.xaxisBorderWidth=s.config.xaxis.axisBorder.width,this.isCategoryBarHorizontal&&(this.xaxisBorderWidth=s.config.yaxis[0].axisBorder.width.toString()),String(this.xaxisBorderWidth).indexOf("%")>-1?this.xaxisBorderWidth=s.globals.gridWidth*parseInt(this.xaxisBorderWidth,10)/100:this.xaxisBorderWidth=parseInt(this.xaxisBorderWidth,10),this.xaxisBorderHeight=s.config.xaxis.axisBorder.height,this.yaxis=s.config.yaxis[0]}return s(t,[{key:"drawXaxis",value:function(){var t=this.w,e=new Mi(this.ctx),i=e.group({class:"apexcharts-xaxis",transform:"translate(".concat(t.config.xaxis.offsetX,", ").concat(t.config.xaxis.offsetY,")")}),a=e.group({class:"apexcharts-xaxis-texts-g",transform:"translate(".concat(t.globals.translateXAxisX,", ").concat(t.globals.translateXAxisY,")")});i.add(a);for(var s=[],r=0;r6&&void 0!==arguments[6]?arguments[6]:{},h=[],c=[],d=this.w,u=l.xaxisFontSize||this.xaxisFontSize,g=l.xaxisFontFamily||this.xaxisFontFamily,p=l.xaxisForeColors||this.xaxisForeColors,f=l.fontWeight||d.config.xaxis.labels.style.fontWeight,x=l.cssClass||d.config.xaxis.labels.style.cssClass,b=d.globals.padHorizontal,m=a.length,v="category"===d.config.xaxis.type?d.globals.dataPoints:m;if(0===v&&m>v&&(v=m),s){var y=Math.max(Number(d.config.xaxis.tickAmount)||1,v>1?v-1:v);n=d.globals.gridWidth/Math.min(y,m-1),b=b+r(0,n)/2+d.config.xaxis.labels.offsetX}else n=d.globals.gridWidth/v,b=b+r(0,n)+d.config.xaxis.labels.offsetX;for(var w=function(s){var l=b-r(s,n)/2+d.config.xaxis.labels.offsetX;0===s&&1===m&&n/2===b&&1===v&&(l=d.globals.gridWidth/2);var y=o.axesUtils.getLabel(a,d.globals.timescaleLabels,l,s,h,u,t),w=28;d.globals.rotateXLabels&&t&&(w=22),d.config.xaxis.title.text&&"top"===d.config.xaxis.position&&(w+=parseFloat(d.config.xaxis.title.style.fontSize)+2),t||(w=w+parseFloat(u)+(d.globals.xAxisLabelsHeight-d.globals.xAxisGroupLabelsHeight)+(d.globals.rotateXLabels?10:0)),y=void 0!==d.config.xaxis.tickAmount&&"dataPoints"!==d.config.xaxis.tickAmount&&"datetime"!==d.config.xaxis.type?o.axesUtils.checkLabelBasedOnTickamount(s,y,m):o.axesUtils.checkForOverflowingLabels(s,y,m,h,c);if(d.config.xaxis.labels.show){var k=e.drawText({x:y.x,y:o.offY+d.config.xaxis.labels.offsetY+w-("top"===d.config.xaxis.position?d.globals.xAxisHeight+d.config.xaxis.axisTicks.height-2:0),text:y.text,textAnchor:"middle",fontWeight:y.isBold?600:f,fontSize:u,fontFamily:g,foreColor:Array.isArray(p)?t&&d.config.xaxis.convertedCatToNumeric?p[d.globals.minX+s-1]:p[s]:p,isPlainText:!1,cssClass:(t?"apexcharts-xaxis-label ":"apexcharts-xaxis-group-label ")+x});if(i.add(k),k.on("click",(function(t){if("function"==typeof d.config.chart.events.xAxisLabelClick){var e=Object.assign({},d,{labelIndex:s});d.config.chart.events.xAxisLabelClick(t,o.ctx,e)}})),t){var A=document.createElementNS(d.globals.SVGNS,"title");A.textContent=Array.isArray(y.text)?y.text.join(" "):y.text,k.node.appendChild(A),""!==y.text&&(h.push(y.text),c.push(y))}}sa.globals.gridWidth)){var r=this.offY+a.config.xaxis.axisTicks.offsetY;if(e=e+r+a.config.xaxis.axisTicks.height,"top"===a.config.xaxis.position&&(e=r-a.config.xaxis.axisTicks.height),a.config.xaxis.axisTicks.show){var n=new Mi(this.ctx).drawLine(t+a.config.xaxis.axisTicks.offsetX,r+a.config.xaxis.offsetY,s+a.config.xaxis.axisTicks.offsetX,e+a.config.xaxis.offsetY,a.config.xaxis.axisTicks.color);i.add(n),n.node.classList.add("apexcharts-xaxis-tick")}}}},{key:"getXAxisTicksPositions",value:function(){var t=this.w,e=[],i=this.xaxisLabels.length,a=t.globals.padHorizontal;if(t.globals.timescaleLabels.length>0)for(var s=0;s0){var h=s[s.length-1].getBBox(),c=s[0].getBBox();h.x<-20&&s[s.length-1].parentNode.removeChild(s[s.length-1]),c.x+c.width>t.globals.gridWidth&&!t.globals.isBarHorizontal&&s[0].parentNode.removeChild(s[0]);for(var d=0;d0&&(this.xaxisLabels=a.globals.timescaleLabels.slice())}return s(t,[{key:"drawGridArea",value:function(){var t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:null,e=this.w,i=new Mi(this.ctx);t||(t=i.group({class:"apexcharts-grid"}));var a=i.drawLine(e.globals.padHorizontal,1,e.globals.padHorizontal,e.globals.gridHeight,"transparent"),s=i.drawLine(e.globals.padHorizontal,e.globals.gridHeight,e.globals.gridWidth,e.globals.gridHeight,"transparent");return t.add(s),t.add(a),t}},{key:"drawGrid",value:function(){if(this.w.globals.axisCharts){var t=this.renderGrid();return this.drawGridArea(t.el),t}return null}},{key:"createGridMask",value:function(){var t=this.w,e=t.globals,i=new Mi(this.ctx),a=Array.isArray(t.config.stroke.width)?Math.max.apply(Math,f(t.config.stroke.width)):t.config.stroke.width,s=function(t){var i=document.createElementNS(e.SVGNS,"clipPath");return i.setAttribute("id",t),i};e.dom.elGridRectMask=s("gridRectMask".concat(e.cuid)),e.dom.elGridRectBarMask=s("gridRectBarMask".concat(e.cuid)),e.dom.elGridRectMarkerMask=s("gridRectMarkerMask".concat(e.cuid)),e.dom.elForecastMask=s("forecastMask".concat(e.cuid)),e.dom.elNonForecastMask=s("nonForecastMask".concat(e.cuid));var r=0,n=0;(["bar","rangeBar","candlestick","boxPlot"].includes(t.config.chart.type)||t.globals.comboBarCount>0)&&t.globals.isXNumeric&&!t.globals.isBarHorizontal&&(r=Math.max(t.config.grid.padding.left,e.barPadForNumericAxis),n=Math.max(t.config.grid.padding.right,e.barPadForNumericAxis)),e.dom.elGridRect=i.drawRect(-a/2-2,-a/2-2,e.gridWidth+a+4,e.gridHeight+a+4,0,"#fff"),e.dom.elGridRectBar=i.drawRect(-a/2-r-2,-a/2-2,e.gridWidth+a+n+r+4,e.gridHeight+a+4,0,"#fff");var o=t.globals.markers.largestSize;e.dom.elGridRectMarker=i.drawRect(Math.min(-a/2-r-2,-o),-o,e.gridWidth+Math.max(a+n+r+4,2*o),e.gridHeight+2*o,0,"#fff"),e.dom.elGridRectMask.appendChild(e.dom.elGridRect.node),e.dom.elGridRectBarMask.appendChild(e.dom.elGridRectBar.node),e.dom.elGridRectMarkerMask.appendChild(e.dom.elGridRectMarker.node);var l=e.dom.baseEl.querySelector("defs");l.appendChild(e.dom.elGridRectMask),l.appendChild(e.dom.elGridRectBarMask),l.appendChild(e.dom.elGridRectMarkerMask),l.appendChild(e.dom.elForecastMask),l.appendChild(e.dom.elNonForecastMask)}},{key:"_drawGridLines",value:function(t){var e=t.i,i=t.x1,a=t.y1,s=t.x2,r=t.y2,n=t.xCount,o=t.parent,l=this.w;if(!(0===e&&l.globals.skipFirstTimelinelabel||e===n-1&&l.globals.skipLastTimelinelabel&&!l.config.xaxis.labels.formatter||"radar"===l.config.chart.type)){l.config.grid.xaxis.lines.show&&this._drawGridLine({i:e,x1:i,y1:a,x2:s,y2:r,xCount:n,parent:o});var h=0;if(l.globals.hasXaxisGroups&&"between"===l.config.xaxis.tickPlacement){var c=l.globals.groups;if(c){for(var d=0,u=0;d0&&"datetime"!==t.config.xaxis.type&&(s=e.yAxisScale[a].result.length-1);this._drawXYLines({xCount:s,tickAmount:r})}else s=r,r=e.xTickAmount,this._drawInvertedXYLines({xCount:s,tickAmount:r});return this.drawGridBands(s,r),{el:this.elg,elGridBorders:this.elGridBorders,xAxisTickWidth:e.gridWidth/s}}},{key:"drawGridBands",value:function(t,e){var i,a,s=this,r=this.w;if((null===(i=r.config.grid.row.colors)||void 0===i?void 0:i.length)>0&&function(t,i,a,n,o,l){for(var h=0,c=0;h=r.config.grid[t].colors.length&&(c=0),s._drawGridBandRect({c:c,x1:a,y1:n,x2:o,y2:l,type:t}),n+=r.globals.gridHeight/e}("row",e,0,0,r.globals.gridWidth,r.globals.gridHeight/e),(null===(a=r.config.grid.column.colors)||void 0===a?void 0:a.length)>0){var n=r.globals.isBarHorizontal||"on"!==r.config.xaxis.tickPlacement||"category"!==r.config.xaxis.type&&!r.config.xaxis.convertedCatToNumeric?t:t-1;r.globals.isXNumeric&&(n=r.globals.xAxisScale.result.length-1);for(var o=r.globals.padHorizontal,l=r.globals.padHorizontal+r.globals.gridWidth/n,h=r.globals.gridHeight,c=0,d=0;c=r.config.grid.column.colors.length&&(d=0),"datetime"===r.config.xaxis.type)o=this.xaxisLabels[c].position,l=((null===(u=this.xaxisLabels[c+1])||void 0===u?void 0:u.position)||r.globals.gridWidth)-this.xaxisLabels[c].position;this._drawGridBandRect({c:d,x1:o,y1:0,x2:l,y2:h,type:"column"}),o+=r.globals.gridWidth/n}}}}]),t}(),ea=function(){function t(e){i(this,t),this.ctx=e,this.w=e.w,this.coreUtils=new Pi(this.ctx)}return s(t,[{key:"niceScale",value:function(t,e){var i,a,s,r,n=arguments.length>2&&void 0!==arguments[2]?arguments[2]:0,o=1e-11,l=this.w,h=l.globals;h.isBarHorizontal?(i=l.config.xaxis,a=Math.max((h.svgWidth-100)/25,2)):(i=l.config.yaxis[n],a=Math.max((h.svgHeight-100)/15,2)),v.isNumber(a)||(a=10),s=void 0!==i.min&&null!==i.min,r=void 0!==i.max&&null!==i.min;var c=void 0!==i.stepSize&&null!==i.stepSize,d=void 0!==i.tickAmount&&null!==i.tickAmount,u=d?i.tickAmount:h.niceScaleDefaultTicks[Math.min(Math.round(a/2),h.niceScaleDefaultTicks.length-1)];if(h.isMultipleYAxis&&!d&&h.multiAxisTickAmount>0&&(u=h.multiAxisTickAmount,d=!0),u="dataPoints"===u?h.dataPoints-1:Math.abs(Math.round(u)),(t===Number.MIN_VALUE&&0===e||!v.isNumber(t)&&!v.isNumber(e)||t===Number.MIN_VALUE&&e===-Number.MAX_VALUE)&&(t=v.isNumber(i.min)?i.min:0,e=v.isNumber(i.max)?i.max:t+u,h.allSeriesCollapsed=!1),t>e){console.warn("axis.min cannot be greater than axis.max: swapping min and max");var g=e;e=t,t=g}else t===e&&(t=0===t?0:t-1,e=0===e?2:e+1);var p=[];u<1&&(u=1);var f=u,x=Math.abs(e-t);!s&&t>0&&t/x<.15&&(t=0,s=!0),!r&&e<0&&-e/x<.15&&(e=0,r=!0);var b=(x=Math.abs(e-t))/f,m=b,y=Math.floor(Math.log10(m)),w=Math.pow(10,y),k=Math.ceil(m/w);if(b=m=(k=h.niceScaleAllowedMagMsd[0===h.yValueDecimal?0:1][k])*w,h.isBarHorizontal&&i.stepSize&&"datetime"!==i.type?(b=i.stepSize,c=!0):c&&(b=i.stepSize),c&&i.forceNiceScale){var A=Math.floor(Math.log10(b));b*=Math.pow(10,y-A)}if(s&&r){var C=x/f;if(d)if(c)if(0!=v.mod(x,b)){var S=v.getGCD(b,C);b=C/S<10?S:C}else 0==v.mod(b,C)?b=C:(C=b,d=!1);else b=C;else if(c)0==v.mod(x,b)?C=b:b=C;else if(0==v.mod(x,b))C=b;else{C=x/(f=Math.ceil(x/b));var L=v.getGCD(x,b);x/La&&(t=e-b*u,t+=b*Math.floor((M-t)/b))}else if(s)if(d)e=t+b*f;else{var P=e;e=b*Math.ceil(e/b),Math.abs(e-t)/v.getGCD(x,b)>a&&(e=t+b*u,e+=b*Math.ceil((P-e)/b))}}else if(h.isMultipleYAxis&&d){var I=b*Math.floor(t/b),T=I+b*f;T0&&t16&&v.getPrimeFactors(f).length<2&&f++,!d&&i.forceNiceScale&&0===h.yValueDecimal&&f>x&&(f=x,b=Math.round(x/f)),f>a&&(!d&&!c||i.forceNiceScale)){var z=v.getPrimeFactors(f),X=z.length-1,R=f;t:for(var E=0;EN);return{result:p,niceMin:p[0],niceMax:p[p.length-1]}}},{key:"linearScale",value:function(t,e){var i=arguments.length>2&&void 0!==arguments[2]?arguments[2]:10,a=arguments.length>3&&void 0!==arguments[3]?arguments[3]:0,s=arguments.length>4&&void 0!==arguments[4]?arguments[4]:void 0,r=Math.abs(e-t),n=[];if(t===e)return{result:n=[t],niceMin:n[0],niceMax:n[n.length-1]};"dataPoints"===(i=this._adjustTicksForSmallRange(i,a,r))&&(i=this.w.globals.dataPoints-1),s||(s=r/i),s=Math.round(100*(s+Number.EPSILON))/100,i===Number.MAX_VALUE&&(i=5,s=1);for(var o=t;i>=0;)n.push(o),o=v.preciseAddition(o,s),i-=1;return{result:n,niceMin:n[0],niceMax:n[n.length-1]}}},{key:"logarithmicScaleNice",value:function(t,e,i){e<=0&&(e=Math.max(t,i)),t<=0&&(t=Math.min(e,i));for(var a=[],s=Math.ceil(Math.log(e)/Math.log(i)+1),r=Math.floor(Math.log(t)/Math.log(i));r5?(a.allSeriesCollapsed=!1,a.yAxisScale[t]=r.forceNiceScale?this.logarithmicScaleNice(e,i,r.logBase):this.logarithmicScale(e,i,r.logBase)):i!==-Number.MAX_VALUE&&v.isNumber(i)&&e!==Number.MAX_VALUE&&v.isNumber(e)?(a.allSeriesCollapsed=!1,a.yAxisScale[t]=this.niceScale(e,i,t)):a.yAxisScale[t]=this.niceScale(Number.MIN_VALUE,0,t)}},{key:"setXScale",value:function(t,e){var i=this.w,a=i.globals;if(e!==-Number.MAX_VALUE&&v.isNumber(e)){var s=a.xTickAmount;a.xAxisScale=this.linearScale(t,e,s,0,void 0===i.config.xaxis.max?i.config.xaxis.stepSize:void 0)}else a.xAxisScale=this.linearScale(0,10,10);return a.xAxisScale}},{key:"scaleMultipleYAxes",value:function(){var t=this,e=this.w.config,i=this.w.globals;this.coreUtils.setSeriesYAxisMappings();var a=i.seriesYAxisMap,s=i.minYArr,r=i.maxYArr;i.allSeriesCollapsed=!0,i.barGroups=[],a.forEach((function(a,n){var o=[];a.forEach((function(t){var i,a=null===(i=e.series[t])||void 0===i?void 0:i.group;o.indexOf(a)<0&&o.push(a)})),a.length>0?function(){var l,h,c=Number.MAX_VALUE,d=-Number.MAX_VALUE,u=c,g=d;if(e.chart.stacked)!function(){var t=new Array(i.dataPoints).fill(0),s=[],r=[],p=[];o.forEach((function(){s.push(t.map((function(){return Number.MIN_VALUE}))),r.push(t.map((function(){return Number.MIN_VALUE}))),p.push(t.map((function(){return Number.MIN_VALUE})))}));for(var f=function(t){!l&&e.series[a[t]].type&&(l=e.series[a[t]].type);var c=a[t];h=e.series[c].group?e.series[c].group:"axis-".concat(n),!(i.collapsedSeriesIndices.indexOf(c)<0&&i.ancillaryCollapsedSeriesIndices.indexOf(c)<0)||(i.allSeriesCollapsed=!1,o.forEach((function(t,a){if(e.series[c].group===t)for(var n=0;n=0?r[a][n]+=o:p[a][n]+=o,s[a][n]+=o,u=Math.min(u,o),g=Math.max(g,o)}}))),"bar"!==l&&"column"!==l||i.barGroups.push(h)},x=0;x1&&void 0!==arguments[1]?arguments[1]:Number.MAX_VALUE,i=arguments.length>2&&void 0!==arguments[2]?arguments[2]:-Number.MAX_VALUE,a=arguments.length>3&&void 0!==arguments[3]?arguments[3]:null,s=this.w.config,r=this.w.globals,n=-Number.MAX_VALUE,o=Number.MIN_VALUE;null===a&&(a=t+1);var l=r.series,h=l,c=l;"candlestick"===s.chart.type?(h=r.seriesCandleL,c=r.seriesCandleH):"boxPlot"===s.chart.type?(h=r.seriesCandleO,c=r.seriesCandleC):r.isRangeData&&(h=r.seriesRangeStart,c=r.seriesRangeEnd);var d=!1;if(r.seriesX.length>=a){var u,g=null===(u=r.brushSource)||void 0===u?void 0:u.w.config.chart.brush;(s.chart.zoom.enabled&&s.chart.zoom.autoScaleYaxis||null!=g&&g.enabled&&null!=g&&g.autoScaleYaxis)&&(d=!0)}for(var p=t;px&&r.seriesX[p][b]>s.xaxis.max;b--);}for(var m=x;m<=b&&m(null===(A=h[p])||void 0===A?void 0:A[m])&&(null===(C=h[p])||void 0===C?void 0:C[m])<0&&(o=h[p][m])}else r.hasNullValues=!0}"bar"!==f&&"column"!==f||(o<0&&n<0&&(n=0,i=Math.max(i,0)),o===Number.MIN_VALUE&&(o=0,e=Math.min(e,0)))}return"rangeBar"===s.chart.type&&r.seriesRangeStart.length&&r.isBarHorizontal&&(o=e),"bar"===s.chart.type&&(o<0&&n<0&&(n=0),o===Number.MIN_VALUE&&(o=0)),{minY:o,maxY:n,lowestY:e,highestY:i}}},{key:"setYRange",value:function(){var t=this.w.globals,e=this.w.config;t.maxY=-Number.MAX_VALUE,t.minY=Number.MIN_VALUE;var i,a=Number.MAX_VALUE;if(t.isMultipleYAxis){a=Number.MAX_VALUE;for(var s=0;st.dataPoints&&0!==t.dataPoints&&(a=t.dataPoints-1);else if("dataPoints"===e.xaxis.tickAmount){if(t.series.length>1&&(a=t.series[t.maxValsInArrayIndex].length-1),t.isXNumeric){var s=Math.round(t.maxX-t.minX);s<30&&(a=s)}}else a=e.xaxis.tickAmount;if(t.xTickAmount=a,void 0!==e.xaxis.max&&"number"==typeof e.xaxis.max&&(t.maxX=e.xaxis.max),void 0!==e.xaxis.min&&"number"==typeof e.xaxis.min&&(t.minX=e.xaxis.min),void 0!==e.xaxis.range&&(t.minX=t.maxX-e.xaxis.range),t.minX!==Number.MAX_VALUE&&t.maxX!==-Number.MAX_VALUE)if(e.xaxis.convertedCatToNumeric&&!t.dataFormatXNumeric){for(var r=[],n=t.minX-1;n0&&(t.xAxisScale=this.scales.linearScale(1,t.labels.length,a-1,0,e.xaxis.stepSize),t.seriesX=t.labels.slice());i&&(t.labels=t.xAxisScale.result.slice())}return t.isBarHorizontal&&t.labels.length&&(t.xTickAmount=t.labels.length),this._handleSingleDataPoint(),this._getMinXDiff(),{minX:t.minX,maxX:t.maxX}}},{key:"setZRange",value:function(){var t=this.w.globals;if(t.isDataXYZ)for(var e=0;e0){var s=e-a[i-1];s>0&&(t.minXDiff=Math.min(s,t.minXDiff))}})),1!==t.dataPoints&&t.minXDiff!==Number.MAX_VALUE||(t.minXDiff=.5)}}))}},{key:"_setStackedMinMax",value:function(){var t=this,e=this.w.globals;if(e.series.length){var i=e.seriesGroups;i.length||(i=[this.w.globals.seriesNames.map((function(t){return t}))]);var a={},s={};i.forEach((function(i){a[i]=[],s[i]=[],t.w.config.series.map((function(t,a){return i.indexOf(e.seriesNames[a])>-1?a:null})).filter((function(t){return null!==t})).forEach((function(r){for(var n=0;n0?a[i][n]+=parseFloat(e.series[r][n])+1e-4:s[i][n]+=parseFloat(e.series[r][n]))}}))})),Object.entries(a).forEach((function(t){var i=p(t,1)[0];a[i].forEach((function(t,r){e.maxY=Math.max(e.maxY,a[i][r]),e.minY=Math.min(e.minY,s[i][r])}))}))}}}]),t}(),aa=function(){function t(e,a){i(this,t),this.ctx=e,this.elgrid=a,this.w=e.w;var s=this.w;this.xaxisFontSize=s.config.xaxis.labels.style.fontSize,this.axisFontFamily=s.config.xaxis.labels.style.fontFamily,this.xaxisForeColors=s.config.xaxis.labels.style.colors,this.isCategoryBarHorizontal="bar"===s.config.chart.type&&s.config.plotOptions.bar.horizontal,this.xAxisoffX="bottom"===s.config.xaxis.position?s.globals.gridHeight:0,this.drawnLabels=[],this.axesUtils=new Ri(e)}return s(t,[{key:"drawYaxis",value:function(t){var e=this.w,i=new Mi(this.ctx),a=e.config.yaxis[t].labels.style,s=a.fontSize,r=a.fontFamily,n=a.fontWeight,o=i.group({class:"apexcharts-yaxis",rel:t,transform:"translate(".concat(e.globals.translateYAxisX[t],", 0)")});if(this.axesUtils.isYAxisHidden(t))return o;var l=i.group({class:"apexcharts-yaxis-texts-g"});o.add(l);var h=e.globals.yAxisScale[t].result.length-1,c=e.globals.gridHeight/h,d=e.globals.yLabelFormatters[t],u=this.axesUtils.checkForReversedLabels(t,e.globals.yAxisScale[t].result.slice());if(e.config.yaxis[t].labels.show){var g=e.globals.translateY+e.config.yaxis[t].labels.offsetY;e.globals.isBarHorizontal?g=0:"heatmap"===e.config.chart.type&&(g-=c/2),g+=parseInt(s,10)/3;for(var p=h;p>=0;p--){var f=d(u[p],p,e),x=e.config.yaxis[t].labels.padding;e.config.yaxis[t].opposite&&0!==e.config.yaxis.length&&(x*=-1);var b=this.getTextAnchor(e.config.yaxis[t].labels.align,e.config.yaxis[t].opposite),m=this.axesUtils.getYAxisForeColor(a.colors,t),y=Array.isArray(m)?m[p]:m,w=v.listToArray(e.globals.dom.baseEl.querySelectorAll(".apexcharts-yaxis[rel='".concat(t,"'] .apexcharts-yaxis-label tspan"))).map((function(t){return t.textContent})),k=i.drawText({x:x,y:g,text:w.includes(f)&&!e.config.yaxis[t].labels.showDuplicates?"":f,textAnchor:b,fontSize:s,fontFamily:r,fontWeight:n,maxWidth:e.config.yaxis[t].labels.maxWidth,foreColor:y,isPlainText:!1,cssClass:"apexcharts-yaxis-label ".concat(a.cssClass)});l.add(k),this.addTooltip(k,f),0!==e.config.yaxis[t].labels.rotate&&this.rotateLabel(i,k,firstLabel,e.config.yaxis[t].labels.rotate),g+=c}}return this.addYAxisTitle(i,o,t),this.addAxisBorder(i,o,t,h,c),o}},{key:"getTextAnchor",value:function(t,e){return"left"===t?"start":"center"===t?"middle":"right"===t?"end":e?"start":"end"}},{key:"addTooltip",value:function(t,e){var i=document.createElementNS(this.w.globals.SVGNS,"title");i.textContent=Array.isArray(e)?e.join(" "):e,t.node.appendChild(i)}},{key:"rotateLabel",value:function(t,e,i,a){var s=t.rotateAroundCenter(i.node),r=t.rotateAroundCenter(e.node);e.node.setAttribute("transform","rotate(".concat(a," ").concat(s.x," ").concat(r.y,")"))}},{key:"addYAxisTitle",value:function(t,e,i){var a=this.w;if(void 0!==a.config.yaxis[i].title.text){var s=t.group({class:"apexcharts-yaxis-title"}),r=a.config.yaxis[i].opposite?a.globals.translateYAxisX[i]:0,n=t.drawText({x:r,y:a.globals.gridHeight/2+a.globals.translateY+a.config.yaxis[i].title.offsetY,text:a.config.yaxis[i].title.text,textAnchor:"end",foreColor:a.config.yaxis[i].title.style.color,fontSize:a.config.yaxis[i].title.style.fontSize,fontWeight:a.config.yaxis[i].title.style.fontWeight,fontFamily:a.config.yaxis[i].title.style.fontFamily,cssClass:"apexcharts-yaxis-title-text ".concat(a.config.yaxis[i].title.style.cssClass)});s.add(n),e.add(s)}}},{key:"addAxisBorder",value:function(t,e,i,a,s){var r=this.w,n=r.config.yaxis[i].axisBorder,o=31+n.offsetX;if(r.config.yaxis[i].opposite&&(o=-31-n.offsetX),n.show){var l=t.drawLine(o,r.globals.translateY+n.offsetY-2,o,r.globals.gridHeight+r.globals.translateY+n.offsetY+2,n.color,0,n.width);e.add(l)}r.config.yaxis[i].axisTicks.show&&this.axesUtils.drawYAxisTicks(o,a,n,r.config.yaxis[i].axisTicks,i,s,e)}},{key:"drawYaxisInversed",value:function(t){var e=this.w,i=new Mi(this.ctx),a=i.group({class:"apexcharts-xaxis apexcharts-yaxis-inversed"}),s=i.group({class:"apexcharts-xaxis-texts-g",transform:"translate(".concat(e.globals.translateXAxisX,", ").concat(e.globals.translateXAxisY,")")});a.add(s);var r=e.globals.yAxisScale[t].result.length-1,n=e.globals.gridWidth/r+.1,o=n+e.config.xaxis.labels.offsetX,l=e.globals.xLabelFormatter,h=this.axesUtils.checkForReversedLabels(t,e.globals.yAxisScale[t].result.slice()),c=e.globals.timescaleLabels;if(c.length>0&&(this.xaxisLabels=c.slice(),r=(h=c.slice()).length),e.config.xaxis.labels.show)for(var d=c.length?0:r;c.length?d=0;c.length?d++:d--){var u=l(h[d],d,e),g=e.globals.gridWidth+e.globals.padHorizontal-(o-n+e.config.xaxis.labels.offsetX);if(c.length){var p=this.axesUtils.getLabel(h,c,g,d,this.drawnLabels,this.xaxisFontSize);g=p.x,u=p.text,this.drawnLabels.push(p.text),0===d&&e.globals.skipFirstTimelinelabel&&(u=""),d===h.length-1&&e.globals.skipLastTimelinelabel&&(u="")}var f=i.drawText({x:g,y:this.xAxisoffX+e.config.xaxis.labels.offsetY+30-("top"===e.config.xaxis.position?e.globals.xAxisHeight+e.config.xaxis.axisTicks.height-2:0),text:u,textAnchor:"middle",foreColor:Array.isArray(this.xaxisForeColors)?this.xaxisForeColors[t]:this.xaxisForeColors,fontSize:this.xaxisFontSize,fontFamily:this.xaxisFontFamily,fontWeight:e.config.xaxis.labels.style.fontWeight,isPlainText:!1,cssClass:"apexcharts-xaxis-label ".concat(e.config.xaxis.labels.style.cssClass)});s.add(f),f.tspan(u),this.addTooltip(f,u),o+=n}return this.inversedYAxisTitleText(a),this.inversedYAxisBorder(a),a}},{key:"inversedYAxisBorder",value:function(t){var e=this.w,i=new Mi(this.ctx),a=e.config.xaxis.axisBorder;if(a.show){var s=0;"bar"===e.config.chart.type&&e.globals.isXNumeric&&(s-=15);var r=i.drawLine(e.globals.padHorizontal+s+a.offsetX,this.xAxisoffX,e.globals.gridWidth,this.xAxisoffX,a.color,0,a.height);this.elgrid&&this.elgrid.elGridBorders&&e.config.grid.show?this.elgrid.elGridBorders.add(r):t.add(r)}}},{key:"inversedYAxisTitleText",value:function(t){var e=this.w,i=new Mi(this.ctx);if(void 0!==e.config.xaxis.title.text){var a=i.group({class:"apexcharts-xaxis-title apexcharts-yaxis-title-inversed"}),s=i.drawText({x:e.globals.gridWidth/2+e.config.xaxis.title.offsetX,y:this.xAxisoffX+parseFloat(this.xaxisFontSize)+parseFloat(e.config.xaxis.title.style.fontSize)+e.config.xaxis.title.offsetY+20,text:e.config.xaxis.title.text,textAnchor:"middle",fontSize:e.config.xaxis.title.style.fontSize,fontFamily:e.config.xaxis.title.style.fontFamily,fontWeight:e.config.xaxis.title.style.fontWeight,foreColor:e.config.xaxis.title.style.color,cssClass:"apexcharts-xaxis-title-text ".concat(e.config.xaxis.title.style.cssClass)});a.add(s),t.add(a)}}},{key:"yAxisTitleRotate",value:function(t,e){var i=this.w,a=new Mi(this.ctx),s=i.globals.dom.baseEl.querySelector(".apexcharts-yaxis[rel='".concat(t,"'] .apexcharts-yaxis-texts-g")),r=s?s.getBoundingClientRect():{width:0,height:0},n=i.globals.dom.baseEl.querySelector(".apexcharts-yaxis[rel='".concat(t,"'] .apexcharts-yaxis-title text")),o=n?n.getBoundingClientRect():{width:0,height:0};if(n){var l=this.xPaddingForYAxisTitle(t,r,o,e);n.setAttribute("x",l.xPos-(e?10:0));var h=a.rotateAroundCenter(n);n.setAttribute("transform","rotate(".concat(e?-1*i.config.yaxis[t].title.rotate:i.config.yaxis[t].title.rotate," ").concat(h.x," ").concat(h.y,")"))}}},{key:"xPaddingForYAxisTitle",value:function(t,e,i,a){var s=this.w,r=0,n=10;return void 0===s.config.yaxis[t].title.text||t<0?{xPos:r,padd:0}:(a?r=e.width+s.config.yaxis[t].title.offsetX+i.width/2+n/2:(r=-1*e.width+s.config.yaxis[t].title.offsetX+n/2+i.width/2,s.globals.isBarHorizontal&&(n=25,r=-1*e.width-s.config.yaxis[t].title.offsetX-n)),{xPos:r,padd:n})}},{key:"setYAxisXPosition",value:function(t,e){var i=this.w,a=0,s=0,r=18,n=1;i.config.yaxis.length>1&&(this.multipleYs=!0),i.config.yaxis.forEach((function(o,l){var h=i.globals.ignoreYAxisIndexes.includes(l)||!o.show||o.floating||0===t[l].width,c=t[l].width+e[l].width;o.opposite?i.globals.isBarHorizontal?(s=i.globals.gridWidth+i.globals.translateX-1,i.globals.translateYAxisX[l]=s-o.labels.offsetX):(s=i.globals.gridWidth+i.globals.translateX+n,h||(n+=c+20),i.globals.translateYAxisX[l]=s-o.labels.offsetX+20):(a=i.globals.translateX-r,h||(r+=c+20),i.globals.translateYAxisX[l]=a+o.labels.offsetX)}))}},{key:"setYAxisTextAlignments",value:function(){var t=this.w;v.listToArray(t.globals.dom.baseEl.getElementsByClassName("apexcharts-yaxis")).forEach((function(e,i){var a=t.config.yaxis[i];if(a&&!a.floating&&void 0!==a.labels.align){var s=t.globals.dom.baseEl.querySelector(".apexcharts-yaxis[rel='".concat(i,"'] .apexcharts-yaxis-texts-g")),r=v.listToArray(t.globals.dom.baseEl.querySelectorAll(".apexcharts-yaxis[rel='".concat(i,"'] .apexcharts-yaxis-label"))),n=s.getBoundingClientRect();r.forEach((function(t){t.setAttribute("text-anchor",a.labels.align)})),"left"!==a.labels.align||a.opposite?"center"===a.labels.align?s.setAttribute("transform","translate(".concat(n.width/2*(a.opposite?1:-1),", 0)")):"right"===a.labels.align&&a.opposite&&s.setAttribute("transform","translate(".concat(n.width,", 0)")):s.setAttribute("transform","translate(-".concat(n.width,", 0)"))}}))}}]),t}(),sa=function(){function t(e){i(this,t),this.ctx=e,this.w=e.w,this.documentEvent=v.bind(this.documentEvent,this)}return s(t,[{key:"addEventListener",value:function(t,e){var i=this.w;i.globals.events.hasOwnProperty(t)?i.globals.events[t].push(e):i.globals.events[t]=[e]}},{key:"removeEventListener",value:function(t,e){var i=this.w;if(i.globals.events.hasOwnProperty(t)){var a=i.globals.events[t].indexOf(e);-1!==a&&i.globals.events[t].splice(a,1)}}},{key:"fireEvent",value:function(t,e){var i=this.w;if(i.globals.events.hasOwnProperty(t)){e&&e.length||(e=[]);for(var a=i.globals.events[t],s=a.length,r=0;r0&&(e=this.w.config.chart.locales.concat(window.Apex.chart.locales));var i=e.filter((function(e){return e.name===t}))[0];if(!i)throw new Error("Wrong locale name provided. Please make sure you set the correct locale name in options");var a=v.extend(Hi,i);this.w.globals.locale=a.options}}]),t}(),na=function(){function t(e){i(this,t),this.ctx=e,this.w=e.w}return s(t,[{key:"drawAxis",value:function(t,e){var i,a,s=this,r=this.w.globals,n=this.w.config,o=new Ki(this.ctx,e),l=new aa(this.ctx,e);r.axisCharts&&"radar"!==t&&(r.isBarHorizontal?(a=l.drawYaxisInversed(0),i=o.drawXaxisInversed(0),r.dom.elGraphical.add(i),r.dom.elGraphical.add(a)):(i=o.drawXaxis(),r.dom.elGraphical.add(i),n.yaxis.map((function(t,e){if(-1===r.ignoreYAxisIndexes.indexOf(e)&&(a=l.drawYaxis(e),r.dom.Paper.add(a),"back"===s.w.config.grid.position)){var i=r.dom.Paper.children()[1];i.remove(),r.dom.Paper.add(i)}}))))}}]),t}(),oa=function(){function t(e){i(this,t),this.ctx=e,this.w=e.w}return s(t,[{key:"drawXCrosshairs",value:function(){var t=this.w,e=new Mi(this.ctx),i=new Li(this.ctx),a=t.config.xaxis.crosshairs.fill.gradient,s=t.config.xaxis.crosshairs.dropShadow,r=t.config.xaxis.crosshairs.fill.type,n=a.colorFrom,o=a.colorTo,l=a.opacityFrom,h=a.opacityTo,c=a.stops,d=s.enabled,u=s.left,g=s.top,p=s.blur,f=s.color,x=s.opacity,b=t.config.xaxis.crosshairs.fill.color;if(t.config.xaxis.crosshairs.show){"gradient"===r&&(b=e.drawGradient("vertical",n,o,l,h,null,c,null));var m=e.drawRect();1===t.config.xaxis.crosshairs.width&&(m=e.drawLine());var y=t.globals.gridHeight;(!v.isNumber(y)||y<0)&&(y=0);var w=t.config.xaxis.crosshairs.width;(!v.isNumber(w)||w<0)&&(w=0),m.attr({class:"apexcharts-xcrosshairs",x:0,y:0,y2:y,width:w,height:y,fill:b,filter:"none","fill-opacity":t.config.xaxis.crosshairs.opacity,stroke:t.config.xaxis.crosshairs.stroke.color,"stroke-width":t.config.xaxis.crosshairs.stroke.width,"stroke-dasharray":t.config.xaxis.crosshairs.stroke.dashArray}),d&&(m=i.dropShadow(m,{left:u,top:g,blur:p,color:f,opacity:x})),t.globals.dom.elGraphical.add(m)}}},{key:"drawYCrosshairs",value:function(){var t=this.w,e=new Mi(this.ctx),i=t.config.yaxis[0].crosshairs,a=t.globals.barPadForNumericAxis;if(t.config.yaxis[0].crosshairs.show){var s=e.drawLine(-a,0,t.globals.gridWidth+a,0,i.stroke.color,i.stroke.dashArray,i.stroke.width);s.attr({class:"apexcharts-ycrosshairs"}),t.globals.dom.elGraphical.add(s)}var r=e.drawLine(-a,0,t.globals.gridWidth+a,0,i.stroke.color,0,0);r.attr({class:"apexcharts-ycrosshairs-hidden"}),t.globals.dom.elGraphical.add(r)}}]),t}(),la=function(){function t(e){i(this,t),this.ctx=e,this.w=e.w}return s(t,[{key:"checkResponsiveConfig",value:function(t){var e=this,i=this.w,a=i.config;if(0!==a.responsive.length){var s=a.responsive.slice();s.sort((function(t,e){return t.breakpoint>e.breakpoint?1:e.breakpoint>t.breakpoint?-1:0})).reverse();var r=new Wi({}),n=function(){var t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{},a=s[0].breakpoint,n=window.innerWidth>0?window.innerWidth:screen.width;if(n>a){var o=v.clone(i.globals.initialConfig);o.series=v.clone(i.config.series);var l=Pi.extendArrayProps(r,o,i);t=v.extend(l,t),t=v.extend(i.config,t),e.overrideResponsiveOptions(t)}else for(var h=0;h0&&"function"==typeof t[0]?(this.isColorFn=!0,i.config.series.map((function(a,s){var r=t[s]||t[0];return"function"==typeof r?r({value:i.globals.axisCharts?i.globals.series[s][0]||0:i.globals.series[s],seriesIndex:s,dataPointIndex:s,w:e.w}):r}))):t:this.predefined()}},{key:"applySeriesColors",value:function(t,e){t.forEach((function(t,i){t&&(e[i]=t)}))}},{key:"getMonochromeColors",value:function(t,e,i){var a=t.color,s=t.shadeIntensity,r=t.shadeTo,n=this.isBarDistributed||this.isHeatmapDistributed?e[0].length*e.length:e.length,o=1/(n/s),l=0;return Array.from({length:n},(function(){var t="dark"===r?i.shadeColor(-1*l,a):i.shadeColor(l,a);return l+=o,t}))}},{key:"applyColorTypes",value:function(t,e){var i=this,a=this.w;t.forEach((function(t){a.globals[t].colors=void 0===a.config[t].colors?i.isColorFn?a.config.colors:e:a.config[t].colors.slice(),i.pushExtraColors(a.globals[t].colors)}))}},{key:"applyDataLabelsColors",value:function(t){var e=this.w;e.globals.dataLabels.style.colors=void 0===e.config.dataLabels.style.colors?t:e.config.dataLabels.style.colors.slice(),this.pushExtraColors(e.globals.dataLabels.style.colors,50)}},{key:"applyRadarPolygonsColors",value:function(){var t=this.w;t.globals.radarPolygons.fill.colors=void 0===t.config.plotOptions.radar.polygons.fill.colors?["dark"===t.config.theme.mode?"#343A3F":"none"]:t.config.plotOptions.radar.polygons.fill.colors.slice(),this.pushExtraColors(t.globals.radarPolygons.fill.colors,20)}},{key:"applyMarkersColors",value:function(t){var e=this.w;e.globals.markers.colors=void 0===e.config.markers.colors?t:e.config.markers.colors.slice(),this.pushExtraColors(e.globals.markers.colors)}},{key:"pushExtraColors",value:function(t,e){var i=arguments.length>2&&void 0!==arguments[2]?arguments[2]:null,a=this.w,s=e||a.globals.series.length;if(null===i&&(i=this.isBarDistributed||this.isHeatmapDistributed||"heatmap"===a.config.chart.type&&a.config.plotOptions.heatmap&&a.config.plotOptions.heatmap.colorScale.inverse),i&&a.globals.series.length&&(s=a.globals.series[a.globals.maxValsInArrayIndex].length*a.globals.series.length),t.lengtht.globals.svgWidth&&(this.dCtx.lgRect.width=t.globals.svgWidth/1.5),this.dCtx.lgRect}},{key:"getDatalabelsRect",value:function(){var t=this,e=this.w,i=[];e.config.series.forEach((function(s,r){s.data.forEach((function(s,n){var o;o=e.globals.series[r][n],a=e.config.dataLabels.formatter(o,{ctx:t.dCtx.ctx,seriesIndex:r,dataPointIndex:n,w:e}),i.push(a)}))}));var a=v.getLargestStringFromArr(i),s=new Mi(this.dCtx.ctx),r=e.config.dataLabels.style,n=s.getTextRects(a,parseInt(r.fontSize),r.fontFamily);return{width:1.05*n.width,height:n.height}}},{key:"getLargestStringFromMultiArr",value:function(t,e){var i=t;if(this.w.globals.isMultiLineX){var a=e.map((function(t,e){return Array.isArray(t)?t.length:1})),s=Math.max.apply(Math,f(a));i=e[a.indexOf(s)]}return i}}]),t}(),ua=function(){function t(e){i(this,t),this.w=e.w,this.dCtx=e}return s(t,[{key:"getxAxisLabelsCoords",value:function(){var t,e=this.w,i=e.globals.labels.slice();if(e.config.xaxis.convertedCatToNumeric&&0===i.length&&(i=e.globals.categoryLabels),e.globals.timescaleLabels.length>0){var a=this.getxAxisTimeScaleLabelsCoords();t={width:a.width,height:a.height},e.globals.rotateXLabels=!1}else{this.dCtx.lgWidthForSideLegends="left"!==e.config.legend.position&&"right"!==e.config.legend.position||e.config.legend.floating?0:this.dCtx.lgRect.width;var s=e.globals.xLabelFormatter,r=v.getLargestStringFromArr(i),n=this.dCtx.dimHelpers.getLargestStringFromMultiArr(r,i);e.globals.isBarHorizontal&&(n=r=e.globals.yAxisScale[0].result.reduce((function(t,e){return t.length>e.length?t:e}),0));var o=new Xi(this.dCtx.ctx),l=r;r=o.xLabelFormat(s,r,l,{i:void 0,dateFormatter:new zi(this.dCtx.ctx).formatDate,w:e}),n=o.xLabelFormat(s,n,l,{i:void 0,dateFormatter:new zi(this.dCtx.ctx).formatDate,w:e}),(e.config.xaxis.convertedCatToNumeric&&void 0===r||""===String(r).trim())&&(n=r="1");var h=new Mi(this.dCtx.ctx),c=h.getTextRects(r,e.config.xaxis.labels.style.fontSize),d=c;if(r!==n&&(d=h.getTextRects(n,e.config.xaxis.labels.style.fontSize)),(t={width:c.width>=d.width?c.width:d.width,height:c.height>=d.height?c.height:d.height}).width*i.length>e.globals.svgWidth-this.dCtx.lgWidthForSideLegends-this.dCtx.yAxisWidth-this.dCtx.gridPad.left-this.dCtx.gridPad.right&&0!==e.config.xaxis.labels.rotate||e.config.xaxis.labels.rotateAlways){if(!e.globals.isBarHorizontal){e.globals.rotateXLabels=!0;var u=function(t){return h.getTextRects(t,e.config.xaxis.labels.style.fontSize,e.config.xaxis.labels.style.fontFamily,"rotate(".concat(e.config.xaxis.labels.rotate," 0 0)"),!1)};c=u(r),r!==n&&(d=u(n)),t.height=(c.height>d.height?c.height:d.height)/1.5,t.width=c.width>d.width?c.width:d.width}}else e.globals.rotateXLabels=!1}return e.config.xaxis.labels.show||(t={width:0,height:0}),{width:t.width,height:t.height}}},{key:"getxAxisGroupLabelsCoords",value:function(){var t,e=this.w;if(!e.globals.hasXaxisGroups)return{width:0,height:0};var i,a=(null===(t=e.config.xaxis.group.style)||void 0===t?void 0:t.fontSize)||e.config.xaxis.labels.style.fontSize,s=e.globals.groups.map((function(t){return t.title})),r=v.getLargestStringFromArr(s),n=this.dCtx.dimHelpers.getLargestStringFromMultiArr(r,s),o=new Mi(this.dCtx.ctx),l=o.getTextRects(r,a),h=l;return r!==n&&(h=o.getTextRects(n,a)),i={width:l.width>=h.width?l.width:h.width,height:l.height>=h.height?l.height:h.height},e.config.xaxis.labels.show||(i={width:0,height:0}),{width:i.width,height:i.height}}},{key:"getxAxisTitleCoords",value:function(){var t=this.w,e=0,i=0;if(void 0!==t.config.xaxis.title.text){var a=new Mi(this.dCtx.ctx).getTextRects(t.config.xaxis.title.text,t.config.xaxis.title.style.fontSize);e=a.width,i=a.height}return{width:e,height:i}}},{key:"getxAxisTimeScaleLabelsCoords",value:function(){var t,e=this.w;this.dCtx.timescaleLabels=e.globals.timescaleLabels.slice();var i=this.dCtx.timescaleLabels.map((function(t){return t.value})),a=i.reduce((function(t,e){return void 0===t?(console.error("You have possibly supplied invalid Date format. Please supply a valid JavaScript Date"),0):t.length>e.length?t:e}),0);return 1.05*(t=new Mi(this.dCtx.ctx).getTextRects(a,e.config.xaxis.labels.style.fontSize)).width*i.length>e.globals.gridWidth&&0!==e.config.xaxis.labels.rotate&&(e.globals.overlappingXLabels=!0),t}},{key:"additionalPaddingXLabels",value:function(t){var e=this,i=this.w,a=i.globals,s=i.config,r=s.xaxis.type,n=t.width;a.skipLastTimelinelabel=!1,a.skipFirstTimelinelabel=!1;var o=i.config.yaxis[0].opposite&&i.globals.isBarHorizontal,l=function(t,o){s.yaxis.length>1&&function(t){return-1!==a.collapsedSeriesIndices.indexOf(t)}(o)||function(t){if(e.dCtx.timescaleLabels&&e.dCtx.timescaleLabels.length){var o=e.dCtx.timescaleLabels[0],l=e.dCtx.timescaleLabels[e.dCtx.timescaleLabels.length-1].position+n/1.75-e.dCtx.yAxisWidthRight,h=o.position-n/1.75+e.dCtx.yAxisWidthLeft,c="right"===i.config.legend.position&&e.dCtx.lgRect.width>0?e.dCtx.lgRect.width:0;l>a.svgWidth-a.translateX-c&&(a.skipLastTimelinelabel=!0),h<-(t.show&&!t.floating||"bar"!==s.chart.type&&"candlestick"!==s.chart.type&&"rangeBar"!==s.chart.type&&"boxPlot"!==s.chart.type?10:n/1.75)&&(a.skipFirstTimelinelabel=!0)}else"datetime"===r?e.dCtx.gridPad.right(null===(a=String(c(e,o)))||void 0===a?void 0:a.length)?t:e}),d),g=u=c(u,o);if(void 0!==u&&0!==u.length||(u=l.niceMax),e.globals.isBarHorizontal){a=0;var p=e.globals.labels.slice();u=v.getLargestStringFromArr(p),u=c(u,{seriesIndex:n,dataPointIndex:-1,w:e}),g=t.dCtx.dimHelpers.getLargestStringFromMultiArr(u,p)}var f=new Mi(t.dCtx.ctx),x="rotate(".concat(r.labels.rotate," 0 0)"),b=f.getTextRects(u,r.labels.style.fontSize,r.labels.style.fontFamily,x,!1),m=b;u!==g&&(m=f.getTextRects(g,r.labels.style.fontSize,r.labels.style.fontFamily,x,!1)),i.push({width:(h>m.width||h>b.width?h:m.width>b.width?m.width:b.width)+a,height:m.height>b.height?m.height:b.height})}else i.push({width:0,height:0})})),i}},{key:"getyAxisTitleCoords",value:function(){var t=this,e=this.w,i=[];return e.config.yaxis.map((function(e,a){if(e.show&&void 0!==e.title.text){var s=new Mi(t.dCtx.ctx),r="rotate(".concat(e.title.rotate," 0 0)"),n=s.getTextRects(e.title.text,e.title.style.fontSize,e.title.style.fontFamily,r,!1);i.push({width:n.width,height:n.height})}else i.push({width:0,height:0})})),i}},{key:"getTotalYAxisWidth",value:function(){var t=this.w,e=0,i=0,a=0,s=t.globals.yAxisScale.length>1?10:0,r=new Ri(this.dCtx.ctx),n=function(n,o){var l=t.config.yaxis[o].floating,h=0;n.width>0&&!l?(h=n.width+s,function(e){return t.globals.ignoreYAxisIndexes.indexOf(e)>-1}(o)&&(h=h-n.width-s)):h=l||r.isYAxisHidden(o)?0:5,t.config.yaxis[o].opposite?a+=h:i+=h,e+=h};return t.globals.yLabelsCoords.map((function(t,e){n(t,e)})),t.globals.yTitleCoords.map((function(t,e){n(t,e)})),t.globals.isBarHorizontal&&!t.config.yaxis[0].floating&&(e=t.globals.yLabelsCoords[0].width+t.globals.yTitleCoords[0].width+15),this.dCtx.yAxisWidthLeft=i,this.dCtx.yAxisWidthRight=a,e}}]),t}(),pa=function(){function t(e){i(this,t),this.w=e.w,this.dCtx=e}return s(t,[{key:"gridPadForColumnsInNumericAxis",value:function(t){var e=this.w,i=e.config,a=e.globals;if(a.noData||a.collapsedSeries.length+a.ancillaryCollapsedSeries.length===i.series.length)return 0;var s=function(t){return["bar","rangeBar","candlestick","boxPlot"].includes(t)},r=i.chart.type,n=0,o=s(r)?i.series.length:1;a.comboBarCount>0&&(o=a.comboBarCount),a.collapsedSeries.forEach((function(t){s(t.type)&&(o-=1)})),i.chart.stacked&&(o=1);var l=s(r)||a.comboBarCount>0,h=Math.abs(a.initialMaxX-a.initialMinX);if(l&&a.isXNumeric&&!a.isBarHorizontal&&o>0&&0!==h){h<=3&&(h=a.dataPoints);var c=h/t,d=a.minXDiff&&a.minXDiff/c>0?a.minXDiff/c:0;d>t/2&&(d/=2),(n=d*parseInt(i.plotOptions.bar.columnWidth,10)/100)<1&&(n=1),a.barPadForNumericAxis=n}return n}},{key:"gridPadFortitleSubtitle",value:function(){var t=this,e=this.w,i=e.globals,a=this.dCtx.isSparkline||!i.axisCharts?0:10;["title","subtitle"].forEach((function(s){void 0!==e.config[s].text?a+=e.config[s].margin:a+=t.dCtx.isSparkline||!i.axisCharts?0:5})),!e.config.legend.show||"bottom"!==e.config.legend.position||e.config.legend.floating||i.axisCharts||(a+=10);var s=this.dCtx.dimHelpers.getTitleSubtitleCoords("title"),r=this.dCtx.dimHelpers.getTitleSubtitleCoords("subtitle");i.gridHeight-=s.height+r.height+a,i.translateY+=s.height+r.height+a}},{key:"setGridXPosForDualYAxis",value:function(t,e){var i=this.w,a=new Ri(this.dCtx.ctx);i.config.yaxis.forEach((function(s,r){-1!==i.globals.ignoreYAxisIndexes.indexOf(r)||s.floating||a.isYAxisHidden(r)||(s.opposite&&(i.globals.translateX-=e[r].width+t[r].width+parseInt(s.labels.style.fontSize,10)/1.2+12),i.globals.translateX<2&&(i.globals.translateX=2))}))}}]),t}(),fa=function(){function t(e){i(this,t),this.ctx=e,this.w=e.w,this.lgRect={},this.yAxisWidth=0,this.yAxisWidthLeft=0,this.yAxisWidthRight=0,this.xAxisHeight=0,this.isSparkline=this.w.config.chart.sparkline.enabled,this.dimHelpers=new da(this),this.dimYAxis=new ga(this),this.dimXAxis=new ua(this),this.dimGrid=new pa(this),this.lgWidthForSideLegends=0,this.gridPad=this.w.config.grid.padding,this.xPadRight=0,this.xPadLeft=0}return s(t,[{key:"plotCoords",value:function(){var t=this,e=this.w,i=e.globals;this.lgRect=this.dimHelpers.getLegendsRect(),this.datalabelsCoords={width:0,height:0};var a=Array.isArray(e.config.stroke.width)?Math.max.apply(Math,f(e.config.stroke.width)):e.config.stroke.width;this.isSparkline&&((e.config.markers.discrete.length>0||e.config.markers.size>0)&&Object.entries(this.gridPad).forEach((function(e){var i=p(e,2),a=i[0],s=i[1];t.gridPad[a]=Math.max(s,t.w.globals.markers.largestSize/1.5)})),this.gridPad.top=Math.max(a/2,this.gridPad.top),this.gridPad.bottom=Math.max(a/2,this.gridPad.bottom)),i.axisCharts?this.setDimensionsForAxisCharts():this.setDimensionsForNonAxisCharts(),this.dimGrid.gridPadFortitleSubtitle(),i.gridHeight=i.gridHeight-this.gridPad.top-this.gridPad.bottom,i.gridWidth=i.gridWidth-this.gridPad.left-this.gridPad.right-this.xPadRight-this.xPadLeft;var s=this.dimGrid.gridPadForColumnsInNumericAxis(i.gridWidth);i.gridWidth=i.gridWidth-2*s,i.translateX=i.translateX+this.gridPad.left+this.xPadLeft+(s>0?s:0),i.translateY=i.translateY+this.gridPad.top}},{key:"setDimensionsForAxisCharts",value:function(){var t=this,e=this.w,i=e.globals,a=this.dimYAxis.getyAxisLabelsCoords(),s=this.dimYAxis.getyAxisTitleCoords();i.isSlopeChart&&(this.datalabelsCoords=this.dimHelpers.getDatalabelsRect()),e.globals.yLabelsCoords=[],e.globals.yTitleCoords=[],e.config.yaxis.map((function(t,i){e.globals.yLabelsCoords.push({width:a[i].width,index:i}),e.globals.yTitleCoords.push({width:s[i].width,index:i})})),this.yAxisWidth=this.dimYAxis.getTotalYAxisWidth();var r=this.dimXAxis.getxAxisLabelsCoords(),n=this.dimXAxis.getxAxisGroupLabelsCoords(),o=this.dimXAxis.getxAxisTitleCoords();this.conditionalChecksForAxisCoords(r,o,n),i.translateXAxisY=e.globals.rotateXLabels?this.xAxisHeight/8:-4,i.translateXAxisX=e.globals.rotateXLabels&&e.globals.isXNumeric&&e.config.xaxis.labels.rotate<=-45?-this.xAxisWidth/4:0,e.globals.isBarHorizontal&&(i.rotateXLabels=!1,i.translateXAxisY=parseInt(e.config.xaxis.labels.style.fontSize,10)/1.5*-1),i.translateXAxisY=i.translateXAxisY+e.config.xaxis.labels.offsetY,i.translateXAxisX=i.translateXAxisX+e.config.xaxis.labels.offsetX;var l=this.yAxisWidth,h=this.xAxisHeight;i.xAxisLabelsHeight=this.xAxisHeight-o.height,i.xAxisGroupLabelsHeight=i.xAxisLabelsHeight-r.height,i.xAxisLabelsWidth=this.xAxisWidth,i.xAxisHeight=this.xAxisHeight;var c=10;("radar"===e.config.chart.type||this.isSparkline)&&(l=0,h=0),this.isSparkline&&(this.lgRect={height:0,width:0}),(this.isSparkline||"treemap"===e.config.chart.type)&&(l=0,h=0,c=0),this.isSparkline||"treemap"===e.config.chart.type||this.dimXAxis.additionalPaddingXLabels(r);var d=function(){i.translateX=l+t.datalabelsCoords.width,i.gridHeight=i.svgHeight-t.lgRect.height-h-(t.isSparkline||"treemap"===e.config.chart.type?0:e.globals.rotateXLabels?10:15),i.gridWidth=i.svgWidth-l-2*t.datalabelsCoords.width};switch("top"===e.config.xaxis.position&&(c=i.xAxisHeight-e.config.xaxis.axisTicks.height-5),e.config.legend.position){case"bottom":i.translateY=c,d();break;case"top":i.translateY=this.lgRect.height+c,d();break;case"left":i.translateY=c,i.translateX=this.lgRect.width+l+this.datalabelsCoords.width,i.gridHeight=i.svgHeight-h-12,i.gridWidth=i.svgWidth-this.lgRect.width-l-2*this.datalabelsCoords.width;break;case"right":i.translateY=c,i.translateX=l+this.datalabelsCoords.width,i.gridHeight=i.svgHeight-h-12,i.gridWidth=i.svgWidth-this.lgRect.width-l-2*this.datalabelsCoords.width-5;break;default:throw new Error("Legend position not supported")}this.dimGrid.setGridXPosForDualYAxis(s,a),new aa(this.ctx).setYAxisXPosition(a,s)}},{key:"setDimensionsForNonAxisCharts",value:function(){var t=this.w,e=t.globals,i=t.config,a=0;t.config.legend.show&&!t.config.legend.floating&&(a=20);var s="pie"===i.chart.type||"polarArea"===i.chart.type||"donut"===i.chart.type?"pie":"radialBar",r=i.plotOptions[s].offsetY,n=i.plotOptions[s].offsetX;if(!i.legend.show||i.legend.floating){e.gridHeight=e.svgHeight;var o=e.dom.elWrap.getBoundingClientRect().width;return e.gridWidth=Math.min(o,e.gridHeight),e.translateY=r,void(e.translateX=n+(e.svgWidth-e.gridWidth)/2)}switch(i.legend.position){case"bottom":e.gridHeight=e.svgHeight-this.lgRect.height,e.gridWidth=e.svgWidth,e.translateY=r-10,e.translateX=n+(e.svgWidth-e.gridWidth)/2;break;case"top":e.gridHeight=e.svgHeight-this.lgRect.height,e.gridWidth=e.svgWidth,e.translateY=this.lgRect.height+r+10,e.translateX=n+(e.svgWidth-e.gridWidth)/2;break;case"left":e.gridWidth=e.svgWidth-this.lgRect.width-a,e.gridHeight="auto"!==i.chart.height?e.svgHeight:e.gridWidth,e.translateY=r,e.translateX=n+this.lgRect.width+a;break;case"right":e.gridWidth=e.svgWidth-this.lgRect.width-a-5,e.gridHeight="auto"!==i.chart.height?e.svgHeight:e.gridWidth,e.translateY=r,e.translateX=n+10;break;default:throw new Error("Legend position not supported")}}},{key:"conditionalChecksForAxisCoords",value:function(t,e,i){var a=this.w,s=a.globals.hasXaxisGroups?2:1,r=i.height+t.height+e.height,n=a.globals.isMultiLineX?1.2:a.globals.LINE_HEIGHT_RATIO,o=a.globals.rotateXLabels?22:10,l=a.globals.rotateXLabels&&"bottom"===a.config.legend.position?10:0;this.xAxisHeight=r*n+s*o+l,this.xAxisWidth=t.width,this.xAxisHeight-e.height>a.config.xaxis.labels.maxHeight&&(this.xAxisHeight=a.config.xaxis.labels.maxHeight),a.config.xaxis.labels.minHeight&&this.xAxisHeightc&&(this.yAxisWidth=c)}}]),t}(),xa=function(){function t(e){i(this,t),this.w=e.w,this.lgCtx=e}return s(t,[{key:"getLegendStyles",value:function(){var t,e,i,a=document.createElement("style");a.setAttribute("type","text/css");var s=(null===(t=this.lgCtx.ctx)||void 0===t||null===(e=t.opts)||void 0===e||null===(i=e.chart)||void 0===i?void 0:i.nonce)||this.w.config.chart.nonce;s&&a.setAttribute("nonce",s);var r=document.createTextNode(Zi);return a.appendChild(r),a}},{key:"getLegendDimensions",value:function(){var t=this.w.globals.dom.baseEl.querySelector(".apexcharts-legend").getBoundingClientRect(),e=t.width;return{clwh:t.height,clww:e}}},{key:"appendToForeignObject",value:function(){var t=this.w.globals;!1!==this.w.config.chart.injectStyleSheet&&t.dom.elLegendForeign.appendChild(this.getLegendStyles())}},{key:"toggleDataSeries",value:function(t,e){var i=this,a=this.w;if(a.globals.axisCharts||"radialBar"===a.config.chart.type){a.globals.resized=!0;var s=null,r=null;if(a.globals.risingSeries=[],a.globals.axisCharts?(s=a.globals.dom.baseEl.querySelector(".apexcharts-series[data\\:realIndex='".concat(t,"']")),r=parseInt(s.getAttribute("data:realIndex"),10)):(s=a.globals.dom.baseEl.querySelector(".apexcharts-series[rel='".concat(t+1,"']")),r=parseInt(s.getAttribute("rel"),10)-1),e)[{cs:a.globals.collapsedSeries,csi:a.globals.collapsedSeriesIndices},{cs:a.globals.ancillaryCollapsedSeries,csi:a.globals.ancillaryCollapsedSeriesIndices}].forEach((function(t){i.riseCollapsedSeries(t.cs,t.csi,r)}));else this.hideSeries({seriesEl:s,realIndex:r})}else{var n=a.globals.dom.Paper.findOne(" .apexcharts-series[rel='".concat(t+1,"'] path")),o=a.config.chart.type;if("pie"===o||"polarArea"===o||"donut"===o){var l=a.config.plotOptions.pie.donut.labels;new Mi(this.lgCtx.ctx).pathMouseDown(n,null),this.lgCtx.ctx.pie.printDataLabelsInner(n.node,l)}n.fire("click")}}},{key:"getSeriesAfterCollapsing",value:function(t){var e=t.realIndex,i=this.w,a=i.globals,s=v.clone(i.config.series);if(a.axisCharts){var r=i.config.yaxis[a.seriesYAxisReverseMap[e]],n={index:e,data:s[e].data.slice(),type:s[e].type||i.config.chart.type};if(r&&r.show&&r.showAlways)a.ancillaryCollapsedSeriesIndices.indexOf(e)<0&&(a.ancillaryCollapsedSeries.push(n),a.ancillaryCollapsedSeriesIndices.push(e));else if(a.collapsedSeriesIndices.indexOf(e)<0){a.collapsedSeries.push(n),a.collapsedSeriesIndices.push(e);var o=a.risingSeries.indexOf(e);a.risingSeries.splice(o,1)}}else a.collapsedSeries.push({index:e,data:s[e]}),a.collapsedSeriesIndices.push(e);return a.allSeriesCollapsed=a.collapsedSeries.length+a.ancillaryCollapsedSeries.length===i.config.series.length,this._getSeriesBasedOnCollapsedState(s)}},{key:"hideSeries",value:function(t){for(var e=t.seriesEl,i=t.realIndex,a=this.w,s=this.getSeriesAfterCollapsing({realIndex:i}),r=e.childNodes,n=0;n0){for(var r=0;r1;if(this.legendHelpers.appendToForeignObject(),(a||!e.axisCharts)&&i.legend.show){for(;e.dom.elLegendWrap.firstChild;)e.dom.elLegendWrap.removeChild(e.dom.elLegendWrap.firstChild);this.drawLegends(),"bottom"===i.legend.position||"top"===i.legend.position?this.legendAlignHorizontal():"right"!==i.legend.position&&"left"!==i.legend.position||this.legendAlignVertical()}}},{key:"createLegendMarker",value:function(t){var e=t.i,i=t.fillcolor,a=this.w,s=document.createElement("span");s.classList.add("apexcharts-legend-marker");var r=a.config.legend.markers.shape||a.config.markers.shape,n=r;Array.isArray(r)&&(n=r[e]);var o=Array.isArray(a.config.legend.markers.size)?parseFloat(a.config.legend.markers.size[e]):parseFloat(a.config.legend.markers.size),l=Array.isArray(a.config.legend.markers.offsetX)?parseFloat(a.config.legend.markers.offsetX[e]):parseFloat(a.config.legend.markers.offsetX),h=Array.isArray(a.config.legend.markers.offsetY)?parseFloat(a.config.legend.markers.offsetY[e]):parseFloat(a.config.legend.markers.offsetY),c=Array.isArray(a.config.legend.markers.strokeWidth)?parseFloat(a.config.legend.markers.strokeWidth[e]):parseFloat(a.config.legend.markers.strokeWidth),d=s.style;if(d.height=2*(o+c)+"px",d.width=2*(o+c)+"px",d.left=l+"px",d.top=h+"px",a.config.legend.markers.customHTML)d.background="transparent",d.color=i[e],Array.isArray(a.config.legend.markers.customHTML)?a.config.legend.markers.customHTML[e]&&(s.innerHTML=a.config.legend.markers.customHTML[e]()):s.innerHTML=a.config.legend.markers.customHTML();else{var g=new Vi(this.ctx).getMarkerConfig({cssClass:"apexcharts-legend-marker apexcharts-marker apexcharts-marker-".concat(n),seriesIndex:e,strokeWidth:c,size:o}),p=window.SVG().addTo(s).size("100%","100%"),f=new Mi(this.ctx).drawMarker(0,0,u(u({},g),{},{pointFillColor:Array.isArray(i)?i[e]:g.pointFillColor,shape:n}));a.globals.dom.Paper.find(".apexcharts-legend-marker.apexcharts-marker").forEach((function(t){t.node.classList.contains("apexcharts-marker-triangle")?t.node.style.transform="translate(50%, 45%)":t.node.style.transform="translate(50%, 50%)"})),p.add(f)}return s}},{key:"drawLegends",value:function(){var t=this,e=this,i=this.w,a=i.config.legend.fontFamily,s=i.globals.seriesNames,r=i.config.legend.markers.fillColors?i.config.legend.markers.fillColors.slice():i.globals.colors.slice();if("heatmap"===i.config.chart.type){var n=i.config.plotOptions.heatmap.colorScale.ranges;s=n.map((function(t){return t.name?t.name:t.from+" - "+t.to})),r=n.map((function(t){return t.color}))}else this.isBarsDistributed&&(s=i.globals.labels.slice());i.config.legend.customLegendItems.length&&(s=i.config.legend.customLegendItems);var o=i.globals.legendFormatter,l=i.config.legend.inverseOrder,h=[];i.globals.seriesGroups.length>1&&i.config.legend.clusterGroupedSeries&&i.globals.seriesGroups.forEach((function(t,e){h[e]=document.createElement("div"),h[e].classList.add("apexcharts-legend-group","apexcharts-legend-group-".concat(e)),"horizontal"===i.config.legend.clusterGroupedSeriesOrientation?i.globals.dom.elLegendWrap.classList.add("apexcharts-legend-group-horizontal"):h[e].classList.add("apexcharts-legend-group-vertical")}));for(var c=function(e){var n,l=o(s[e],{seriesIndex:e,w:i}),c=!1,d=!1;if(i.globals.collapsedSeries.length>0)for(var u=0;u0)for(var g=0;g=0:d<=s.length-1;l?d--:d++)c(d);i.globals.dom.elWrap.addEventListener("click",e.onLegendClick,!0),i.config.legend.onItemHover.highlightDataSeries&&0===i.config.legend.customLegendItems.length&&(i.globals.dom.elWrap.addEventListener("mousemove",e.onLegendHovered,!0),i.globals.dom.elWrap.addEventListener("mouseout",e.onLegendHovered,!0))}},{key:"setLegendWrapXY",value:function(t,e){var i=this.w,a=i.globals.dom.elLegendWrap,s=a.clientHeight,r=0,n=0;if("bottom"===i.config.legend.position)n=i.globals.svgHeight-Math.min(s,i.globals.svgHeight/2)-5;else if("top"===i.config.legend.position){var o=new fa(this.ctx),l=o.dimHelpers.getTitleSubtitleCoords("title").height,h=o.dimHelpers.getTitleSubtitleCoords("subtitle").height;n=(l>0?l-10:0)+(h>0?h-10:0)}a.style.position="absolute",r=r+t+i.config.legend.offsetX,n=n+e+i.config.legend.offsetY,a.style.left=r+"px",a.style.top=n+"px","right"===i.config.legend.position&&(a.style.left="auto",a.style.right=25+i.config.legend.offsetX+"px");["width","height"].forEach((function(t){a.style[t]&&(a.style[t]=parseInt(i.config.legend[t],10)+"px")}))}},{key:"legendAlignHorizontal",value:function(){var t=this.w;t.globals.dom.elLegendWrap.style.right=0;var e=new fa(this.ctx),i=e.dimHelpers.getTitleSubtitleCoords("title"),a=e.dimHelpers.getTitleSubtitleCoords("subtitle"),s=0;"top"===t.config.legend.position&&(s=i.height+a.height+t.config.title.margin+t.config.subtitle.margin-10),this.setLegendWrapXY(20,s)}},{key:"legendAlignVertical",value:function(){var t=this.w,e=this.legendHelpers.getLegendDimensions(),i=0;"left"===t.config.legend.position&&(i=20),"right"===t.config.legend.position&&(i=t.globals.svgWidth-e.clww-10),this.setLegendWrapXY(i,20)}},{key:"onLegendHovered",value:function(t){var e=this.w,i=t.target.classList.contains("apexcharts-legend-series")||t.target.classList.contains("apexcharts-legend-text")||t.target.classList.contains("apexcharts-legend-marker");if("heatmap"===e.config.chart.type||this.isBarsDistributed){if(i){var a=parseInt(t.target.getAttribute("rel"),10)-1;this.ctx.events.fireEvent("legendHover",[this.ctx,a,this.w]),new $i(this.ctx).highlightRangeInSeries(t,t.target)}}else!t.target.classList.contains("apexcharts-inactive-legend")&&i&&new $i(this.ctx).toggleSeriesOnHover(t,t.target)}},{key:"onLegendClick",value:function(t){var e=this.w;if(!e.config.legend.customLegendItems.length&&(t.target.classList.contains("apexcharts-legend-series")||t.target.classList.contains("apexcharts-legend-text")||t.target.classList.contains("apexcharts-legend-marker"))){var i=parseInt(t.target.getAttribute("rel"),10)-1,a="true"===t.target.getAttribute("data:collapsed"),s=this.w.config.chart.events.legendClick;"function"==typeof s&&s(this.ctx,i,this.w),this.ctx.events.fireEvent("legendClick",[this.ctx,i,this.w]);var r=this.w.config.legend.markers.onClick;"function"==typeof r&&t.target.classList.contains("apexcharts-legend-marker")&&(r(this.ctx,i,this.w),this.ctx.events.fireEvent("legendMarkerClick",[this.ctx,i,this.w])),"treemap"!==e.config.chart.type&&"heatmap"!==e.config.chart.type&&!this.isBarsDistributed&&e.config.legend.onItemClick.toggleDataSeries&&this.legendHelpers.toggleDataSeries(i,a)}}}]),t}(),ma=function(){function t(e){i(this,t),this.ctx=e,this.w=e.w;var a=this.w;this.ev=this.w.config.chart.events,this.selectedClass="apexcharts-selected",this.localeValues=this.w.globals.locale.toolbar,this.minX=a.globals.minX,this.maxX=a.globals.maxX}return s(t,[{key:"createToolbar",value:function(){var t=this,e=this.w,i=function(){return document.createElement("div")},a=i();if(a.setAttribute("class","apexcharts-toolbar"),a.style.top=e.config.chart.toolbar.offsetY+"px",a.style.right=3-e.config.chart.toolbar.offsetX+"px",e.globals.dom.elWrap.appendChild(a),this.elZoom=i(),this.elZoomIn=i(),this.elZoomOut=i(),this.elPan=i(),this.elSelection=i(),this.elZoomReset=i(),this.elMenuIcon=i(),this.elMenu=i(),this.elCustomIcons=[],this.t=e.config.chart.toolbar.tools,Array.isArray(this.t.customIcons))for(var s=0;s\n \n \n\n'),n("zoomOut",this.elZoomOut,'\n \n \n\n');var o=function(i){t.t[i]&&e.config.chart[i].enabled&&r.push({el:"zoom"===i?t.elZoom:t.elSelection,icon:"string"==typeof t.t[i]?t.t[i]:"zoom"===i?'\n \n \n \n':'\n \n \n',title:t.localeValues["zoom"===i?"selectionZoom":"selection"],class:"apexcharts-".concat(i,"-icon")})};o("zoom"),o("selection"),this.t.pan&&e.config.chart.zoom.enabled&&r.push({el:this.elPan,icon:"string"==typeof this.t.pan?this.t.pan:'\n \n \n \n \n \n \n \n',title:this.localeValues.pan,class:"apexcharts-pan-icon"}),n("reset",this.elZoomReset,'\n \n \n'),this.t.download&&r.push({el:this.elMenuIcon,icon:"string"==typeof this.t.download?this.t.download:'',title:this.localeValues.menu,class:"apexcharts-menu-icon"});for(var l=0;lthis.wheelDelay&&(this.executeMouseWheelZoom(t),i.globals.lastWheelExecution=a),this.debounceTimer&&clearTimeout(this.debounceTimer),this.debounceTimer=setTimeout((function(){a-i.globals.lastWheelExecution>e.wheelDelay&&(e.executeMouseWheelZoom(t),i.globals.lastWheelExecution=a)}),this.debounceDelay)}},{key:"executeMouseWheelZoom",value:function(t){var e,i=this.w;this.minX=i.globals.isRangeBar?i.globals.minY:i.globals.minX,this.maxX=i.globals.isRangeBar?i.globals.maxY:i.globals.maxX;var a=null===(e=this.gridRect)||void 0===e?void 0:e.getBoundingClientRect();if(a){var s,r,n,o=(t.clientX-a.left)/a.width,l=this.minX,h=this.maxX,c=h-l;if(t.deltaY<0){var d=l+o*c;r=d-(s=.5*c)/2,n=d+s/2}else r=l-(s=1.5*c)/2,n=h+s/2;if(!i.globals.isRangeBar){r=Math.max(r,i.globals.initialMinX),n=Math.min(n,i.globals.initialMaxX);var u=.01*(i.globals.initialMaxX-i.globals.initialMinX);if(n-r0&&i.height>0&&(this.selectionRect.select(!1).resize(!1),this.selectionRect.select({createRot:function(){},updateRot:function(){},createHandle:function(t,e,i,a,s){return"l"===s||"r"===s?t.circle(8).css({"stroke-width":1,stroke:"#333",fill:"#fff"}):t.circle(0)},updateHandle:function(t,e){return t.center(e[0],e[1])}}).resize().on("resize",(function(){var i=e.globals.zoomEnabled?e.config.chart.zoom.type:e.config.chart.selection.type;t.handleMouseUp({zoomtype:i,isResized:!0})})))}}},{key:"preselectedSelection",value:function(){var t=this.w,e=this.xyRatios;if(!t.globals.zoomEnabled)if(void 0!==t.globals.selection&&null!==t.globals.selection)this.drawSelectionRect(u(u({},t.globals.selection),{},{translateX:t.globals.translateX,translateY:t.globals.translateY}));else if(void 0!==t.config.chart.selection.xaxis.min&&void 0!==t.config.chart.selection.xaxis.max){var i=(t.config.chart.selection.xaxis.min-t.globals.minX)/e.xRatio,a=t.globals.gridWidth-(t.globals.maxX-t.config.chart.selection.xaxis.max)/e.xRatio-i;t.globals.isRangeBar&&(i=(t.config.chart.selection.xaxis.min-t.globals.yAxisScale[0].niceMin)/e.invertedYRatio,a=(t.config.chart.selection.xaxis.max-t.config.chart.selection.xaxis.min)/e.invertedYRatio);var s={x:i,y:0,width:a,height:t.globals.gridHeight,translateX:t.globals.translateX,translateY:t.globals.translateY,selectionEnabled:!0};this.drawSelectionRect(s),this.makeSelectionRectDraggable(),"function"==typeof t.config.chart.events.selection&&t.config.chart.events.selection(this.ctx,{xaxis:{min:t.config.chart.selection.xaxis.min,max:t.config.chart.selection.xaxis.max},yaxis:{}})}}},{key:"drawSelectionRect",value:function(t){var e=t.x,i=t.y,a=t.width,s=t.height,r=t.translateX,n=void 0===r?0:r,o=t.translateY,l=void 0===o?0:o,h=this.w,c=this.zoomRect,d=this.selectionRect;if(this.dragged||null!==h.globals.selection){var u={transform:"translate("+n+", "+l+")"};h.globals.zoomEnabled&&this.dragged&&(a<0&&(a=1),c.attr({x:e,y:i,width:a,height:s,fill:h.config.chart.zoom.zoomedArea.fill.color,"fill-opacity":h.config.chart.zoom.zoomedArea.fill.opacity,stroke:h.config.chart.zoom.zoomedArea.stroke.color,"stroke-width":h.config.chart.zoom.zoomedArea.stroke.width,"stroke-opacity":h.config.chart.zoom.zoomedArea.stroke.opacity}),Mi.setAttrs(c.node,u)),h.globals.selectionEnabled&&(d.attr({x:e,y:i,width:a>0?a:0,height:s>0?s:0,fill:h.config.chart.selection.fill.color,"fill-opacity":h.config.chart.selection.fill.opacity,stroke:h.config.chart.selection.stroke.color,"stroke-width":h.config.chart.selection.stroke.width,"stroke-dasharray":h.config.chart.selection.stroke.dashArray,"stroke-opacity":h.config.chart.selection.stroke.opacity}),Mi.setAttrs(d.node,u))}}},{key:"hideSelectionRect",value:function(t){t&&t.attr({x:0,y:0,width:0,height:0})}},{key:"selectionDrawing",value:function(t){var e=t.context,i=t.zoomtype,a=this.w,s=e,r=this.gridRect.getBoundingClientRect(),n=s.startX-1,o=s.startY,l=!1,h=!1,c=s.clientX-r.left-a.globals.barPadForNumericAxis,d=s.clientY-r.top,g=c-n,p=d-o,f={translateX:a.globals.translateX,translateY:a.globals.translateY};return Math.abs(g+n)>a.globals.gridWidth?g=a.globals.gridWidth-n:c<0&&(g=n),n>c&&(l=!0,g=Math.abs(g)),o>d&&(h=!0,p=Math.abs(p)),f=u(u({},f="x"===i?{x:l?n-g:n,y:0,width:g,height:a.globals.gridHeight}:"y"===i?{x:0,y:h?o-p:o,width:a.globals.gridWidth,height:p}:{x:l?n-g:n,y:h?o-p:o,width:g,height:p}),{},{translateX:a.globals.translateX,translateY:a.globals.translateY}),s.drawSelectionRect(f),s.selectionDragging("resizing"),f}},{key:"selectionDragging",value:function(t,e){var i=this,a=this.w;if(e){e.preventDefault();var s=e.detail,r=s.handler,n=s.box,o=n.x,l=n.y;othis.constraints.x2&&(o=this.constraints.x2-n.w),n.y2>this.constraints.y2&&(l=this.constraints.y2-n.h),r.move(o,l);var h=this.xyRatios,c=this.selectionRect,d=0;"resizing"===t&&(d=30);var u=function(t){return parseFloat(c.node.getAttribute(t))},g={x:u("x"),y:u("y"),width:u("width"),height:u("height")};a.globals.selection=g,"function"==typeof a.config.chart.events.selection&&a.globals.selectionEnabled&&(clearTimeout(this.w.globals.selectionResizeTimer),this.w.globals.selectionResizeTimer=window.setTimeout((function(){var t,e,s,r,n=i.gridRect.getBoundingClientRect(),o=c.node.getBoundingClientRect();a.globals.isRangeBar?(t=a.globals.yAxisScale[0].niceMin+(o.left-n.left)*h.invertedYRatio,e=a.globals.yAxisScale[0].niceMin+(o.right-n.left)*h.invertedYRatio,s=0,r=1):(t=a.globals.xAxisScale.niceMin+(o.left-n.left)*h.xRatio,e=a.globals.xAxisScale.niceMin+(o.right-n.left)*h.xRatio,s=a.globals.yAxisScale[0].niceMin+(n.bottom-o.bottom)*h.yRatio[0],r=a.globals.yAxisScale[0].niceMax-(o.top-n.top)*h.yRatio[0]);var l={xaxis:{min:t,max:e},yaxis:{min:s,max:r}};a.config.chart.events.selection(i.ctx,l),a.config.chart.brush.enabled&&void 0!==a.config.chart.events.brushScrolled&&a.config.chart.events.brushScrolled(i.ctx,l)}),d))}}},{key:"selectionDrawn",value:function(t){var e,i,a=t.context,s=t.zoomtype,r=this.w,n=a,o=this.xyRatios,l=this.ctx.toolbar,h=r.globals.zoomEnabled?n.zoomRect.node.getBoundingClientRect():n.selectionRect.node.getBoundingClientRect(),c=n.gridRect.getBoundingClientRect(),d=h.left-c.left-r.globals.barPadForNumericAxis,u=h.right-c.left-r.globals.barPadForNumericAxis,g=h.top-c.top,p=h.bottom-c.top;r.globals.isRangeBar?(e=r.globals.yAxisScale[0].niceMin+d*o.invertedYRatio,i=r.globals.yAxisScale[0].niceMin+u*o.invertedYRatio):(e=r.globals.xAxisScale.niceMin+d*o.xRatio,i=r.globals.xAxisScale.niceMin+u*o.xRatio);var f=[],x=[];if(r.config.yaxis.forEach((function(t,e){var i=r.globals.seriesYAxisMap[e][0],a=r.globals.yAxisScale[e].niceMax-o.yRatio[i]*g,s=r.globals.yAxisScale[e].niceMax-o.yRatio[i]*p;f.push(a),x.push(s)})),n.dragged&&(n.dragX>10||n.dragY>10)&&e!==i)if(r.globals.zoomEnabled){var b=v.clone(r.globals.initialConfig.yaxis),m=v.clone(r.globals.initialConfig.xaxis);if(r.globals.zoomed=!0,r.config.xaxis.convertedCatToNumeric&&(e=Math.floor(e),i=Math.floor(i),e<1&&(e=1,i=r.globals.dataPoints),i-e<2&&(i=e+1)),"xy"!==s&&"x"!==s||(m={min:e,max:i}),"xy"!==s&&"y"!==s||b.forEach((function(t,e){b[e].min=x[e],b[e].max=f[e]})),l){var y=l.getBeforeZoomRange(m,b);y&&(m=y.xaxis?y.xaxis:m,b=y.yaxis?y.yaxis:b)}var w={xaxis:m};r.config.chart.group||(w.yaxis=b),n.ctx.updateHelpers._updateOptions(w,!1,n.w.config.chart.animations.dynamicAnimation.enabled),"function"==typeof r.config.chart.events.zoomed&&l.zoomCallback(m,b)}else if(r.globals.selectionEnabled){var k,A=null;k={min:e,max:i},"xy"!==s&&"y"!==s||(A=v.clone(r.config.yaxis)).forEach((function(t,e){A[e].min=x[e],A[e].max=f[e]})),r.globals.selection=n.selection,"function"==typeof r.config.chart.events.selection&&r.config.chart.events.selection(n.ctx,{xaxis:k,yaxis:A})}}},{key:"panDragging",value:function(t){var e=t.context,i=this.w,a=e;if(void 0!==i.globals.lastClientPosition.x){var s=i.globals.lastClientPosition.x-a.clientX,r=i.globals.lastClientPosition.y-a.clientY;Math.abs(s)>Math.abs(r)&&s>0?this.moveDirection="left":Math.abs(s)>Math.abs(r)&&s<0?this.moveDirection="right":Math.abs(r)>Math.abs(s)&&r>0?this.moveDirection="up":Math.abs(r)>Math.abs(s)&&r<0&&(this.moveDirection="down")}i.globals.lastClientPosition={x:a.clientX,y:a.clientY};var n=i.globals.isRangeBar?i.globals.minY:i.globals.minX,o=i.globals.isRangeBar?i.globals.maxY:i.globals.maxX;a.panScrolled(n,o)}},{key:"panScrolled",value:function(t,e){var i=this.w,a=this.xyRatios,s=v.clone(i.globals.initialConfig.yaxis),r=a.xRatio,n=i.globals.minX,o=i.globals.maxX;i.globals.isRangeBar&&(r=a.invertedYRatio,n=i.globals.minY,o=i.globals.maxY),"left"===this.moveDirection?(t=n+i.globals.gridWidth/15*r,e=o+i.globals.gridWidth/15*r):"right"===this.moveDirection&&(t=n-i.globals.gridWidth/15*r,e=o-i.globals.gridWidth/15*r),i.globals.isRangeBar||(ti.globals.initialMaxX)&&(t=n,e=o);var l={xaxis:{min:t,max:e}};i.config.chart.group||(l.yaxis=s),this.updateScrolledChart(l,t,e)}},{key:"updateScrolledChart",value:function(t,e,i){var a=this.w;if(this.ctx.updateHelpers._updateOptions(t,!1,!1),"function"==typeof a.config.chart.events.scrolled){var s={xaxis:{min:e,max:i}};a.config.chart.events.scrolled(this.ctx,s),this.ctx.events.fireEvent("scrolled",s)}}}]),a}(ma),ya=function(){function t(e){i(this,t),this.w=e.w,this.ttCtx=e,this.ctx=e.ctx}return s(t,[{key:"getNearestValues",value:function(t){var e=t.hoverArea,i=t.elGrid,a=t.clientX,s=t.clientY,r=this.w,n=i.getBoundingClientRect(),o=n.width,l=n.height,h=o/(r.globals.dataPoints-1),c=l/r.globals.dataPoints,d=this.hasBars();!r.globals.comboCharts&&!d||r.config.xaxis.convertedCatToNumeric||(h=o/r.globals.dataPoints);var u=a-n.left-r.globals.barPadForNumericAxis,g=s-n.top;u<0||g<0||u>o||g>l?(e.classList.remove("hovering-zoom"),e.classList.remove("hovering-pan")):r.globals.zoomEnabled?(e.classList.remove("hovering-pan"),e.classList.add("hovering-zoom")):r.globals.panEnabled&&(e.classList.remove("hovering-zoom"),e.classList.add("hovering-pan"));var p=Math.round(u/h),f=Math.floor(g/c);d&&!r.config.xaxis.convertedCatToNumeric&&(p=Math.ceil(u/h),p-=1);var x=null,b=null,m=r.globals.seriesXvalues.map((function(t){return t.filter((function(t){return v.isNumber(t)}))})),y=r.globals.seriesYvalues.map((function(t){return t.filter((function(t){return v.isNumber(t)}))}));if(r.globals.isXNumeric){var w=this.ttCtx.getElGrid().getBoundingClientRect(),k=u*(w.width/o),A=g*(w.height/l);x=(b=this.closestInMultiArray(k,A,m,y)).index,p=b.j,null!==x&&r.globals.hasNullValues&&(m=r.globals.seriesXvalues[x],p=(b=this.closestInArray(k,m)).j)}return r.globals.capturedSeriesIndex=null===x?-1:x,(!p||p<1)&&(p=0),r.globals.isBarHorizontal?r.globals.capturedDataPointIndex=f:r.globals.capturedDataPointIndex=p,{capturedSeries:x,j:r.globals.isBarHorizontal?f:p,hoverX:u,hoverY:g}}},{key:"getFirstActiveXArray",value:function(t){for(var e=this.w,i=0,a=t.map((function(t,e){return t.length>0?e:-1})),s=0;s0)for(var a=0;a *")):this.w.globals.dom.baseEl.querySelectorAll(".apexcharts-series-markers-wrap > *")}},{key:"getAllMarkers",value:function(){var t=this,e=arguments.length>0&&void 0!==arguments[0]&&arguments[0],i=this.w.globals.dom.baseEl.querySelectorAll(".apexcharts-series-markers-wrap");i=f(i),e&&(i=i.filter((function(e){var i=Number(e.getAttribute("data:realIndex"));return-1===t.w.globals.collapsedSeriesIndices.indexOf(i)}))),i.sort((function(t,e){var i=Number(t.getAttribute("data:realIndex")),a=Number(e.getAttribute("data:realIndex"));return ai?-1:0}));var a=[];return i.forEach((function(t){a.push(t.querySelector(".apexcharts-marker"))})),a}},{key:"hasMarkers",value:function(t){return this.getElMarkers(t).length>0}},{key:"getPathFromPoint",value:function(t,e){var i=Number(t.getAttribute("cx")),a=Number(t.getAttribute("cy")),s=t.getAttribute("shape");return new Mi(this.ctx).getMarkerPath(i,a,s,e)}},{key:"getElBars",value:function(){return this.w.globals.dom.baseEl.querySelectorAll(".apexcharts-bar-series, .apexcharts-candlestick-series, .apexcharts-boxPlot-series, .apexcharts-rangebar-series")}},{key:"hasBars",value:function(){return this.getElBars().length>0}},{key:"getHoverMarkerSize",value:function(t){var e=this.w,i=e.config.markers.hover.size;return void 0===i&&(i=e.globals.markers.size[t]+e.config.markers.hover.sizeOffset),i}},{key:"toggleAllTooltipSeriesGroups",value:function(t){var e=this.w,i=this.ttCtx;0===i.allTooltipSeriesGroups.length&&(i.allTooltipSeriesGroups=e.globals.dom.baseEl.querySelectorAll(".apexcharts-tooltip-series-group"));for(var a=i.allTooltipSeriesGroups,s=0;s ').concat(i.attrs.name,""),e+="
".concat(i.val,"
")})),m.innerHTML=t+"",v.innerHTML=e+""};n?l.globals.seriesGoals[e][i]&&Array.isArray(l.globals.seriesGoals[e][i])?y():(m.innerHTML="",v.innerHTML=""):y()}else m.innerHTML="",v.innerHTML="";null!==p&&(a[e].querySelector(".apexcharts-tooltip-text-z-label").innerHTML=l.config.tooltip.z.title,a[e].querySelector(".apexcharts-tooltip-text-z-value").innerHTML=void 0!==p?p:"");if(n&&f[0]){if(l.config.tooltip.hideEmptySeries){var w=a[e].querySelector(".apexcharts-tooltip-marker"),k=a[e].querySelector(".apexcharts-tooltip-text");0==parseFloat(c)?(w.style.display="none",k.style.display="none"):(w.style.display="block",k.style.display="block")}null==c||l.globals.ancillaryCollapsedSeriesIndices.indexOf(e)>-1||l.globals.collapsedSeriesIndices.indexOf(e)>-1||Array.isArray(h.tConfig.enabledOnSeries)&&-1===h.tConfig.enabledOnSeries.indexOf(e)?f[0].parentNode.style.display="none":f[0].parentNode.style.display=l.config.tooltip.items.display}else Array.isArray(h.tConfig.enabledOnSeries)&&-1===h.tConfig.enabledOnSeries.indexOf(e)&&(f[0].parentNode.style.display="none")}},{key:"toggleActiveInactiveSeries",value:function(t,e){var i=this.w;if(t)this.tooltipUtil.toggleAllTooltipSeriesGroups("enable");else{this.tooltipUtil.toggleAllTooltipSeriesGroups("disable");var a=i.globals.dom.baseEl.querySelector(".apexcharts-tooltip-series-group-".concat(e));a&&(a.classList.add("apexcharts-active"),a.style.display=i.config.tooltip.items.display)}}},{key:"getValuesToPrint",value:function(t){var e=t.i,i=t.j,a=this.w,s=this.ctx.series.filteredSeriesX(),r="",n="",o=null,l=null,h={series:a.globals.series,seriesIndex:e,dataPointIndex:i,w:a},c=a.globals.ttZFormatter;null===i?l=a.globals.series[e]:a.globals.isXNumeric&&"treemap"!==a.config.chart.type?(r=s[e][i],0===s[e].length&&(r=s[this.tooltipUtil.getFirstActiveXArray(s)][i])):r=new Ji(this.ctx).isFormatXY()?void 0!==a.config.series[e].data[i]?a.config.series[e].data[i].x:"":void 0!==a.globals.labels[i]?a.globals.labels[i]:"";var d=r;a.globals.isXNumeric&&"datetime"===a.config.xaxis.type?r=new Xi(this.ctx).xLabelFormat(a.globals.ttKeyFormatter,d,d,{i:void 0,dateFormatter:new zi(this.ctx).formatDate,w:this.w}):r=a.globals.isBarHorizontal?a.globals.yLabelFormatters[0](d,h):a.globals.xLabelFormatter(d,h);return void 0!==a.config.tooltip.x.formatter&&(r=a.globals.ttKeyFormatter(d,h)),a.globals.seriesZ.length>0&&a.globals.seriesZ[e].length>0&&(o=c(a.globals.seriesZ[e][i],a)),n="function"==typeof a.config.xaxis.tooltip.formatter?a.globals.xaxisTooltipFormatter(d,h):r,{val:Array.isArray(l)?l.join(" "):l,xVal:Array.isArray(r)?r.join(" "):r,xAxisTTVal:Array.isArray(n)?n.join(" "):n,zVal:o}}},{key:"handleCustomTooltip",value:function(t){var e=t.i,i=t.j,a=t.y1,s=t.y2,r=t.w,n=this.ttCtx.getElTooltip(),o=r.config.tooltip.custom;Array.isArray(o)&&o[e]&&(o=o[e]);var l=o({ctx:this.ctx,series:r.globals.series,seriesIndex:e,dataPointIndex:i,y1:a,y2:s,w:r});"string"==typeof l||"number"==typeof l?n.innerHTML=l:(l instanceof Element||"string"==typeof l.nodeName)&&(n.innerHTML="",n.appendChild(l.cloneNode(!0)))}}]),t}(),ka=function(){function t(e){i(this,t),this.ttCtx=e,this.ctx=e.ctx,this.w=e.w}return s(t,[{key:"moveXCrosshairs",value:function(t){var e=arguments.length>1&&void 0!==arguments[1]?arguments[1]:null,i=this.ttCtx,a=this.w,s=i.getElXCrosshairs(),r=t-i.xcrosshairsWidth/2,n=a.globals.labels.slice().length;if(null!==e&&(r=a.globals.gridWidth/n*e),null===s||a.globals.isBarHorizontal||(s.setAttribute("x",r),s.setAttribute("x1",r),s.setAttribute("x2",r),s.setAttribute("y2",a.globals.gridHeight),s.classList.add("apexcharts-active")),r<0&&(r=0),r>a.globals.gridWidth&&(r=a.globals.gridWidth),i.isXAxisTooltipEnabled){var o=r;"tickWidth"!==a.config.xaxis.crosshairs.width&&"barWidth"!==a.config.xaxis.crosshairs.width||(o=r+i.xcrosshairsWidth/2),this.moveXAxisTooltip(o)}}},{key:"moveYCrosshairs",value:function(t){var e=this.ttCtx;null!==e.ycrosshairs&&Mi.setAttrs(e.ycrosshairs,{y1:t,y2:t}),null!==e.ycrosshairsHidden&&Mi.setAttrs(e.ycrosshairsHidden,{y1:t,y2:t})}},{key:"moveXAxisTooltip",value:function(t){var e=this.w,i=this.ttCtx;if(null!==i.xaxisTooltip&&0!==i.xcrosshairsWidth){i.xaxisTooltip.classList.add("apexcharts-active");var a=i.xaxisOffY+e.config.xaxis.tooltip.offsetY+e.globals.translateY+1+e.config.xaxis.offsetY;if(t-=i.xaxisTooltip.getBoundingClientRect().width/2,!isNaN(t)){t+=e.globals.translateX;var s;s=new Mi(this.ctx).getTextRects(i.xaxisTooltipText.innerHTML),i.xaxisTooltipText.style.minWidth=s.width+"px",i.xaxisTooltip.style.left=t+"px",i.xaxisTooltip.style.top=a+"px"}}}},{key:"moveYAxisTooltip",value:function(t){var e=this.w,i=this.ttCtx;null===i.yaxisTTEls&&(i.yaxisTTEls=e.globals.dom.baseEl.querySelectorAll(".apexcharts-yaxistooltip"));var a=parseInt(i.ycrosshairsHidden.getAttribute("y1"),10),s=e.globals.translateY+a,r=i.yaxisTTEls[t].getBoundingClientRect(),n=r.height,o=e.globals.translateYAxisX[t]-2;e.config.yaxis[t].opposite&&(o-=r.width),s-=n/2,-1===e.globals.ignoreYAxisIndexes.indexOf(t)&&s>0&&s2&&void 0!==arguments[2]?arguments[2]:null,a=this.w,s=this.ttCtx,r=s.getElTooltip(),n=s.tooltipRect,o=null!==i?parseFloat(i):1,l=parseFloat(t)+o+5,h=parseFloat(e)+o/2;if(l>a.globals.gridWidth/2&&(l=l-n.ttWidth-o-10),l>a.globals.gridWidth-n.ttWidth-10&&(l=a.globals.gridWidth-n.ttWidth),l<-20&&(l=-20),a.config.tooltip.followCursor){var c=s.getElGrid().getBoundingClientRect();(l=s.e.clientX-c.left)>a.globals.gridWidth/2&&(l-=s.tooltipRect.ttWidth),(h=s.e.clientY+a.globals.translateY-c.top)>a.globals.gridHeight/2&&(h-=s.tooltipRect.ttHeight)}else a.globals.isBarHorizontal||n.ttHeight/2+h>a.globals.gridHeight&&(h=a.globals.gridHeight-n.ttHeight+a.globals.translateY);isNaN(l)||(l+=a.globals.translateX,r.style.left=l+"px",r.style.top=h+"px")}},{key:"moveMarkers",value:function(t,e){var i=this.w,a=this.ttCtx;if(i.globals.markers.size[t]>0)for(var s=i.globals.dom.baseEl.querySelectorAll(" .apexcharts-series[data\\:realIndex='".concat(t,"'] .apexcharts-marker")),r=0;r0){var g=u.getAttribute("shape"),p=l.getMarkerPath(s,r,g,1.5*c);u.setAttribute("d",p)}this.moveXCrosshairs(s),o.fixedTooltip||this.moveTooltip(s,r,c)}}},{key:"moveDynamicPointsOnHover",value:function(t){var e,i=this.ttCtx,a=i.w,s=0,r=0,n=a.globals.pointsArray,o=new $i(this.ctx),l=new Mi(this.ctx);e=o.getActiveConfigSeriesIndex("asc",["line","area","scatter","bubble"]);var h=i.tooltipUtil.getHoverMarkerSize(e);if(n[e]&&(s=n[e][t][0],r=n[e][t][1]),!isNaN(s)){var c=i.tooltipUtil.getAllMarkers();if(c.length)for(var d=0;d0){var b=l.getMarkerPath(s,g,f,h);c[d].setAttribute("d",b)}else c[d].setAttribute("d","")}}this.moveXCrosshairs(s),i.fixedTooltip||this.moveTooltip(s,r||a.globals.gridHeight,h)}}},{key:"moveStickyTooltipOverBars",value:function(t,e){var i=this.w,a=this.ttCtx,s=i.globals.columnSeries?i.globals.columnSeries.length:i.globals.series.length;i.config.chart.stacked&&(s=i.globals.barGroups.length);var r=s>=2&&s%2==0?Math.floor(s/2):Math.floor(s/2)+1;i.globals.isBarHorizontal&&(r=new $i(this.ctx).getActiveConfigSeriesIndex("desc")+1);var n=i.globals.dom.baseEl.querySelector(".apexcharts-bar-series .apexcharts-series[rel='".concat(r,"'] path[j='").concat(t,"'], .apexcharts-candlestick-series .apexcharts-series[rel='").concat(r,"'] path[j='").concat(t,"'], .apexcharts-boxPlot-series .apexcharts-series[rel='").concat(r,"'] path[j='").concat(t,"'], .apexcharts-rangebar-series .apexcharts-series[rel='").concat(r,"'] path[j='").concat(t,"']"));n||"number"!=typeof e||(n=i.globals.dom.baseEl.querySelector(".apexcharts-bar-series .apexcharts-series[data\\:realIndex='".concat(e,"'] path[j='").concat(t,"'],\n .apexcharts-candlestick-series .apexcharts-series[data\\:realIndex='").concat(e,"'] path[j='").concat(t,"'],\n .apexcharts-boxPlot-series .apexcharts-series[data\\:realIndex='").concat(e,"'] path[j='").concat(t,"'],\n .apexcharts-rangebar-series .apexcharts-series[data\\:realIndex='").concat(e,"'] path[j='").concat(t,"']")));var o=n?parseFloat(n.getAttribute("cx")):0,l=n?parseFloat(n.getAttribute("cy")):0,h=n?parseFloat(n.getAttribute("barWidth")):0,c=a.getElGrid().getBoundingClientRect(),d=n&&(n.classList.contains("apexcharts-candlestick-area")||n.classList.contains("apexcharts-boxPlot-area"));i.globals.isXNumeric?(n&&!d&&(o-=s%2!=0?h/2:0),n&&d&&(o-=h/2)):i.globals.isBarHorizontal||(o=a.xAxisTicksPositions[t-1]+a.dataPointsDividedWidth/2,isNaN(o)&&(o=a.xAxisTicksPositions[t]-a.dataPointsDividedWidth/2)),i.globals.isBarHorizontal?l-=a.tooltipRect.ttHeight:i.config.tooltip.followCursor?l=a.e.clientY-c.top-a.tooltipRect.ttHeight/2:l+a.tooltipRect.ttHeight+15>i.globals.gridHeight&&(l=i.globals.gridHeight),i.globals.isBarHorizontal||this.moveXCrosshairs(o),a.fixedTooltip||this.moveTooltip(o,l||i.globals.gridHeight)}}]),t}(),Aa=function(){function t(e){i(this,t),this.w=e.w,this.ttCtx=e,this.ctx=e.ctx,this.tooltipPosition=new ka(e)}return s(t,[{key:"drawDynamicPoints",value:function(){var t=this.w,e=new Mi(this.ctx),i=new Vi(this.ctx),a=t.globals.dom.baseEl.querySelectorAll(".apexcharts-series");a=f(a),t.config.chart.stacked&&a.sort((function(t,e){return parseFloat(t.getAttribute("data:realIndex"))-parseFloat(e.getAttribute("data:realIndex"))}));for(var s=0;s2&&void 0!==arguments[2]?arguments[2]:null,a=arguments.length>3&&void 0!==arguments[3]?arguments[3]:null,s=this.w;"bubble"!==s.config.chart.type&&this.newPointSize(t,e);var r=e.getAttribute("cx"),n=e.getAttribute("cy");if(null!==i&&null!==a&&(r=i,n=a),this.tooltipPosition.moveXCrosshairs(r),!this.fixedTooltip){if("radar"===s.config.chart.type){var o=this.ttCtx.getElGrid().getBoundingClientRect();r=this.ttCtx.e.clientX-o.left}this.tooltipPosition.moveTooltip(r,n,s.config.markers.hover.size)}}},{key:"enlargePoints",value:function(t){for(var e=this.w,i=this,a=this.ttCtx,s=t,r=e.globals.dom.baseEl.querySelectorAll(".apexcharts-series:not(.apexcharts-series-collapsed) .apexcharts-marker"),n=e.config.markers.hover.size,o=0;o0){var a=this.ttCtx.tooltipUtil.getPathFromPoint(t[e],i);t[e].setAttribute("d",a)}else t[e].setAttribute("d","M0,0")}}}]),t}(),Ca=function(){function t(e){i(this,t),this.w=e.w;var a=this.w;this.ttCtx=e,this.isVerticalGroupedRangeBar=!a.globals.isBarHorizontal&&"rangeBar"===a.config.chart.type&&a.config.plotOptions.bar.rangeBarGroupRows}return s(t,[{key:"getAttr",value:function(t,e){return parseFloat(t.target.getAttribute(e))}},{key:"handleHeatTreeTooltip",value:function(t){var e=t.e,i=t.opt,a=t.x,s=t.y,r=t.type,n=this.ttCtx,o=this.w;if(e.target.classList.contains("apexcharts-".concat(r,"-rect"))){var l=this.getAttr(e,"i"),h=this.getAttr(e,"j"),c=this.getAttr(e,"cx"),d=this.getAttr(e,"cy"),u=this.getAttr(e,"width"),g=this.getAttr(e,"height");if(n.tooltipLabels.drawSeriesTexts({ttItems:i.ttItems,i:l,j:h,shared:!1,e:e}),o.globals.capturedSeriesIndex=l,o.globals.capturedDataPointIndex=h,a=c+n.tooltipRect.ttWidth/2+u,s=d+n.tooltipRect.ttHeight/2-g/2,n.tooltipPosition.moveXCrosshairs(c+u/2),a>o.globals.gridWidth/2&&(a=c-n.tooltipRect.ttWidth/2+u),n.w.config.tooltip.followCursor){var p=o.globals.dom.elWrap.getBoundingClientRect();a=o.globals.clientX-p.left-(a>o.globals.gridWidth/2?n.tooltipRect.ttWidth:0),s=o.globals.clientY-p.top-(s>o.globals.gridHeight/2?n.tooltipRect.ttHeight:0)}}return{x:a,y:s}}},{key:"handleMarkerTooltip",value:function(t){var e,i,a=t.e,s=t.opt,r=t.x,n=t.y,o=this.w,l=this.ttCtx;if(a.target.classList.contains("apexcharts-marker")){var h=parseInt(s.paths.getAttribute("cx"),10),c=parseInt(s.paths.getAttribute("cy"),10),d=parseFloat(s.paths.getAttribute("val"));if(i=parseInt(s.paths.getAttribute("rel"),10),e=parseInt(s.paths.parentNode.parentNode.parentNode.getAttribute("rel"),10)-1,l.intersect){var u=v.findAncestor(s.paths,"apexcharts-series");u&&(e=parseInt(u.getAttribute("data:realIndex"),10))}if(l.tooltipLabels.drawSeriesTexts({ttItems:s.ttItems,i:e,j:i,shared:!l.showOnIntersect&&o.config.tooltip.shared,e:a}),"mouseup"===a.type&&l.markerClick(a,e,i),o.globals.capturedSeriesIndex=e,o.globals.capturedDataPointIndex=i,r=h,n=c+o.globals.translateY-1.4*l.tooltipRect.ttHeight,l.w.config.tooltip.followCursor){var g=l.getElGrid().getBoundingClientRect();n=l.e.clientY+o.globals.translateY-g.top}d<0&&(n=c),l.marker.enlargeCurrentPoint(i,s.paths,r,n)}return{x:r,y:n}}},{key:"handleBarTooltip",value:function(t){var e,i,a=t.e,s=t.opt,r=this.w,n=this.ttCtx,o=n.getElTooltip(),l=0,h=0,c=0,d=this.getBarTooltipXY({e:a,opt:s});if(null!==d.j||0!==d.barHeight||0!==d.barWidth){e=d.i;var u=d.j;if(r.globals.capturedSeriesIndex=e,r.globals.capturedDataPointIndex=u,r.globals.isBarHorizontal&&n.tooltipUtil.hasBars()||!r.config.tooltip.shared?(h=d.x,c=d.y,i=Array.isArray(r.config.stroke.width)?r.config.stroke.width[e]:r.config.stroke.width,l=h):r.globals.comboCharts||r.config.tooltip.shared||(l/=2),isNaN(c)&&(c=r.globals.svgHeight-n.tooltipRect.ttHeight),parseInt(s.paths.parentNode.getAttribute("data:realIndex"),10),h+n.tooltipRect.ttWidth>r.globals.gridWidth?h-=n.tooltipRect.ttWidth:h<0&&(h=0),n.w.config.tooltip.followCursor){var g=n.getElGrid().getBoundingClientRect();c=n.e.clientY-g.top}null===n.tooltip&&(n.tooltip=r.globals.dom.baseEl.querySelector(".apexcharts-tooltip")),r.config.tooltip.shared||(r.globals.comboBarCount>0?n.tooltipPosition.moveXCrosshairs(l+i/2):n.tooltipPosition.moveXCrosshairs(l)),!n.fixedTooltip&&(!r.config.tooltip.shared||r.globals.isBarHorizontal&&n.tooltipUtil.hasBars())&&(c=c+r.globals.translateY-n.tooltipRect.ttHeight/2,o.style.left=h+r.globals.translateX+"px",o.style.top=c+"px")}}},{key:"getBarTooltipXY",value:function(t){var e=this,i=t.e,a=t.opt,s=this.w,r=null,n=this.ttCtx,o=0,l=0,h=0,c=0,d=0,u=i.target.classList;if(u.contains("apexcharts-bar-area")||u.contains("apexcharts-candlestick-area")||u.contains("apexcharts-boxPlot-area")||u.contains("apexcharts-rangebar-area")){var g=i.target,p=g.getBoundingClientRect(),f=a.elGrid.getBoundingClientRect(),x=p.height;d=p.height;var b=p.width,m=parseInt(g.getAttribute("cx"),10),v=parseInt(g.getAttribute("cy"),10);c=parseFloat(g.getAttribute("barWidth"));var y="touchmove"===i.type?i.touches[0].clientX:i.clientX;r=parseInt(g.getAttribute("j"),10),o=parseInt(g.parentNode.getAttribute("rel"),10)-1;var w=g.getAttribute("data-range-y1"),k=g.getAttribute("data-range-y2");s.globals.comboCharts&&(o=parseInt(g.parentNode.getAttribute("data:realIndex"),10));var A=function(t){return s.globals.isXNumeric?m-b/2:e.isVerticalGroupedRangeBar?m+b/2:m-n.dataPointsDividedWidth+b/2},C=function(){return v-n.dataPointsDividedHeight+x/2-n.tooltipRect.ttHeight/2};n.tooltipLabels.drawSeriesTexts({ttItems:a.ttItems,i:o,j:r,y1:w?parseInt(w,10):null,y2:k?parseInt(k,10):null,shared:!n.showOnIntersect&&s.config.tooltip.shared,e:i}),s.config.tooltip.followCursor?s.globals.isBarHorizontal?(l=y-f.left+15,h=C()):(l=A(),h=i.clientY-f.top-n.tooltipRect.ttHeight/2-15):s.globals.isBarHorizontal?((l=m)0&&i.setAttribute("width",e.xcrosshairsWidth)}},{key:"handleYCrosshair",value:function(){var t=this.w,e=this.ttCtx;e.ycrosshairs=t.globals.dom.baseEl.querySelector(".apexcharts-ycrosshairs"),e.ycrosshairsHidden=t.globals.dom.baseEl.querySelector(".apexcharts-ycrosshairs-hidden")}},{key:"drawYaxisTooltipText",value:function(t,e,i){var a=this.ttCtx,s=this.w,r=s.globals,n=r.seriesYAxisMap[t];if(a.yaxisTooltips[t]&&n.length>0){var o=r.yLabelFormatters[t],l=a.getElGrid().getBoundingClientRect(),h=n[0],c=0;i.yRatio.length>1&&(c=h);var d=(e-l.top)*i.yRatio[c],u=r.maxYArr[h]-r.minYArr[h],g=r.minYArr[h]+(u-d);s.config.yaxis[t].reversed&&(g=r.maxYArr[h]-(u-d)),a.tooltipPosition.moveYCrosshairs(e-l.top),a.yaxisTooltipText[t].innerHTML=o(g),a.tooltipPosition.moveYAxisTooltip(t)}}}]),t}(),La=function(){function t(e){i(this,t),this.ctx=e,this.w=e.w;var a=this.w;this.tConfig=a.config.tooltip,this.tooltipUtil=new ya(this),this.tooltipLabels=new wa(this),this.tooltipPosition=new ka(this),this.marker=new Aa(this),this.intersect=new Ca(this),this.axesTooltip=new Sa(this),this.showOnIntersect=this.tConfig.intersect,this.showTooltipTitle=this.tConfig.x.show,this.fixedTooltip=this.tConfig.fixed.enabled,this.xaxisTooltip=null,this.yaxisTTEls=null,this.isBarShared=!a.globals.isBarHorizontal&&this.tConfig.shared,this.lastHoverTime=Date.now()}return s(t,[{key:"getElTooltip",value:function(t){return t||(t=this),t.w.globals.dom.baseEl?t.w.globals.dom.baseEl.querySelector(".apexcharts-tooltip"):null}},{key:"getElXCrosshairs",value:function(){return this.w.globals.dom.baseEl.querySelector(".apexcharts-xcrosshairs")}},{key:"getElGrid",value:function(){return this.w.globals.dom.baseEl.querySelector(".apexcharts-grid")}},{key:"drawTooltip",value:function(t){var e=this.w;this.xyRatios=t,this.isXAxisTooltipEnabled=e.config.xaxis.tooltip.enabled&&e.globals.axisCharts,this.yaxisTooltips=e.config.yaxis.map((function(t,i){return!!(t.show&&t.tooltip.enabled&&e.globals.axisCharts)})),this.allTooltipSeriesGroups=[],e.globals.axisCharts||(this.showTooltipTitle=!1);var i=document.createElement("div");if(i.classList.add("apexcharts-tooltip"),e.config.tooltip.cssClass&&i.classList.add(e.config.tooltip.cssClass),i.classList.add("apexcharts-theme-".concat(this.tConfig.theme||"light")),e.globals.dom.elWrap.appendChild(i),e.globals.axisCharts){this.axesTooltip.drawXaxisTooltip(),this.axesTooltip.drawYaxisTooltip(),this.axesTooltip.setXCrosshairWidth(),this.axesTooltip.handleYCrosshair();var a=new Ki(this.ctx);this.xAxisTicksPositions=a.getXAxisTicksPositions()}if(!e.globals.comboCharts&&!this.tConfig.intersect&&"rangeBar"!==e.config.chart.type||this.tConfig.shared||(this.showOnIntersect=!0),0!==e.config.markers.size&&0!==e.globals.markers.largestSize||this.marker.drawDynamicPoints(this),e.globals.collapsedSeries.length!==e.globals.series.length){this.dataPointsDividedHeight=e.globals.gridHeight/e.globals.dataPoints,this.dataPointsDividedWidth=e.globals.gridWidth/e.globals.dataPoints,this.showTooltipTitle&&(this.tooltipTitle=document.createElement("div"),this.tooltipTitle.classList.add("apexcharts-tooltip-title"),this.tooltipTitle.style.fontFamily=this.tConfig.style.fontFamily||e.config.chart.fontFamily,this.tooltipTitle.style.fontSize=this.tConfig.style.fontSize,i.appendChild(this.tooltipTitle));var s=e.globals.series.length;(e.globals.xyCharts||e.globals.comboCharts)&&this.tConfig.shared&&(s=this.showOnIntersect?1:e.globals.series.length),this.legendLabels=e.globals.dom.baseEl.querySelectorAll(".apexcharts-legend-text"),this.ttItems=this.createTTElements(s),this.addSVGEvents()}}},{key:"createTTElements",value:function(t){for(var e=this,i=this.w,a=[],s=this.getElTooltip(),r=function(r){var n=document.createElement("div");n.classList.add("apexcharts-tooltip-series-group","apexcharts-tooltip-series-group-".concat(r)),n.style.order=i.config.tooltip.inverseOrder?t-r:r+1;var o=document.createElement("span");o.classList.add("apexcharts-tooltip-marker"),i.config.tooltip.fillSeriesColor?o.style.backgroundColor=i.globals.colors[r]:o.style.color=i.globals.colors[r];var l=i.config.markers.shape,h=l;Array.isArray(l)&&(h=l[r]),o.setAttribute("shape",h),n.appendChild(o);var c=document.createElement("div");c.classList.add("apexcharts-tooltip-text"),c.style.fontFamily=e.tConfig.style.fontFamily||i.config.chart.fontFamily,c.style.fontSize=e.tConfig.style.fontSize,["y","goals","z"].forEach((function(t){var e=document.createElement("div");e.classList.add("apexcharts-tooltip-".concat(t,"-group"));var i=document.createElement("span");i.classList.add("apexcharts-tooltip-text-".concat(t,"-label")),e.appendChild(i);var a=document.createElement("span");a.classList.add("apexcharts-tooltip-text-".concat(t,"-value")),e.appendChild(a),c.appendChild(e)})),n.appendChild(c),s.appendChild(n),a.push(n)},n=0;n0&&this.addPathsEventListeners(g,c),this.tooltipUtil.hasBars()&&!this.tConfig.shared&&this.addDatapointEventsListeners(c)}}},{key:"drawFixedTooltipRect",value:function(){var t=this.w,e=this.getElTooltip(),i=e.getBoundingClientRect(),a=i.width+10,s=i.height+10,r=this.tConfig.fixed.offsetX,n=this.tConfig.fixed.offsetY,o=this.tConfig.fixed.position.toLowerCase();return o.indexOf("right")>-1&&(r=r+t.globals.svgWidth-a+10),o.indexOf("bottom")>-1&&(n=n+t.globals.svgHeight-s-10),e.style.left=r+"px",e.style.top=n+"px",{x:r,y:n,ttWidth:a,ttHeight:s}}},{key:"addDatapointEventsListeners",value:function(t){var e=this.w.globals.dom.baseEl.querySelectorAll(".apexcharts-series-markers .apexcharts-marker, .apexcharts-bar-area, .apexcharts-candlestick-area, .apexcharts-boxPlot-area, .apexcharts-rangebar-area");this.addPathsEventListeners(e,t)}},{key:"addPathsEventListeners",value:function(t,e){for(var i=this,a=function(a){var s={paths:t[a],tooltipEl:e.tooltipEl,tooltipY:e.tooltipY,tooltipX:e.tooltipX,elGrid:e.elGrid,hoverArea:e.hoverArea,ttItems:e.ttItems};["mousemove","mouseup","touchmove","mouseout","touchend"].map((function(e){return t[a].addEventListener(e,i.onSeriesHover.bind(i,s),{capture:!1,passive:!0})}))},s=0;s=20?this.seriesHover(t,e):(clearTimeout(this.seriesHoverTimeout),this.seriesHoverTimeout=setTimeout((function(){i.seriesHover(t,e)}),20-a))}},{key:"seriesHover",value:function(t,e){var i=this;this.lastHoverTime=Date.now();var a=[],s=this.w;s.config.chart.group&&(a=this.ctx.getGroupedCharts()),s.globals.axisCharts&&(s.globals.minX===-1/0&&s.globals.maxX===1/0||0===s.globals.dataPoints)||(a.length?a.forEach((function(a){var s=i.getElTooltip(a),r={paths:t.paths,tooltipEl:s,tooltipY:t.tooltipY,tooltipX:t.tooltipX,elGrid:t.elGrid,hoverArea:t.hoverArea,ttItems:a.w.globals.tooltip.ttItems};a.w.globals.minX===i.w.globals.minX&&a.w.globals.maxX===i.w.globals.maxX&&a.w.globals.tooltip.seriesHoverByContext({chartCtx:a,ttCtx:a.w.globals.tooltip,opt:r,e:e})})):this.seriesHoverByContext({chartCtx:this.ctx,ttCtx:this.w.globals.tooltip,opt:t,e:e}))}},{key:"seriesHoverByContext",value:function(t){var e=t.chartCtx,i=t.ttCtx,a=t.opt,s=t.e,r=e.w,n=this.getElTooltip(e);if(n){if(i.tooltipRect={x:0,y:0,ttWidth:n.getBoundingClientRect().width,ttHeight:n.getBoundingClientRect().height},i.e=s,i.tooltipUtil.hasBars()&&!r.globals.comboCharts&&!i.isBarShared)if(this.tConfig.onDatasetHover.highlightDataSeries)new $i(e).toggleSeriesOnHover(s,s.target.parentNode);r.globals.axisCharts?i.axisChartsTooltips({e:s,opt:a,tooltipRect:i.tooltipRect}):i.nonAxisChartsTooltips({e:s,opt:a,tooltipRect:i.tooltipRect}),i.fixedTooltip&&i.drawFixedTooltipRect()}}},{key:"axisChartsTooltips",value:function(t){var e,i,a=t.e,s=t.opt,r=this.w,n=s.elGrid.getBoundingClientRect(),o="touchmove"===a.type?a.touches[0].clientX:a.clientX,l="touchmove"===a.type?a.touches[0].clientY:a.clientY;if(this.clientY=l,this.clientX=o,r.globals.capturedSeriesIndex=-1,r.globals.capturedDataPointIndex=-1,ln.top+n.height)this.handleMouseOut(s);else{if(Array.isArray(this.tConfig.enabledOnSeries)&&!r.config.tooltip.shared){var h=parseInt(s.paths.getAttribute("index"),10);if(this.tConfig.enabledOnSeries.indexOf(h)<0)return void this.handleMouseOut(s)}var c=this.getElTooltip(),d=this.getElXCrosshairs(),u=[];r.config.chart.group&&(u=this.ctx.getSyncedCharts());var g=r.globals.xyCharts||"bar"===r.config.chart.type&&!r.globals.isBarHorizontal&&this.tooltipUtil.hasBars()&&this.tConfig.shared||r.globals.comboCharts&&this.tooltipUtil.hasBars();if("mousemove"===a.type||"touchmove"===a.type||"mouseup"===a.type){if(r.globals.collapsedSeries.length+r.globals.ancillaryCollapsedSeries.length===r.globals.series.length)return;null!==d&&d.classList.add("apexcharts-active");var p=this.yaxisTooltips.filter((function(t){return!0===t}));if(null!==this.ycrosshairs&&p.length&&this.ycrosshairs.classList.add("apexcharts-active"),g&&!this.showOnIntersect||u.length>1)this.handleStickyTooltip(a,o,l,s);else if("heatmap"===r.config.chart.type||"treemap"===r.config.chart.type){var f=this.intersect.handleHeatTreeTooltip({e:a,opt:s,x:e,y:i,type:r.config.chart.type});e=f.x,i=f.y,c.style.left=e+"px",c.style.top=i+"px"}else this.tooltipUtil.hasBars()&&this.intersect.handleBarTooltip({e:a,opt:s}),this.tooltipUtil.hasMarkers()&&this.intersect.handleMarkerTooltip({e:a,opt:s,x:e,y:i});if(this.yaxisTooltips.length)for(var x=0;xl.width)this.handleMouseOut(a);else if(null!==o)this.handleStickyCapturedSeries(t,o,a,n);else if(this.tooltipUtil.isXoverlap(n)||s.globals.isBarHorizontal){var h=s.globals.series.findIndex((function(t,e){return!s.globals.collapsedSeriesIndices.includes(e)}));this.create(t,this,h,n,a.ttItems)}}},{key:"handleStickyCapturedSeries",value:function(t,e,i,a){var s=this.w;if(!this.tConfig.shared&&null===s.globals.series[e][a])return void this.handleMouseOut(i);if(void 0!==s.globals.series[e][a])this.tConfig.shared&&this.tooltipUtil.isXoverlap(a)&&this.tooltipUtil.isInitialSeriesSameLen()?this.create(t,this,e,a,i.ttItems):this.create(t,this,e,a,i.ttItems,!1);else if(this.tooltipUtil.isXoverlap(a)){var r=s.globals.series.findIndex((function(t,e){return!s.globals.collapsedSeriesIndices.includes(e)}));this.create(t,this,r,a,i.ttItems)}}},{key:"deactivateHoverFilter",value:function(){for(var t=this.w,e=new Mi(this.ctx),i=t.globals.dom.Paper.find(".apexcharts-bar-area"),a=0;a5&&void 0!==arguments[5]?arguments[5]:null,A=this.w,C=e;"mouseup"===t.type&&this.markerClick(t,i,a),null===k&&(k=this.tConfig.shared);var S=this.tooltipUtil.hasMarkers(i),L=this.tooltipUtil.getElBars(),M=function(){A.globals.markers.largestSize>0?C.marker.enlargePoints(a):C.tooltipPosition.moveDynamicPointsOnHover(a)};if(A.config.legend.tooltipHoverFormatter){var P=A.config.legend.tooltipHoverFormatter,I=Array.from(this.legendLabels);I.forEach((function(t){var e=t.getAttribute("data:default-text");t.innerHTML=decodeURIComponent(e)}));for(var T=0;T0)){var H=new Mi(this.ctx),O=A.globals.dom.Paper.find(".apexcharts-bar-area[j='".concat(a,"']"));this.deactivateHoverFilter(),C.tooltipUtil.getAllMarkers(!0).length&&!this.barSeriesHeight&&M(),C.tooltipPosition.moveStickyTooltipOverBars(a,i);for(var F=0;F0&&i.config.plotOptions.bar.hideZeroBarsWhenGrouped&&(g-=c*A)),k){g=g+u.height/2-m/2-2}var S=i.globals.series[a][s]<0,L=l;switch(this.barCtx.isReversed&&(L=l+(S?d:-d)),x.position){case"center":p=k?S?L-d/2+y:L+d/2-y:S?L-d/2+u.height/2+y:L+d/2+u.height/2-y;break;case"bottom":p=k?S?L-d+y:L+d-y:S?L-d+u.height+m+y:L+d-u.height/2+m-y;break;case"top":p=k?S?L+y:L-y:S?L-u.height/2-y:L+u.height+y}var M=L;if(i.globals.seriesGroups.forEach((function(t){var i;null===(i=e.barCtx[t.join(",")])||void 0===i||i.prevY.forEach((function(t){M=S?Math.max(t[s],M):Math.min(t[s],M)}))})),this.barCtx.lastActiveBarSerieIndex===r&&b.enabled){var P=new Mi(this.barCtx.ctx).getTextRects(this.getStackedTotalDataLabel({realIndex:r,j:s}),f.fontSize);n=S?M-P.height/2-y-b.offsetY+18:M+P.height+y+b.offsetY-18;var I=C;o=w+(i.globals.isXNumeric?-c*i.globals.barGroups.length/2:i.globals.barGroups.length*c/2-(i.globals.barGroups.length-1)*c-I)+b.offsetX}return i.config.chart.stacked||(p<0?p=0+m:p+u.height/3>i.globals.gridHeight&&(p=i.globals.gridHeight-m)),{bcx:h,bcy:l,dataLabelsX:g,dataLabelsY:p,totalDataLabelsX:o,totalDataLabelsY:n,totalDataLabelsAnchor:"middle"}}},{key:"calculateBarsDataLabelsPosition",value:function(t){var e=this,i=this.w,a=t.x,s=t.i,r=t.j,n=t.realIndex,o=t.bcy,l=t.barHeight,h=t.barWidth,c=t.textRects,d=t.dataLabelsX,u=t.strokeWidth,g=t.dataLabelsConfig,p=t.barDataLabelsConfig,f=t.barTotalDataLabelsConfig,x=t.offX,b=t.offY,m=i.globals.gridHeight/i.globals.dataPoints,v=this.barCtx.barHelpers.getZeroValueEncounters({i:s,j:r}).zeroEncounters;h=Math.abs(h);var y,w,k=o-(this.barCtx.isRangeBar?0:m)+l/2+c.height/2+b-3;!i.config.chart.stacked&&v>0&&i.config.plotOptions.bar.hideZeroBarsWhenGrouped&&(k-=l*v);var A="start",C=i.globals.series[s][r]<0,S=a;switch(this.barCtx.isReversed&&(S=a+(C?-h:h),A=C?"start":"end"),p.position){case"center":d=C?S+h/2-x:Math.max(c.width/2,S-h/2)+x;break;case"bottom":d=C?S+h-u-x:S-h+u+x;break;case"top":d=C?S-u-x:S-u+x}var L=S;if(i.globals.seriesGroups.forEach((function(t){var i;null===(i=e.barCtx[t.join(",")])||void 0===i||i.prevX.forEach((function(t){L=C?Math.min(t[r],L):Math.max(t[r],L)}))})),this.barCtx.lastActiveBarSerieIndex===n&&f.enabled){var M=new Mi(this.barCtx.ctx).getTextRects(this.getStackedTotalDataLabel({realIndex:n,j:r}),g.fontSize);C?(y=L-u-x-f.offsetX,A="end"):y=L+x+f.offsetX+(this.barCtx.isReversed?-(h+u):u),w=k-c.height/2+M.height/2+f.offsetY+u,i.globals.barGroups.length>1&&(w-=i.globals.barGroups.length/2*(l/2))}return i.config.chart.stacked||("start"===g.textAnchor?d-c.width<0?d=C?c.width+u:u:d+c.width>i.globals.gridWidth&&(d=C?i.globals.gridWidth-u:i.globals.gridWidth-c.width-u):"middle"===g.textAnchor?d-c.width/2<0?d=c.width/2+u:d+c.width/2>i.globals.gridWidth&&(d=i.globals.gridWidth-c.width/2-u):"end"===g.textAnchor&&(d<1?d=c.width+u:d+1>i.globals.gridWidth&&(d=i.globals.gridWidth-c.width-u))),{bcx:a,bcy:o,dataLabelsX:d,dataLabelsY:k,totalDataLabelsX:y,totalDataLabelsY:w,totalDataLabelsAnchor:A}}},{key:"drawCalculatedDataLabels",value:function(t){var e=t.x,i=t.y,a=t.val,s=t.i,r=t.j,n=t.textRects,o=t.barHeight,l=t.barWidth,h=t.dataLabelsConfig,c=this.w,d="rotate(0)";"vertical"===c.config.plotOptions.bar.dataLabels.orientation&&(d="rotate(-90, ".concat(e,", ").concat(i,")"));var g=new qi(this.barCtx.ctx),p=new Mi(this.barCtx.ctx),f=h.formatter,x=null,b=c.globals.collapsedSeriesIndices.indexOf(s)>-1;if(h.enabled&&!b){x=p.group({class:"apexcharts-data-labels",transform:d});var m="";void 0!==a&&(m=f(a,u(u({},c),{},{seriesIndex:s,dataPointIndex:r,w:c}))),!a&&c.config.plotOptions.bar.hideZeroBarsWhenGrouped&&(m="");var v=c.globals.series[s][r]<0,y=c.config.plotOptions.bar.dataLabels.position;if("vertical"===c.config.plotOptions.bar.dataLabels.orientation&&("top"===y&&(h.textAnchor=v?"end":"start"),"center"===y&&(h.textAnchor="middle"),"bottom"===y&&(h.textAnchor=v?"end":"start")),this.barCtx.isRangeBar&&this.barCtx.barOptions.dataLabels.hideOverflowingLabels)lMath.abs(l)&&(m=""):n.height/1.6>Math.abs(o)&&(m=""));var w=u({},h);this.barCtx.isHorizontal&&a<0&&("start"===h.textAnchor?w.textAnchor="end":"end"===h.textAnchor&&(w.textAnchor="start")),g.plotDataLabelsText({x:e,y:i,text:m,i:s,j:r,parent:x,dataLabelsConfig:w,alwaysDrawDataLabel:!0,offsetCorrection:!0})}return x}},{key:"drawTotalDataLabels",value:function(t){var e=t.x,i=t.y,a=t.val,s=t.realIndex,r=t.textAnchor,n=t.barTotalDataLabelsConfig;this.w;var o,l=new Mi(this.barCtx.ctx);return n.enabled&&void 0!==e&&void 0!==i&&this.barCtx.lastActiveBarSerieIndex===s&&(o=l.drawText({x:e,y:i,foreColor:n.style.color,text:a,textAnchor:r,fontFamily:n.style.fontFamily,fontSize:n.style.fontSize,fontWeight:n.style.fontWeight})),o}}]),t}(),Pa=function(){function t(e){i(this,t),this.w=e.w,this.barCtx=e}return s(t,[{key:"initVariables",value:function(t){var e=this.w;this.barCtx.series=t,this.barCtx.totalItems=0,this.barCtx.seriesLen=0,this.barCtx.visibleI=-1,this.barCtx.visibleItems=1;for(var i=0;i0&&(this.barCtx.seriesLen=this.barCtx.seriesLen+1,this.barCtx.totalItems+=t[i].length),e.globals.isXNumeric)for(var a=0;ae.globals.minX&&e.globals.seriesX[i][a]0&&(s=h.globals.minXDiff/u),(n=s/d*parseInt(this.barCtx.barOptions.columnWidth,10)/100)<1&&(n=1)}if(-1===String(this.barCtx.barOptions.columnWidth).indexOf("%")&&(n=parseInt(this.barCtx.barOptions.columnWidth,10)),o=h.globals.gridHeight-this.barCtx.baseLineY[this.barCtx.translationsIndex]-(this.barCtx.isReversed?h.globals.gridHeight:0)+(this.barCtx.isReversed?2*this.barCtx.baseLineY[this.barCtx.translationsIndex]:0),h.globals.isXNumeric)e=this.barCtx.getBarXForNumericXAxis({x:e,j:0,realIndex:t,barWidth:n}).x;else e=h.globals.padHorizontal+v.noExponents(s-n*this.barCtx.seriesLen)/2}return h.globals.barHeight=r,h.globals.barWidth=n,{x:e,y:i,yDivision:a,xDivision:s,barHeight:r,barWidth:n,zeroH:o,zeroW:l}}},{key:"initializeStackedPrevVars",value:function(t){t.w.globals.seriesGroups.forEach((function(e){t[e]||(t[e]={}),t[e].prevY=[],t[e].prevX=[],t[e].prevYF=[],t[e].prevXF=[],t[e].prevYVal=[],t[e].prevXVal=[]}))}},{key:"initializeStackedXYVars",value:function(t){t.w.globals.seriesGroups.forEach((function(e){t[e]||(t[e]={}),t[e].xArrj=[],t[e].xArrjF=[],t[e].xArrjVal=[],t[e].yArrj=[],t[e].yArrjF=[],t[e].yArrjVal=[]}))}},{key:"getPathFillColor",value:function(t,e,i,a){var s,r,n,o,l=this.w,h=this.barCtx.ctx.fill,c=null,d=this.barCtx.barOptions.distributed?i:e,u=!1;this.barCtx.barOptions.colors.ranges.length>0&&this.barCtx.barOptions.colors.ranges.map((function(a){t[e][i]>=a.from&&t[e][i]<=a.to&&(c=a.color,u=!0)}));return{color:h.fillPath({seriesNumber:this.barCtx.barOptions.distributed?d:a,dataPointIndex:i,color:c,value:t[e][i],fillConfig:null===(s=l.config.series[e].data[i])||void 0===s?void 0:s.fill,fillType:null!==(r=l.config.series[e].data[i])&&void 0!==r&&null!==(n=r.fill)&&void 0!==n&&n.type?null===(o=l.config.series[e].data[i])||void 0===o?void 0:o.fill.type:Array.isArray(l.config.fill.type)?l.config.fill.type[a]:l.config.fill.type}),useRangeColor:u}}},{key:"getStrokeWidth",value:function(t,e,i){var a=0,s=this.w;return void 0===this.barCtx.series[t][e]||null===this.barCtx.series[t][e]||"bar"===s.config.chart.type&&!this.barCtx.series[t][e]?this.barCtx.isNullValue=!0:this.barCtx.isNullValue=!1,s.config.stroke.show&&(this.barCtx.isNullValue||(a=Array.isArray(this.barCtx.strokeWidth)?this.barCtx.strokeWidth[i]:this.barCtx.strokeWidth)),a}},{key:"createBorderRadiusArr",value:function(t){var e,i=this.w,a=!this.w.config.chart.stacked||i.config.plotOptions.bar.borderRadius<=0,s=t.length,n=0|(null===(e=t[0])||void 0===e?void 0:e.length),o=Array.from({length:s},(function(){return Array(n).fill(a?"top":"none")}));if(a)return o;for(var l=0;l0?(h.push(u),d++):g<0&&(c.push(u),d++)}if(h.length>0&&0===c.length)if(1===h.length)o[h[0]][l]="both";else{var p,f=h[0],x=h[h.length-1],b=r(h);try{for(b.s();!(p=b.n()).done;){var m=p.value;o[m][l]=m===f?"bottom":m===x?"top":"none"}}catch(t){b.e(t)}finally{b.f()}}else if(c.length>0&&0===h.length)if(1===c.length)o[c[0]][l]="both";else{var v,y=Math.max.apply(Math,c),w=Math.min.apply(Math,c),k=r(c);try{for(k.s();!(v=k.n()).done;){var A=v.value;o[A][l]=A===y?"bottom":A===w?"top":"none"}}catch(t){k.e(t)}finally{k.f()}}else if(h.length>0&&c.length>0){var C,S=h[h.length-1],L=r(h);try{for(L.s();!(C=L.n()).done;){var M=C.value;o[M][l]=M===S?"top":"none"}}catch(t){L.e(t)}finally{L.f()}var P,I=Math.max.apply(Math,c),T=r(c);try{for(T.s();!(P=T.n()).done;){var z=P.value;o[z][l]=z===I?"bottom":"none"}}catch(t){T.e(t)}finally{T.f()}}else if(1===d){o[h[0]||c[0]][l]="both"}}return o}},{key:"barBackground",value:function(t){var e=t.j,i=t.i,a=t.x1,s=t.x2,r=t.y1,n=t.y2,o=t.elSeries,l=this.w,h=new Mi(this.barCtx.ctx),c=new $i(this.barCtx.ctx).getActiveConfigSeriesIndex();if(this.barCtx.barOptions.colors.backgroundBarColors.length>0&&c===i){e>=this.barCtx.barOptions.colors.backgroundBarColors.length&&(e%=this.barCtx.barOptions.colors.backgroundBarColors.length);var d=this.barCtx.barOptions.colors.backgroundBarColors[e],u=h.drawRect(void 0!==a?a:0,void 0!==r?r:0,void 0!==s?s:l.globals.gridWidth,void 0!==n?n:l.globals.gridHeight,this.barCtx.barOptions.colors.backgroundBarRadius,d,this.barCtx.barOptions.colors.backgroundBarOpacity);o.add(u),u.node.classList.add("apexcharts-backgroundBar")}}},{key:"getColumnPaths",value:function(t){var e,i=t.barWidth,a=t.barXPosition,s=t.y1,r=t.y2,n=t.strokeWidth,o=t.isReversed,l=t.series,h=t.seriesGroup,c=t.realIndex,d=t.i,u=t.j,g=t.w,p=new Mi(this.barCtx.ctx);(n=Array.isArray(n)?n[c]:n)||(n=0);var f=i,x=a;null!==(e=g.config.series[c].data[u])&&void 0!==e&&e.columnWidthOffset&&(x=a-g.config.series[c].data[u].columnWidthOffset/2,f=i+g.config.series[c].data[u].columnWidthOffset);var b=n/2,m=x+b,v=x+f-b,y=(l[d][u]>=0?1:-1)*(o?-1:1);s+=.001-b*y,r+=.001+b*y;var w=p.move(m,s),k=p.move(m,s),A=p.line(v,s);if(g.globals.previousPaths.length>0&&(k=this.barCtx.getPreviousPath(c,u,!1)),w=w+p.line(m,r)+p.line(v,r)+A+("around"===g.config.plotOptions.bar.borderRadiusApplication||"both"===this.arrBorderRadius[c][u]?" Z":" z"),k=k+p.line(m,s)+A+A+A+A+A+p.line(m,s)+("around"===g.config.plotOptions.bar.borderRadiusApplication||"both"===this.arrBorderRadius[c][u]?" Z":" z"),"none"!==this.arrBorderRadius[c][u]&&(w=p.roundPathCorners(w,g.config.plotOptions.bar.borderRadius)),g.config.chart.stacked){var C=this.barCtx;(C=this.barCtx[h]).yArrj.push(r-b*y),C.yArrjF.push(Math.abs(s-r+n*y)),C.yArrjVal.push(this.barCtx.series[d][u])}return{pathTo:w,pathFrom:k}}},{key:"getBarpaths",value:function(t){var e,i=t.barYPosition,a=t.barHeight,s=t.x1,r=t.x2,n=t.strokeWidth,o=t.isReversed,l=t.series,h=t.seriesGroup,c=t.realIndex,d=t.i,u=t.j,g=t.w,p=new Mi(this.barCtx.ctx);(n=Array.isArray(n)?n[c]:n)||(n=0);var f=i,x=a;null!==(e=g.config.series[c].data[u])&&void 0!==e&&e.barHeightOffset&&(f=i-g.config.series[c].data[u].barHeightOffset/2,x=a+g.config.series[c].data[u].barHeightOffset);var b=n/2,m=f+b,v=f+x-b,y=(l[d][u]>=0?1:-1)*(o?-1:1);s+=.001+b*y,r+=.001-b*y;var w=p.move(s,m),k=p.move(s,m);g.globals.previousPaths.length>0&&(k=this.barCtx.getPreviousPath(c,u,!1));var A=p.line(s,v);if(w=w+p.line(r,m)+p.line(r,v)+A+("around"===g.config.plotOptions.bar.borderRadiusApplication||"both"===this.arrBorderRadius[c][u]?" Z":" z"),k=k+p.line(s,m)+A+A+A+A+A+p.line(s,m)+("around"===g.config.plotOptions.bar.borderRadiusApplication||"both"===this.arrBorderRadius[c][u]?" Z":" z"),"none"!==this.arrBorderRadius[c][u]&&(w=p.roundPathCorners(w,g.config.plotOptions.bar.borderRadius)),g.config.chart.stacked){var C=this.barCtx;(C=this.barCtx[h]).xArrj.push(r+b*y),C.xArrjF.push(Math.abs(s-r-n*y)),C.xArrjVal.push(this.barCtx.series[d][u])}return{pathTo:w,pathFrom:k}}},{key:"checkZeroSeries",value:function(t){for(var e=t.series,i=this.w,a=0;a2&&void 0!==arguments[2])||arguments[2]?e:null;return null!=t&&(i=e+t/this.barCtx.invertedYRatio-2*(this.barCtx.isReversed?t/this.barCtx.invertedYRatio:0)),i}},{key:"getYForValue",value:function(t,e,i){var a=!(arguments.length>3&&void 0!==arguments[3])||arguments[3]?e:null;return null!=t&&(a=e-t/this.barCtx.yRatio[i]+2*(this.barCtx.isReversed?t/this.barCtx.yRatio[i]:0)),a}},{key:"getGoalValues",value:function(t,e,i,a,s,r){var n=this,l=this.w,h=[],c=function(a,s){var l;h.push((o(l={},t,"x"===t?n.getXForValue(a,e,!1):n.getYForValue(a,i,r,!1)),o(l,"attrs",s),l))};if(l.globals.seriesGoals[a]&&l.globals.seriesGoals[a][s]&&Array.isArray(l.globals.seriesGoals[a][s])&&l.globals.seriesGoals[a][s].forEach((function(t){c(t.value,t)})),this.barCtx.barOptions.isDumbbell&&l.globals.seriesRange.length){var d=this.barCtx.barOptions.dumbbellColors?this.barCtx.barOptions.dumbbellColors:l.globals.colors,g={strokeHeight:"x"===t?0:l.globals.markers.size[a],strokeWidth:"x"===t?l.globals.markers.size[a]:0,strokeDashArray:0,strokeLineCap:"round",strokeColor:Array.isArray(d[a])?d[a][0]:d[a]};c(l.globals.seriesRangeStart[a][s],g),c(l.globals.seriesRangeEnd[a][s],u(u({},g),{},{strokeColor:Array.isArray(d[a])?d[a][1]:d[a]}))}return h}},{key:"drawGoalLine",value:function(t){var e=t.barXPosition,i=t.barYPosition,a=t.goalX,s=t.goalY,r=t.barWidth,n=t.barHeight,o=new Mi(this.barCtx.ctx),l=o.group({className:"apexcharts-bar-goals-groups"});l.node.classList.add("apexcharts-element-hidden"),this.barCtx.w.globals.delayedElements.push({el:l.node}),l.attr("clip-path","url(#gridRectMarkerMask".concat(this.barCtx.w.globals.cuid,")"));var h=null;return this.barCtx.isHorizontal?Array.isArray(a)&&a.forEach((function(t){if(t.x>=-1&&t.x<=o.w.globals.gridWidth+1){var e=void 0!==t.attrs.strokeHeight?t.attrs.strokeHeight:n/2,a=i+e+n/2;h=o.drawLine(t.x,a-2*e,t.x,a,t.attrs.strokeColor?t.attrs.strokeColor:void 0,t.attrs.strokeDashArray,t.attrs.strokeWidth?t.attrs.strokeWidth:2,t.attrs.strokeLineCap),l.add(h)}})):Array.isArray(s)&&s.forEach((function(t){if(t.y>=-1&&t.y<=o.w.globals.gridHeight+1){var i=void 0!==t.attrs.strokeWidth?t.attrs.strokeWidth:r/2,a=e+i+r/2;h=o.drawLine(a-2*i,t.y,a,t.y,t.attrs.strokeColor?t.attrs.strokeColor:void 0,t.attrs.strokeDashArray,t.attrs.strokeHeight?t.attrs.strokeHeight:2,t.attrs.strokeLineCap),l.add(h)}})),l}},{key:"drawBarShadow",value:function(t){var e=t.prevPaths,i=t.currPaths,a=t.color,s=this.w,r=e.x,n=e.x1,o=e.barYPosition,l=i.x,h=i.x1,c=i.barYPosition,d=o+i.barHeight,u=new Mi(this.barCtx.ctx),g=new v,p=u.move(n,d)+u.line(r,d)+u.line(l,c)+u.line(h,c)+u.line(n,d)+("around"===s.config.plotOptions.bar.borderRadiusApplication||"both"===this.arrBorderRadius[realIndex][j]?" Z":" z");return u.drawPath({d:p,fill:g.shadeColor(.5,v.rgb2hex(a)),stroke:"none",strokeWidth:0,fillOpacity:1,classes:"apexcharts-bar-shadow apexcharts-decoration-element"})}},{key:"getZeroValueEncounters",value:function(t){var e,i=t.i,a=t.j,s=this.w,r=0,n=0;return(s.config.plotOptions.bar.horizontal?s.globals.series.map((function(t,e){return e})):(null===(e=s.globals.columnSeries)||void 0===e?void 0:e.i.map((function(t){return t})))||[]).forEach((function(t){var e=s.globals.seriesPercent[t][a];e&&r++,t-1})),a=this.barCtx.columnGroupIndices,s=a.indexOf(i);return s<0&&(a.push(i),s=a.length-1),{groupIndex:i,columnGroupIndex:s}}}]),t}(),Ia=function(){function t(e,a){i(this,t),this.ctx=e,this.w=e.w;var s=this.w;this.barOptions=s.config.plotOptions.bar,this.isHorizontal=this.barOptions.horizontal,this.strokeWidth=s.config.stroke.width,this.isNullValue=!1,this.isRangeBar=s.globals.seriesRange.length&&this.isHorizontal,this.isVerticalGroupedRangeBar=!s.globals.isBarHorizontal&&s.globals.seriesRange.length&&s.config.plotOptions.bar.rangeBarGroupRows,this.isFunnel=this.barOptions.isFunnel,this.xyRatios=a,null!==this.xyRatios&&(this.xRatio=a.xRatio,this.yRatio=a.yRatio,this.invertedXRatio=a.invertedXRatio,this.invertedYRatio=a.invertedYRatio,this.baseLineY=a.baseLineY,this.baseLineInvertedY=a.baseLineInvertedY),this.yaxisIndex=0,this.translationsIndex=0,this.seriesLen=0,this.pathArr=[];var r=new $i(this.ctx);this.lastActiveBarSerieIndex=r.getActiveConfigSeriesIndex("desc",["bar","column"]),this.columnGroupIndices=[];var n=r.getBarSeriesIndices(),o=new Pi(this.ctx);this.stackedSeriesTotals=o.getStackedSeriesTotals(this.w.config.series.map((function(t,e){return-1===n.indexOf(e)?e:-1})).filter((function(t){return-1!==t}))),this.barHelpers=new Pa(this)}return s(t,[{key:"draw",value:function(t,e){var i=this.w,a=new Mi(this.ctx),s=new Pi(this.ctx,i);t=s.getLogSeries(t),this.series=t,this.yRatio=s.getLogYRatios(this.yRatio),this.barHelpers.initVariables(t);var r=a.group({class:"apexcharts-bar-series apexcharts-plot-series"});i.config.dataLabels.enabled&&this.totalItems>this.barOptions.dataLabels.maxItems&&console.warn("WARNING: DataLabels are enabled but there are too many to display. This may cause performance issue when rendering - ApexCharts");for(var n=0,o=0;n0&&(this.visibleI=this.visibleI+1);var w=0,k=0;this.yRatio.length>1&&(this.yaxisIndex=i.globals.seriesYAxisReverseMap[b],this.translationsIndex=b);var A=this.translationsIndex;this.isReversed=i.config.yaxis[this.yaxisIndex]&&i.config.yaxis[this.yaxisIndex].reversed;var C=this.barHelpers.initialPositions(b);p=C.y,w=C.barHeight,h=C.yDivision,d=C.zeroW,g=C.x,k=C.barWidth,l=C.xDivision,c=C.zeroH,this.isHorizontal||x.push(g+k/2);var S=a.group({class:"apexcharts-datalabels","data:realIndex":b});i.globals.delayedElements.push({el:S.node}),S.node.classList.add("apexcharts-element-hidden");var L=a.group({class:"apexcharts-bar-goals-markers"}),M=a.group({class:"apexcharts-bar-shadows"});i.globals.delayedElements.push({el:M.node}),M.node.classList.add("apexcharts-element-hidden");for(var P=0;P0){var R,E=this.barHelpers.drawBarShadow({color:"string"==typeof X.color&&-1===(null===(R=X.color)||void 0===R?void 0:R.indexOf("url"))?X.color:v.hexToRgba(i.globals.colors[n]),prevPaths:this.pathArr[this.pathArr.length-1],currPaths:T});if(M.add(E),i.config.chart.dropShadow.enabled)new Li(this.ctx).dropShadow(E,i.config.chart.dropShadow,b)}this.pathArr.push(T);var Y=this.barHelpers.drawGoalLine({barXPosition:T.barXPosition,barYPosition:T.barYPosition,goalX:T.goalX,goalY:T.goalY,barHeight:w,barWidth:k});Y&&L.add(Y),p=T.y,g=T.x,P>0&&x.push(g+k/2),f.push(p),this.renderSeries(u(u({realIndex:b,pathFill:X.color},X.useRangeColor?{lineFill:X.color}:{}),{},{j:P,i:n,columnGroupIndex:m,pathFrom:T.pathFrom,pathTo:T.pathTo,strokeWidth:I,elSeries:y,x:g,y:p,series:t,barHeight:Math.abs(T.barHeight?T.barHeight:w),barWidth:Math.abs(T.barWidth?T.barWidth:k),elDataLabelsWrap:S,elGoalsMarkers:L,elBarShadows:M,visibleSeries:this.visibleI,type:"bar"}))}i.globals.seriesXvalues[b]=x,i.globals.seriesYvalues[b]=f,r.add(y)}return r}},{key:"renderSeries",value:function(t){var e=t.realIndex,i=t.pathFill,a=t.lineFill,s=t.j,r=t.i,n=t.columnGroupIndex,o=t.pathFrom,l=t.pathTo,h=t.strokeWidth,c=t.elSeries,d=t.x,u=t.y,g=t.y1,p=t.y2,f=t.series,x=t.barHeight,b=t.barWidth,m=t.barXPosition,v=t.barYPosition,y=t.elDataLabelsWrap,w=t.elGoalsMarkers,k=t.elBarShadows,A=t.visibleSeries,C=t.type,S=t.classes,L=this.w,M=new Mi(this.ctx),P=!1;if(!a){var I="function"==typeof L.globals.stroke.colors[e]?function(t){var e,i=L.config.stroke.colors;return Array.isArray(i)&&i.length>0&&((e=i[t])||(e=""),"function"==typeof e)?e({value:L.globals.series[t][s],dataPointIndex:s,w:L}):e}(e):L.globals.stroke.colors[e];a=this.barOptions.distributed?L.globals.stroke.colors[s]:I}var T=new Ma(this).handleBarDataLabels({x:d,y:u,y1:g,y2:p,i:r,j:s,series:f,realIndex:e,columnGroupIndex:n,barHeight:x,barWidth:b,barXPosition:m,barYPosition:v,visibleSeries:A});L.globals.isBarHorizontal||(T.dataLabelsPos.dataLabelsX+Math.max(b,L.globals.barPadForNumericAxis)<0||T.dataLabelsPos.dataLabelsX-Math.max(b,L.globals.barPadForNumericAxis)>L.globals.gridWidth)&&(P=!0),L.config.series[r].data[s]&&L.config.series[r].data[s].strokeColor&&(a=L.config.series[r].data[s].strokeColor),this.isNullValue&&(i="none");var z=s/L.config.chart.animations.animateGradually.delay*(L.config.chart.animations.speed/L.globals.dataPoints)/2.4;if(!P){var X=M.renderPaths({i:r,j:s,realIndex:e,pathFrom:o,pathTo:l,stroke:a,strokeWidth:h,strokeLineCap:L.config.stroke.lineCap,fill:i,animationDelay:z,initialSpeed:L.config.chart.animations.speed,dataChangeSpeed:L.config.chart.animations.dynamicAnimation.speed,className:"apexcharts-".concat(C,"-area ").concat(S),chartType:C});X.attr("clip-path","url(#gridRectBarMask".concat(L.globals.cuid,")"));var R=L.config.forecastDataPoints;R.count>0&&s>=L.globals.dataPoints-R.count&&(X.node.setAttribute("stroke-dasharray",R.dashArray),X.node.setAttribute("stroke-width",R.strokeWidth),X.node.setAttribute("fill-opacity",R.fillOpacity)),void 0!==g&&void 0!==p&&(X.attr("data-range-y1",g),X.attr("data-range-y2",p)),new Li(this.ctx).setSelectionFilter(X,e,s),c.add(X),X.attr({cy:T.dataLabelsPos.bcy,cx:T.dataLabelsPos.bcx,j:s,val:L.globals.series[r][s],barHeight:x,barWidth:b}),null!==T.dataLabels&&y.add(T.dataLabels),T.totalDataLabels&&y.add(T.totalDataLabels),c.add(y),w&&c.add(w),k&&c.add(k)}return c}},{key:"drawBarPaths",value:function(t){var e,i=t.indexes,a=t.barHeight,s=t.strokeWidth,r=t.zeroW,n=t.x,o=t.y,l=t.yDivision,h=t.elSeries,c=this.w,d=i.i,u=i.j;if(c.globals.isXNumeric)e=(o=(c.globals.seriesX[d][u]-c.globals.minX)/this.invertedXRatio-a)+a*this.visibleI;else if(c.config.plotOptions.bar.hideZeroBarsWhenGrouped){var g=this.barHelpers.getZeroValueEncounters({i:d,j:u}),p=g.nonZeroColumns,f=g.zeroEncounters;p>0&&(a=this.seriesLen*a/p),e=o+a*this.visibleI,e-=a*f}else e=o+a*this.visibleI;this.isFunnel&&(r-=(this.barHelpers.getXForValue(this.series[d][u],r)-r)/2),n=this.barHelpers.getXForValue(this.series[d][u],r);var x=this.barHelpers.getBarpaths({barYPosition:e,barHeight:a,x1:r,x2:n,strokeWidth:s,isReversed:this.isReversed,series:this.series,realIndex:i.realIndex,i:d,j:u,w:c});return c.globals.isXNumeric||(o+=l),this.barHelpers.barBackground({j:u,i:d,y1:e-a*this.visibleI,y2:a*this.seriesLen,elSeries:h}),{pathTo:x.pathTo,pathFrom:x.pathFrom,x1:r,x:n,y:o,goalX:this.barHelpers.getGoalValues("x",r,null,d,u),barYPosition:e,barHeight:a}}},{key:"drawColumnPaths",value:function(t){var e,i=t.indexes,a=t.x,s=t.y,r=t.xDivision,n=t.barWidth,o=t.zeroH,l=t.strokeWidth,h=t.elSeries,c=this.w,d=i.realIndex,u=i.translationsIndex,g=i.i,p=i.j,f=i.bc;if(c.globals.isXNumeric){var x=this.getBarXForNumericXAxis({x:a,j:p,realIndex:d,barWidth:n});a=x.x,e=x.barXPosition}else if(c.config.plotOptions.bar.hideZeroBarsWhenGrouped){var b=this.barHelpers.getZeroValueEncounters({i:g,j:p}),m=b.nonZeroColumns,v=b.zeroEncounters;m>0&&(n=this.seriesLen*n/m),e=a+n*this.visibleI,e-=n*v}else e=a+n*this.visibleI;s=this.barHelpers.getYForValue(this.series[g][p],o,u);var y=this.barHelpers.getColumnPaths({barXPosition:e,barWidth:n,y1:o,y2:s,strokeWidth:l,isReversed:this.isReversed,series:this.series,realIndex:d,i:g,j:p,w:c});return c.globals.isXNumeric||(a+=r),this.barHelpers.barBackground({bc:f,j:p,i:g,x1:e-l/2-n*this.visibleI,x2:n*this.seriesLen+l/2,elSeries:h}),{pathTo:y.pathTo,pathFrom:y.pathFrom,x:a,y:s,goalY:this.barHelpers.getGoalValues("y",null,o,g,p,u),barXPosition:e,barWidth:n}}},{key:"getBarXForNumericXAxis",value:function(t){var e=t.x,i=t.barWidth,a=t.realIndex,s=t.j,r=this.w,n=a;return r.globals.seriesX[a].length||(n=r.globals.maxValsInArrayIndex),v.isNumber(r.globals.seriesX[n][s])&&(e=(r.globals.seriesX[n][s]-r.globals.minX)/this.xRatio-i*this.seriesLen/2),{barXPosition:e+i*this.visibleI,x:e}}},{key:"getPreviousPath",value:function(t,e){for(var i=this.w,a="M 0 0",s=0;s0&&parseInt(r.realIndex,10)===parseInt(t,10)&&void 0!==i.globals.previousPaths[s].paths[e]&&(a=i.globals.previousPaths[s].paths[e].d)}return a}}]),t}(),Ta=function(t){h(a,t);var e=n(a);function a(){return i(this,a),e.apply(this,arguments)}return s(a,[{key:"draw",value:function(t,e){var i=this,a=this.w;this.graphics=new Mi(this.ctx),this.bar=new Ia(this.ctx,this.xyRatios);var s=new Pi(this.ctx,a);t=s.getLogSeries(t),this.yRatio=s.getLogYRatios(this.yRatio),this.barHelpers.initVariables(t),"100%"===a.config.chart.stackType&&(t=a.globals.comboCharts?e.map((function(t){return a.globals.seriesPercent[t]})):a.globals.seriesPercent.slice()),this.series=t,this.barHelpers.initializeStackedPrevVars(this);for(var r=this.graphics.group({class:"apexcharts-bar-series apexcharts-plot-series"}),n=0,o=0,l=function(s,l){var h=void 0,c=void 0,d=void 0,g=void 0,p=a.globals.comboCharts?e[s]:s,f=i.barHelpers.getGroupIndex(p),x=f.groupIndex,b=f.columnGroupIndex;i.groupCtx=i[a.globals.seriesGroups[x]];var m=[],y=[],w=0;i.yRatio.length>1&&(i.yaxisIndex=a.globals.seriesYAxisReverseMap[p][0],w=p),i.isReversed=a.config.yaxis[i.yaxisIndex]&&a.config.yaxis[i.yaxisIndex].reversed;var k=i.graphics.group({class:"apexcharts-series",seriesName:v.escapeString(a.globals.seriesNames[p]),rel:s+1,"data:realIndex":p});i.ctx.series.addCollapsedClassToSeries(k,p);var A=i.graphics.group({class:"apexcharts-datalabels","data:realIndex":p}),C=i.graphics.group({class:"apexcharts-bar-goals-markers"}),S=0,L=0,M=i.initialPositions(n,o,h,c,d,g,w);o=M.y,S=M.barHeight,c=M.yDivision,g=M.zeroW,n=M.x,L=M.barWidth,h=M.xDivision,d=M.zeroH,a.globals.barHeight=S,a.globals.barWidth=L,i.barHelpers.initializeStackedXYVars(i),1===i.groupCtx.prevY.length&&i.groupCtx.prevY[0].every((function(t){return isNaN(t)}))&&(i.groupCtx.prevY[0]=i.groupCtx.prevY[0].map((function(){return d})),i.groupCtx.prevYF[0]=i.groupCtx.prevYF[0].map((function(){return 0})));for(var P=0;P0||"top"===i.barHelpers.arrBorderRadius[p][P]&&a.globals.series[p][P]<0)&&(E=Y),k=i.renderSeries(u(u({realIndex:p,pathFill:R.color},R.useRangeColor?{lineFill:R.color}:{}),{},{j:P,i:s,columnGroupIndex:b,pathFrom:z.pathFrom,pathTo:z.pathTo,strokeWidth:I,elSeries:k,x:n,y:o,series:t,barHeight:S,barWidth:L,elDataLabelsWrap:A,elGoalsMarkers:C,type:"bar",visibleSeries:b,classes:E}))}a.globals.seriesXvalues[p]=m,a.globals.seriesYvalues[p]=y,i.groupCtx.prevY.push(i.groupCtx.yArrj),i.groupCtx.prevYF.push(i.groupCtx.yArrjF),i.groupCtx.prevYVal.push(i.groupCtx.yArrjVal),i.groupCtx.prevX.push(i.groupCtx.xArrj),i.groupCtx.prevXF.push(i.groupCtx.xArrjF),i.groupCtx.prevXVal.push(i.groupCtx.xArrjVal),r.add(k)},h=0,c=0;h1?l=(i=h.globals.minXDiff/this.xRatio)*parseInt(this.barOptions.columnWidth,10)/100:-1===String(d).indexOf("%")?l=parseInt(d,10):l*=parseInt(d,10)/100,s=this.isReversed?this.baseLineY[n]:h.globals.gridHeight-this.baseLineY[n],t=h.globals.padHorizontal+(i-l)/2}var u=h.globals.barGroups.length||1;return{x:t,y:e,yDivision:a,xDivision:i,barHeight:o/u,barWidth:l/u,zeroH:s,zeroW:r}}},{key:"drawStackedBarPaths",value:function(t){for(var e,i=t.indexes,a=t.barHeight,s=t.strokeWidth,r=t.zeroW,n=t.x,o=t.y,l=t.columnGroupIndex,h=t.seriesGroup,c=t.yDivision,d=t.elSeries,u=this.w,g=o+l*a,p=i.i,f=i.j,x=i.realIndex,b=i.translationsIndex,m=0,v=0;v0){var w=r;this.groupCtx.prevXVal[y-1][f]<0?w=this.series[p][f]>=0?this.groupCtx.prevX[y-1][f]+m-2*(this.isReversed?m:0):this.groupCtx.prevX[y-1][f]:this.groupCtx.prevXVal[y-1][f]>=0&&(w=this.series[p][f]>=0?this.groupCtx.prevX[y-1][f]:this.groupCtx.prevX[y-1][f]-m+2*(this.isReversed?m:0)),e=w}else e=r;n=null===this.series[p][f]?e:e+this.series[p][f]/this.invertedYRatio-2*(this.isReversed?this.series[p][f]/this.invertedYRatio:0);var k=this.barHelpers.getBarpaths({barYPosition:g,barHeight:a,x1:e,x2:n,strokeWidth:s,isReversed:this.isReversed,series:this.series,realIndex:i.realIndex,seriesGroup:h,i:p,j:f,w:u});return this.barHelpers.barBackground({j:f,i:p,y1:g,y2:a,elSeries:d}),o+=c,{pathTo:k.pathTo,pathFrom:k.pathFrom,goalX:this.barHelpers.getGoalValues("x",r,null,p,f,b),barXPosition:e,barYPosition:g,x:n,y:o}}},{key:"drawStackedColumnPaths",value:function(t){var e=t.indexes,i=t.x,a=t.y,s=t.xDivision,r=t.barWidth,n=t.zeroH,o=t.columnGroupIndex,l=t.seriesGroup,h=t.elSeries,c=this.w,d=e.i,u=e.j,g=e.bc,p=e.realIndex,f=e.translationsIndex;if(c.globals.isXNumeric){var x=c.globals.seriesX[p][u];x||(x=0),i=(x-c.globals.minX)/this.xRatio-r/2*c.globals.barGroups.length}for(var b,m=i+o*r,v=0,y=0;y0&&!c.globals.isXNumeric||w>0&&c.globals.isXNumeric&&c.globals.seriesX[p-1][u]===c.globals.seriesX[p][u]){var k,A,C,S=Math.min(this.yRatio.length+1,p+1);if(void 0!==this.groupCtx.prevY[w-1]&&this.groupCtx.prevY[w-1].length)for(var L=1;L=0?C-v+2*(this.isReversed?v:0):C;break}if((null===(T=this.groupCtx.prevYVal[w-P])||void 0===T?void 0:T[u])>=0){A=this.series[d][u]>=0?C:C+v-2*(this.isReversed?v:0);break}}void 0===A&&(A=c.globals.gridHeight),b=null!==(k=this.groupCtx.prevYF[0])&&void 0!==k&&k.every((function(t){return 0===t}))&&this.groupCtx.prevYF.slice(1,w).every((function(t){return t.every((function(t){return isNaN(t)}))}))?n:A}else b=n;a=this.series[d][u]?b-this.series[d][u]/this.yRatio[f]+2*(this.isReversed?this.series[d][u]/this.yRatio[f]:0):b;var z=this.barHelpers.getColumnPaths({barXPosition:m,barWidth:r,y1:b,y2:a,yRatio:this.yRatio[f],strokeWidth:this.strokeWidth,isReversed:this.isReversed,series:this.series,seriesGroup:l,realIndex:e.realIndex,i:d,j:u,w:c});return this.barHelpers.barBackground({bc:g,j:u,i:d,x1:m,x2:r,elSeries:h}),{pathTo:z.pathTo,pathFrom:z.pathFrom,goalY:this.barHelpers.getGoalValues("y",null,n,d,u),barXPosition:m,x:c.globals.isXNumeric?i:i+s,y:a}}}]),a}(Ia),za=function(t){h(a,t);var e=n(a);function a(){return i(this,a),e.apply(this,arguments)}return s(a,[{key:"draw",value:function(t,e,i){var a=this,s=this.w,r=new Mi(this.ctx),n=s.globals.comboCharts?e:s.config.chart.type,o=new ji(this.ctx);this.candlestickOptions=this.w.config.plotOptions.candlestick,this.boxOptions=this.w.config.plotOptions.boxPlot,this.isHorizontal=s.config.plotOptions.bar.horizontal,this.isOHLC=this.candlestickOptions&&"ohlc"===this.candlestickOptions.type;var l=new Pi(this.ctx,s);t=l.getLogSeries(t),this.series=t,this.yRatio=l.getLogYRatios(this.yRatio),this.barHelpers.initVariables(t);for(var h=r.group({class:"apexcharts-".concat(n,"-series apexcharts-plot-series")}),c=function(e){a.isBoxPlot="boxPlot"===s.config.chart.type||"boxPlot"===s.config.series[e].type;var n,l,c,d,g=void 0,p=void 0,f=[],x=[],b=s.globals.comboCharts?i[e]:e,m=a.barHelpers.getGroupIndex(b).columnGroupIndex,y=r.group({class:"apexcharts-series",seriesName:v.escapeString(s.globals.seriesNames[b]),rel:e+1,"data:realIndex":b});a.ctx.series.addCollapsedClassToSeries(y,b),t[e].length>0&&(a.visibleI=a.visibleI+1);var w,k,A=0;a.yRatio.length>1&&(a.yaxisIndex=s.globals.seriesYAxisReverseMap[b][0],A=b);var C=a.barHelpers.initialPositions(b);p=C.y,w=C.barHeight,l=C.yDivision,d=C.zeroW,g=C.x,k=C.barWidth,n=C.xDivision,c=C.zeroH,x.push(g+k/2);for(var S=r.group({class:"apexcharts-datalabels","data:realIndex":b}),L=r.group({class:"apexcharts-bar-goals-markers"}),M=function(i){var r=a.barHelpers.getStrokeWidth(e,i,b),h=null,v={indexes:{i:e,j:i,realIndex:b,translationsIndex:A},x:g,y:p,strokeWidth:r,elSeries:y};h=a.isHorizontal?a.drawHorizontalBoxPaths(u(u({},v),{},{yDivision:l,barHeight:w,zeroW:d})):a.drawVerticalBoxPaths(u(u({},v),{},{xDivision:n,barWidth:k,zeroH:c})),p=h.y,g=h.x;var C=a.barHelpers.drawGoalLine({barXPosition:h.barXPosition,barYPosition:h.barYPosition,goalX:h.goalX,goalY:h.goalY,barHeight:w,barWidth:k});C&&L.add(C),i>0&&x.push(g+k/2),f.push(p),h.pathTo.forEach((function(n,l){var c=!a.isBoxPlot&&a.candlestickOptions.wick.useFillColor?h.color[l]:s.globals.stroke.colors[e],d=o.fillPath({seriesNumber:b,dataPointIndex:i,color:h.color[l],value:t[e][i]});a.renderSeries({realIndex:b,pathFill:d,lineFill:c,j:i,i:e,pathFrom:h.pathFrom,pathTo:n,strokeWidth:r,elSeries:y,x:g,y:p,series:t,columnGroupIndex:m,barHeight:w,barWidth:k,elDataLabelsWrap:S,elGoalsMarkers:L,visibleSeries:a.visibleI,type:s.config.chart.type})}))},P=0;P0&&(M=this.getPreviousPath(g,c,!0)),this.isOHLC){var P=S+s/2,I=r-m.o/b,T=r-m.c/b;L=[l.move(P,v)+l.line(P,y)+l.move(P,I)+l.line(S,I)+l.move(P,T)+l.line(S+s,T)]}else L=this.isBoxPlot?[l.move(S,k)+l.line(S+s/2,k)+l.line(S+s/2,v)+l.line(S+s/4,v)+l.line(S+s-s/4,v)+l.line(S+s/2,v)+l.line(S+s/2,k)+l.line(S+s,k)+l.line(S+s,C)+l.line(S,C)+l.line(S,k+n/2),l.move(S,C)+l.line(S+s,C)+l.line(S+s,A)+l.line(S+s/2,A)+l.line(S+s/2,y)+l.line(S+s-s/4,y)+l.line(S+s/4,y)+l.line(S+s/2,y)+l.line(S+s/2,A)+l.line(S,A)+l.line(S,C)+"z"]:[l.move(S,A)+l.line(S+s/2,A)+l.line(S+s/2,v)+l.line(S+s/2,A)+l.line(S+s,A)+l.line(S+s,k)+l.line(S+s/2,k)+l.line(S+s/2,y)+l.line(S+s/2,k)+l.line(S,k)+l.line(S,A-n/2)];return M+=l.move(S,k),o.globals.isXNumeric||(i+=a),{pathTo:L,pathFrom:M,x:i,y:A,goalY:this.barHelpers.getGoalValues("y",null,r,h,c,e.translationsIndex),barXPosition:S,color:w}}},{key:"drawHorizontalBoxPaths",value:function(t){var e=t.indexes;t.x;var i=t.y,a=t.yDivision,s=t.barHeight,r=t.zeroW,n=t.strokeWidth,o=this.w,l=new Mi(this.ctx),h=e.i,c=e.j,d=this.boxOptions.colors.lower;this.isBoxPlot&&(d=[this.boxOptions.colors.lower,this.boxOptions.colors.upper]);var u=this.invertedYRatio,g=e.realIndex,p=this.getOHLCValue(g,c),f=r,x=r,b=Math.min(p.o,p.c),m=Math.max(p.o,p.c),v=p.m;o.globals.isXNumeric&&(i=(o.globals.seriesX[g][c]-o.globals.minX)/this.invertedXRatio-s/2);var y=i+s*this.visibleI;void 0===this.series[h][c]||null===this.series[h][c]?(b=r,m=r):(b=r+b/u,m=r+m/u,f=r+p.h/u,x=r+p.l/u,v=r+p.m/u);var w=l.move(r,y),k=l.move(b,y+s/2);return o.globals.previousPaths.length>0&&(k=this.getPreviousPath(g,c,!0)),w=[l.move(b,y)+l.line(b,y+s/2)+l.line(f,y+s/2)+l.line(f,y+s/2-s/4)+l.line(f,y+s/2+s/4)+l.line(f,y+s/2)+l.line(b,y+s/2)+l.line(b,y+s)+l.line(v,y+s)+l.line(v,y)+l.line(b+n/2,y),l.move(v,y)+l.line(v,y+s)+l.line(m,y+s)+l.line(m,y+s/2)+l.line(x,y+s/2)+l.line(x,y+s-s/4)+l.line(x,y+s/4)+l.line(x,y+s/2)+l.line(m,y+s/2)+l.line(m,y)+l.line(v,y)+"z"],k+=l.move(b,y),o.globals.isXNumeric||(i+=a),{pathTo:w,pathFrom:k,x:m,y:i,goalX:this.barHelpers.getGoalValues("x",r,null,h,c),barYPosition:y,color:d}}},{key:"getOHLCValue",value:function(t,e){var i=this.w,a=new Pi(this.ctx,i),s=a.getLogValAtSeriesIndex(i.globals.seriesCandleH[t][e],t),r=a.getLogValAtSeriesIndex(i.globals.seriesCandleO[t][e],t),n=a.getLogValAtSeriesIndex(i.globals.seriesCandleM[t][e],t),o=a.getLogValAtSeriesIndex(i.globals.seriesCandleC[t][e],t),l=a.getLogValAtSeriesIndex(i.globals.seriesCandleL[t][e],t);return{o:this.isBoxPlot?s:r,h:this.isBoxPlot?r:s,m:n,l:this.isBoxPlot?o:l,c:this.isBoxPlot?l:o}}}]),a}(Ia),Xa=function(){function t(e){i(this,t),this.ctx=e,this.w=e.w}return s(t,[{key:"checkColorRange",value:function(){var t=this.w,e=!1,i=t.config.plotOptions[t.config.chart.type];return i.colorScale.ranges.length>0&&i.colorScale.ranges.map((function(t,i){t.from<=0&&(e=!0)})),e}},{key:"getShadeColor",value:function(t,e,i,a){var s=this.w,r=1,n=s.config.plotOptions[t].shadeIntensity,o=this.determineColor(t,e,i);s.globals.hasNegs||a?r=s.config.plotOptions[t].reverseNegativeShade?o.percent<0?o.percent/100*(1.25*n):(1-o.percent/100)*(1.25*n):o.percent<=0?1-(1+o.percent/100)*n:(1-o.percent/100)*n:(r=1-o.percent/100,"treemap"===t&&(r=(1-o.percent/100)*(1.25*n)));var l=o.color,h=new v;if(s.config.plotOptions[t].enableShades)if("dark"===this.w.config.theme.mode){var c=h.shadeColor(-1*r,o.color);l=v.hexToRgba(v.isColorHex(c)?c:v.rgb2hex(c),s.config.fill.opacity)}else{var d=h.shadeColor(r,o.color);l=v.hexToRgba(v.isColorHex(d)?d:v.rgb2hex(d),s.config.fill.opacity)}return{color:l,colorProps:o}}},{key:"determineColor",value:function(t,e,i){var a=this.w,s=a.globals.series[e][i],r=a.config.plotOptions[t],n=r.colorScale.inverse?i:e;r.distributed&&"treemap"===a.config.chart.type&&(n=i);var o=a.globals.colors[n],l=null,h=Math.min.apply(Math,f(a.globals.series[e])),c=Math.max.apply(Math,f(a.globals.series[e]));r.distributed||"heatmap"!==t||(h=a.globals.minY,c=a.globals.maxY),void 0!==r.colorScale.min&&(h=r.colorScale.mina.globals.maxY?r.colorScale.max:a.globals.maxY);var d=Math.abs(c)+Math.abs(h),u=100*s/(0===d?d-1e-6:d);r.colorScale.ranges.length>0&&r.colorScale.ranges.map((function(t,e){if(s>=t.from&&s<=t.to){o=t.color,l=t.foreColor?t.foreColor:null,h=t.from,c=t.to;var i=Math.abs(c)+Math.abs(h);u=100*s/(0===i?i-1e-6:i)}}));return{color:o,foreColor:l,percent:u}}},{key:"calculateDataLabels",value:function(t){var e=t.text,i=t.x,a=t.y,s=t.i,r=t.j,n=t.colorProps,o=t.fontSize,l=this.w.config.dataLabels,h=new Mi(this.ctx),c=new qi(this.ctx),d=null;if(l.enabled){d=h.group({class:"apexcharts-data-labels"});var u=l.offsetX,g=l.offsetY,p=i+u,f=a+parseFloat(l.style.fontSize)/3+g;c.plotDataLabelsText({x:p,y:f,text:e,i:s,j:r,color:n.foreColor,parent:d,fontSize:o,dataLabelsConfig:l})}return d}},{key:"addListeners",value:function(t){var e=new Mi(this.ctx);t.node.addEventListener("mouseenter",e.pathMouseEnter.bind(this,t)),t.node.addEventListener("mouseleave",e.pathMouseLeave.bind(this,t)),t.node.addEventListener("mousedown",e.pathMouseDown.bind(this,t))}}]),t}(),Ra=function(){function t(e,a){i(this,t),this.ctx=e,this.w=e.w,this.xRatio=a.xRatio,this.yRatio=a.yRatio,this.dynamicAnim=this.w.config.chart.animations.dynamicAnimation,this.helpers=new Xa(e),this.rectRadius=this.w.config.plotOptions.heatmap.radius,this.strokeWidth=this.w.config.stroke.show?this.w.config.stroke.width:0}return s(t,[{key:"draw",value:function(t){var e=this.w,i=new Mi(this.ctx),a=i.group({class:"apexcharts-heatmap"});a.attr("clip-path","url(#gridRectMask".concat(e.globals.cuid,")"));var s=e.globals.gridWidth/e.globals.dataPoints,r=e.globals.gridHeight/e.globals.series.length,n=0,o=!1;this.negRange=this.helpers.checkColorRange();var l=t.slice();e.config.yaxis[0].reversed&&(o=!0,l.reverse());for(var h=o?0:l.length-1;o?h=0;o?h++:h--){var c=i.group({class:"apexcharts-series apexcharts-heatmap-series",seriesName:v.escapeString(e.globals.seriesNames[h]),rel:h+1,"data:realIndex":h});if(this.ctx.series.addCollapsedClassToSeries(c,h),e.config.chart.dropShadow.enabled){var d=e.config.chart.dropShadow;new Li(this.ctx).dropShadow(c,d,h)}for(var u=0,g=e.config.plotOptions.heatmap.shadeIntensity,p=0,f=0;f=l[h].length)break;var x=this.helpers.getShadeColor(e.config.chart.type,h,p,this.negRange),b=x.color,m=x.colorProps;if("image"===e.config.fill.type)b=new ji(this.ctx).fillPath({seriesNumber:h,dataPointIndex:p,opacity:e.globals.hasNegs?m.percent<0?1-(1+m.percent/100):g+m.percent/100:m.percent/100,patternID:v.randomId(),width:e.config.fill.image.width?e.config.fill.image.width:s,height:e.config.fill.image.height?e.config.fill.image.height:r});var y=this.rectRadius,w=i.drawRect(u,n,s,r,y);if(w.attr({cx:u,cy:n}),w.node.classList.add("apexcharts-heatmap-rect"),c.add(w),w.attr({fill:b,i:h,index:h,j:p,val:t[h][p],"stroke-width":this.strokeWidth,stroke:e.config.plotOptions.heatmap.useFillColorAsStroke?b:e.globals.stroke.colors[0],color:b}),this.helpers.addListeners(w),e.config.chart.animations.enabled&&!e.globals.dataChanged){var k=1;e.globals.resized||(k=e.config.chart.animations.speed),this.animateHeatMap(w,u,n,s,r,k)}if(e.globals.dataChanged){var A=1;if(this.dynamicAnim.enabled&&e.globals.shouldAnimate){A=this.dynamicAnim.speed;var C=e.globals.previousPaths[h]&&e.globals.previousPaths[h][p]&&e.globals.previousPaths[h][p].color;C||(C="rgba(255, 255, 255, 0)"),this.animateHeatColor(w,v.isColorHex(C)?C:v.rgb2hex(C),v.isColorHex(b)?b:v.rgb2hex(b),A)}}var S=(0,e.config.dataLabels.formatter)(e.globals.series[h][p],{value:e.globals.series[h][p],seriesIndex:h,dataPointIndex:p,w:e}),L=this.helpers.calculateDataLabels({text:S,x:u+s/2,y:n+r/2,i:h,j:p,colorProps:m,series:l});null!==L&&c.add(L),u+=s,p++}n+=r,a.add(c)}var M=e.globals.yAxisScale[0].result.slice();return e.config.yaxis[0].reversed?M.unshift(""):M.push(""),e.globals.yAxisScale[0].result=M,a}},{key:"animateHeatMap",value:function(t,e,i,a,s,r){var n=new y(this.ctx);n.animateRect(t,{x:e+a/2,y:i+s/2,width:0,height:0},{x:e,y:i,width:a,height:s},r,(function(){n.animationCompleted(t)}))}},{key:"animateHeatColor",value:function(t,e,i,a){t.attr({fill:e}).animate(a).attr({fill:i})}}]),t}(),Ea=function(){function t(e){i(this,t),this.ctx=e,this.w=e.w}return s(t,[{key:"drawYAxisTexts",value:function(t,e,i,a){var s=this.w,r=s.config.yaxis[0],n=s.globals.yLabelFormatters[0];return new Mi(this.ctx).drawText({x:t+r.labels.offsetX,y:e+r.labels.offsetY,text:n(a,i),textAnchor:"middle",fontSize:r.labels.style.fontSize,fontFamily:r.labels.style.fontFamily,foreColor:Array.isArray(r.labels.style.colors)?r.labels.style.colors[i]:r.labels.style.colors})}}]),t}(),Ya=function(){function t(e){i(this,t),this.ctx=e,this.w=e.w;var a=this.w;this.chartType=this.w.config.chart.type,this.initialAnim=this.w.config.chart.animations.enabled,this.dynamicAnim=this.initialAnim&&this.w.config.chart.animations.dynamicAnimation.enabled,this.animBeginArr=[0],this.animDur=0,this.donutDataLabels=this.w.config.plotOptions.pie.donut.labels,this.lineColorArr=void 0!==a.globals.stroke.colors?a.globals.stroke.colors:a.globals.colors,this.defaultSize=Math.min(a.globals.gridWidth,a.globals.gridHeight),this.centerY=this.defaultSize/2,this.centerX=a.globals.gridWidth/2,"radialBar"===a.config.chart.type?this.fullAngle=360:this.fullAngle=Math.abs(a.config.plotOptions.pie.endAngle-a.config.plotOptions.pie.startAngle),this.initialAngle=a.config.plotOptions.pie.startAngle%this.fullAngle,a.globals.radialSize=this.defaultSize/2.05-a.config.stroke.width-(a.config.chart.sparkline.enabled?0:a.config.chart.dropShadow.blur),this.donutSize=a.globals.radialSize*parseInt(a.config.plotOptions.pie.donut.size,10)/100;var s=a.config.plotOptions.pie.customScale,r=a.globals.gridWidth/2,n=a.globals.gridHeight/2;this.translateX=r-r*s,this.translateY=n-n*s,this.dataLabelsGroup=new Mi(this.ctx).group({class:"apexcharts-datalabels-group",transform:"translate(".concat(this.translateX,", ").concat(this.translateY,") scale(").concat(s,")")}),this.maxY=0,this.sliceLabels=[],this.sliceSizes=[],this.prevSectorAngleArr=[]}return s(t,[{key:"draw",value:function(t){var e=this,i=this.w,a=new Mi(this.ctx),s=a.group({class:"apexcharts-pie"});if(i.globals.noData)return s;for(var r=0,n=0;n-1&&this.pieClicked(d),i.config.dataLabels.enabled){var w=m.x,k=m.y,A=100*g/this.fullAngle+"%";if(0!==g&&i.config.plotOptions.pie.dataLabels.minAngleToShowLabelthis.fullAngle?e.endAngle=e.endAngle-(a+n):a+n=this.fullAngle+this.w.config.plotOptions.pie.startAngle%this.fullAngle&&(h=this.fullAngle+this.w.config.plotOptions.pie.startAngle%this.fullAngle-.01),Math.ceil(h)>this.fullAngle&&(h-=this.fullAngle);var c=Math.PI*(h-90)/180,d=i.centerX+r*Math.cos(l),u=i.centerY+r*Math.sin(l),g=i.centerX+r*Math.cos(c),p=i.centerY+r*Math.sin(c),f=v.polarToCartesian(i.centerX,i.centerY,i.donutSize,h),x=v.polarToCartesian(i.centerX,i.centerY,i.donutSize,o),b=s>180?1:0,m=["M",d,u,"A",r,r,0,b,1,g,p];return e="donut"===i.chartType?[].concat(m,["L",f.x,f.y,"A",i.donutSize,i.donutSize,0,b,0,x.x,x.y,"L",d,u,"z"]).join(" "):"pie"===i.chartType||"polarArea"===i.chartType?[].concat(m,["L",i.centerX,i.centerY,"L",d,u]).join(" "):[].concat(m).join(" "),n.roundPathCorners(e,2*this.strokeWidth)}},{key:"drawPolarElements",value:function(t){var e=this.w,i=new ea(this.ctx),a=new Mi(this.ctx),s=new Ea(this.ctx),r=a.group(),n=a.group(),o=i.niceScale(0,Math.ceil(this.maxY),0),l=o.result.reverse(),h=o.result.length;this.maxY=o.niceMax;for(var c=e.globals.radialSize,d=c/(h-1),u=0;u1&&t.total.show&&(s=t.total.color);var n=r.globals.dom.baseEl.querySelector(".apexcharts-datalabel-label"),o=r.globals.dom.baseEl.querySelector(".apexcharts-datalabel-value");i=(0,t.value.formatter)(i,r),a||"function"!=typeof t.total.formatter||(i=t.total.formatter(r));var l=e===t.total.label;e=this.donutDataLabels.total.label?t.name.formatter(e,l,r):"",null!==n&&(n.textContent=e),null!==o&&(o.textContent=i),null!==n&&(n.style.fill=s)}},{key:"printDataLabelsInner",value:function(t,e){var i=this.w,a=t.getAttribute("data:value"),s=i.globals.seriesNames[parseInt(t.parentNode.getAttribute("rel"),10)-1];i.globals.series.length>1&&this.printInnerLabels(e,s,a,t);var r=i.globals.dom.baseEl.querySelector(".apexcharts-datalabels-group");null!==r&&(r.style.opacity=1)}},{key:"drawSpokes",value:function(t){var e=this,i=this.w,a=new Mi(this.ctx),s=i.config.plotOptions.polarArea.spokes;if(0!==s.strokeWidth){for(var r=[],n=360/i.globals.series.length,o=0;o0&&(f=e.getPreviousPath(n));for(var x=0;x=10?t.x>0?(i="start",a+=10):t.x<0&&(i="end",a-=10):i="middle",Math.abs(t.y)>=e-10&&(t.y<0?s-=10:t.y>0&&(s+=10)),{textAnchor:i,newX:a,newY:s}}},{key:"getPreviousPath",value:function(t){for(var e=this.w,i=null,a=0;a0&&parseInt(s.realIndex,10)===parseInt(t,10)&&void 0!==e.globals.previousPaths[a].paths[0]&&(i=e.globals.previousPaths[a].paths[0].d)}return i}},{key:"getDataPointsPos",value:function(t,e){var i=arguments.length>2&&void 0!==arguments[2]?arguments[2]:this.dataPointsLen;t=t||[],e=e||[];for(var a=[],s=0;s=360&&(u=360-Math.abs(this.startAngle)-.1);var g=i.drawPath({d:"",stroke:c,strokeWidth:n*parseInt(h.strokeWidth,10)/100,fill:"none",strokeOpacity:h.opacity,classes:"apexcharts-radialbar-area"});if(h.dropShadow.enabled){var p=h.dropShadow;s.dropShadow(g,p)}l.add(g),g.attr("id","apexcharts-radialbarTrack-"+o),this.animatePaths(g,{centerX:t.centerX,centerY:t.centerY,endAngle:u,startAngle:d,size:t.size,i:o,totalItems:2,animBeginArr:0,dur:0,isTrack:!0})}return a}},{key:"drawArcs",value:function(t){var e=this.w,i=new Mi(this.ctx),a=new ji(this.ctx),s=new Li(this.ctx),r=i.group(),n=this.getStrokeWidth(t);t.size=t.size-n/2;var o=e.config.plotOptions.radialBar.hollow.background,l=t.size-n*t.series.length-this.margin*t.series.length-n*parseInt(e.config.plotOptions.radialBar.track.strokeWidth,10)/100/2,h=l-e.config.plotOptions.radialBar.hollow.margin;void 0!==e.config.plotOptions.radialBar.hollow.image&&(o=this.drawHollowImage(t,r,l,o));var c=this.drawHollow({size:h,centerX:t.centerX,centerY:t.centerY,fill:o||"transparent"});if(e.config.plotOptions.radialBar.hollow.dropShadow.enabled){var d=e.config.plotOptions.radialBar.hollow.dropShadow;s.dropShadow(c,d)}var u=1;!this.radialDataLabels.total.show&&e.globals.series.length>1&&(u=0);var g=null;if(this.radialDataLabels.show){var p=e.globals.dom.Paper.findOne(".apexcharts-datalabels-group");g=this.renderInnerDataLabels(p,this.radialDataLabels,{hollowSize:l,centerX:t.centerX,centerY:t.centerY,opacity:u})}"back"===e.config.plotOptions.radialBar.hollow.position&&(r.add(c),g&&r.add(g));var f=!1;e.config.plotOptions.radialBar.inverseOrder&&(f=!0);for(var x=f?t.series.length-1:0;f?x>=0:x100?100:t.series[x])/100,A=Math.round(this.totalAngle*k)+this.startAngle,C=void 0;e.globals.dataChanged&&(w=this.startAngle,C=Math.round(this.totalAngle*v.negToZero(e.globals.previousPaths[x])/100)+w),Math.abs(A)+Math.abs(y)>360&&(A-=.01),Math.abs(C)+Math.abs(w)>360&&(C-=.01);var S=A-y,L=Array.isArray(e.config.stroke.dashArray)?e.config.stroke.dashArray[x]:e.config.stroke.dashArray,M=i.drawPath({d:"",stroke:m,strokeWidth:n,fill:"none",fillOpacity:e.config.fill.opacity,classes:"apexcharts-radialbar-area apexcharts-radialbar-slice-"+x,strokeDashArray:L});if(Mi.setAttrs(M.node,{"data:angle":S,"data:value":t.series[x]}),e.config.chart.dropShadow.enabled){var P=e.config.chart.dropShadow;s.dropShadow(M,P,x)}if(s.setSelectionFilter(M,0,x),this.addListeners(M,this.radialDataLabels),b.add(M),M.attr({index:0,j:x}),this.barLabels.enabled){var I=v.polarToCartesian(t.centerX,t.centerY,t.size,y),T=this.barLabels.formatter(e.globals.seriesNames[x],{seriesIndex:x,w:e}),z=["apexcharts-radialbar-label"];this.barLabels.onClick||z.push("apexcharts-no-click");var X=this.barLabels.useSeriesColors?e.globals.colors[x]:e.config.chart.foreColor;X||(X=e.config.chart.foreColor);var R=I.x+this.barLabels.offsetX,E=I.y+this.barLabels.offsetY,Y=i.drawText({x:R,y:E,text:T,textAnchor:"end",dominantBaseline:"middle",fontFamily:this.barLabels.fontFamily,fontWeight:this.barLabels.fontWeight,fontSize:this.barLabels.fontSize,foreColor:X,cssClass:z.join(" ")});Y.on("click",this.onBarLabelClick),Y.attr({rel:x+1}),0!==y&&Y.attr({"transform-origin":"".concat(R," ").concat(E),transform:"rotate(".concat(y," 0 0)")}),b.add(Y)}var H=0;!this.initialAnim||e.globals.resized||e.globals.dataChanged||(H=e.config.chart.animations.speed),e.globals.dataChanged&&(H=e.config.chart.animations.dynamicAnimation.speed),this.animDur=H/(1.2*t.series.length)+this.animDur,this.animBeginArr.push(this.animDur),this.animatePaths(M,{centerX:t.centerX,centerY:t.centerY,endAngle:A,startAngle:y,prevEndAngle:C,prevStartAngle:w,size:t.size,i:x,totalItems:2,animBeginArr:this.animBeginArr,dur:H,shouldSetPrevPaths:!0})}return{g:r,elHollow:c,dataLabels:g}}},{key:"drawHollow",value:function(t){var e=new Mi(this.ctx).drawCircle(2*t.size);return e.attr({class:"apexcharts-radialbar-hollow",cx:t.centerX,cy:t.centerY,r:t.size,fill:t.fill}),e}},{key:"drawHollowImage",value:function(t,e,i,a){var s=this.w,r=new ji(this.ctx),n=v.randomId(),o=s.config.plotOptions.radialBar.hollow.image;if(s.config.plotOptions.radialBar.hollow.imageClipped)r.clippedImgArea({width:i,height:i,image:o,patternID:"pattern".concat(s.globals.cuid).concat(n)}),a="url(#pattern".concat(s.globals.cuid).concat(n,")");else{var l=s.config.plotOptions.radialBar.hollow.imageWidth,h=s.config.plotOptions.radialBar.hollow.imageHeight;if(void 0===l&&void 0===h){var c=s.globals.dom.Paper.image(o,(function(e){this.move(t.centerX-e.width/2+s.config.plotOptions.radialBar.hollow.imageOffsetX,t.centerY-e.height/2+s.config.plotOptions.radialBar.hollow.imageOffsetY)}));e.add(c)}else{var d=s.globals.dom.Paper.image(o,(function(e){this.move(t.centerX-l/2+s.config.plotOptions.radialBar.hollow.imageOffsetX,t.centerY-h/2+s.config.plotOptions.radialBar.hollow.imageOffsetY),this.size(l,h)}));e.add(d)}}return a}},{key:"getStrokeWidth",value:function(t){var e=this.w;return t.size*(100-parseInt(e.config.plotOptions.radialBar.hollow.size,10))/100/(t.series.length+1)-this.margin}},{key:"onBarLabelClick",value:function(t){var e=parseInt(t.target.getAttribute("rel"),10)-1,i=this.barLabels.onClick,a=this.w;i&&i(a.globals.seriesNames[e],{w:a,seriesIndex:e})}}]),r}(Ya),Fa=function(t){h(a,t);var e=n(a);function a(){return i(this,a),e.apply(this,arguments)}return s(a,[{key:"draw",value:function(t,e){var i=this.w,a=new Mi(this.ctx);this.rangeBarOptions=this.w.config.plotOptions.rangeBar,this.series=t,this.seriesRangeStart=i.globals.seriesRangeStart,this.seriesRangeEnd=i.globals.seriesRangeEnd,this.barHelpers.initVariables(t);for(var s=a.group({class:"apexcharts-rangebar-series apexcharts-plot-series"}),r=0;r0&&(this.visibleI=this.visibleI+1);var x=0,b=0,m=0;this.yRatio.length>1&&(this.yaxisIndex=i.globals.seriesYAxisReverseMap[g][0],m=g);var y=this.barHelpers.initialPositions(g);d=y.y,h=y.zeroW,c=y.x,b=y.barWidth,x=y.barHeight,n=y.xDivision,o=y.yDivision,l=y.zeroH;for(var w=a.group({class:"apexcharts-datalabels","data:realIndex":g}),k=a.group({class:"apexcharts-rangebar-goals-markers"}),A=0;A0}));return this.isHorizontal?(a=u.config.plotOptions.bar.rangeBarGroupRows?r+h*b:r+o*this.visibleI+h*b,m>-1&&!u.config.plotOptions.bar.rangeBarOverlap&&(g=u.globals.seriesRange[e][m].overlaps).indexOf(p)>-1&&(a=(o=d.barHeight/g.length)*this.visibleI+h*(100-parseInt(this.barOptions.barHeight,10))/100/2+o*(this.visibleI+g.indexOf(p))+h*b)):(b>-1&&!u.globals.timescaleLabels.length&&(s=u.config.plotOptions.bar.rangeBarGroupRows?n+c*b:n+l*this.visibleI+c*b),m>-1&&!u.config.plotOptions.bar.rangeBarOverlap&&(g=u.globals.seriesRange[e][m].overlaps).indexOf(p)>-1&&(s=(l=d.barWidth/g.length)*this.visibleI+c*(100-parseInt(this.barOptions.barWidth,10))/100/2+l*(this.visibleI+g.indexOf(p))+c*b)),{barYPosition:a,barXPosition:s,barHeight:o,barWidth:l}}},{key:"drawRangeColumnPaths",value:function(t){var e=t.indexes,i=t.x,a=t.xDivision,s=t.barWidth,r=t.barXPosition,n=t.zeroH,o=this.w,l=e.i,h=e.j,c=e.realIndex,d=e.translationsIndex,u=this.yRatio[d],g=this.getRangeValue(c,h),p=Math.min(g.start,g.end),f=Math.max(g.start,g.end);void 0===this.series[l][h]||null===this.series[l][h]?p=n:(p=n-p/u,f=n-f/u);var x=Math.abs(f-p),b=this.barHelpers.getColumnPaths({barXPosition:r,barWidth:s,y1:p,y2:f,strokeWidth:this.strokeWidth,series:this.seriesRangeEnd,realIndex:c,i:c,j:h,w:o});if(o.globals.isXNumeric){var m=this.getBarXForNumericXAxis({x:i,j:h,realIndex:c,barWidth:s});i=m.x,r=m.barXPosition}else i+=a;return{pathTo:b.pathTo,pathFrom:b.pathFrom,barHeight:x,x:i,y:g.start<0&&g.end<0?p:f,goalY:this.barHelpers.getGoalValues("y",null,n,l,h,d),barXPosition:r}}},{key:"preventBarOverflow",value:function(t){var e=this.w;return t<0&&(t=0),t>e.globals.gridWidth&&(t=e.globals.gridWidth),t}},{key:"drawRangeBarPaths",value:function(t){var e=t.indexes,i=t.y,a=t.y1,s=t.y2,r=t.yDivision,n=t.barHeight,o=t.barYPosition,l=t.zeroW,h=this.w,c=e.realIndex,d=e.j,u=this.preventBarOverflow(l+a/this.invertedYRatio),g=this.preventBarOverflow(l+s/this.invertedYRatio),p=this.getRangeValue(c,d),f=Math.abs(g-u),x=this.barHelpers.getBarpaths({barYPosition:o,barHeight:n,x1:u,x2:g,strokeWidth:this.strokeWidth,series:this.seriesRangeEnd,i:c,realIndex:c,j:d,w:h});return h.globals.isXNumeric||(i+=r),{pathTo:x.pathTo,pathFrom:x.pathFrom,barWidth:f,x:p.start<0&&p.end<0?u:g,goalX:this.barHelpers.getGoalValues("x",l,null,c,d),y:i}}},{key:"getRangeValue",value:function(t,e){var i=this.w;return{start:i.globals.seriesRangeStart[t][e],end:i.globals.seriesRangeEnd[t][e]}}}]),a}(Ia),Da=function(){function t(e){i(this,t),this.w=e.w,this.lineCtx=e}return s(t,[{key:"sameValueSeriesFix",value:function(t,e){var i=this.w;if(("gradient"===i.config.fill.type||"gradient"===i.config.fill.type[t])&&new Pi(this.lineCtx.ctx,i).seriesHaveSameValues(t)){var a=e[t].slice();a[a.length-1]=a[a.length-1]+1e-6,e[t]=a}return e}},{key:"calculatePoints",value:function(t){var e=t.series,i=t.realIndex,a=t.x,s=t.y,r=t.i,n=t.j,o=t.prevY,l=this.w,h=[],c=[],d=this.lineCtx.categoryAxisCorrection+l.config.markers.offsetX;return l.globals.isXNumeric&&(d=(l.globals.seriesX[i][0]-l.globals.minX)/this.lineCtx.xRatio+l.config.markers.offsetX),0===n&&(h.push(d),c.push(v.isNumber(e[r][0])?o+l.config.markers.offsetY:null)),h.push(a+l.config.markers.offsetX),c.push(v.isNumber(e[r][n+1])?s+l.config.markers.offsetY:null),{x:h,y:c}}},{key:"checkPreviousPaths",value:function(t){for(var e=t.pathFromLine,i=t.pathFromArea,a=t.realIndex,s=this.w,r=0;r0&&parseInt(n.realIndex,10)===parseInt(a,10)&&("line"===n.type?(this.lineCtx.appendPathFrom=!1,e=s.globals.previousPaths[r].paths[0].d):"area"===n.type&&(this.lineCtx.appendPathFrom=!1,i=s.globals.previousPaths[r].paths[0].d,s.config.stroke.show&&s.globals.previousPaths[r].paths[1]&&(e=s.globals.previousPaths[r].paths[1].d)))}return{pathFromLine:e,pathFromArea:i}}},{key:"determineFirstPrevY",value:function(t){var e,i,a,s=t.i,r=t.realIndex,n=t.series,o=t.prevY,l=t.lineYPosition,h=t.translationsIndex,c=this.w,d=c.config.chart.stacked&&!c.globals.comboCharts||c.config.chart.stacked&&c.globals.comboCharts&&(!this.w.config.chart.stackOnlyBar||"bar"===(null===(e=this.w.config.series[r])||void 0===e?void 0:e.type)||"column"===(null===(i=this.w.config.series[r])||void 0===i?void 0:i.type));if(void 0!==(null===(a=n[s])||void 0===a?void 0:a[0]))o=(l=d&&s>0?this.lineCtx.prevSeriesY[s-1][0]:this.lineCtx.zeroY)-n[s][0]/this.lineCtx.yRatio[h]+2*(this.lineCtx.isReversed?n[s][0]/this.lineCtx.yRatio[h]:0);else if(d&&s>0&&void 0===n[s][0])for(var u=s-1;u>=0;u--)if(null!==n[u][0]&&void 0!==n[u][0]){o=l=this.lineCtx.prevSeriesY[u][0];break}return{prevY:o,lineYPosition:l}}}]),t}(),_a=function(t){for(var e,i,a,s,r=function(t){for(var e=[],i=t[0],a=t[1],s=e[0]=Ba(i,a),r=1,n=t.length-1;r9&&(s=3*a/Math.sqrt(s),r[l]=s*e,r[l+1]=s*i);for(var h=0;h<=n;h++)s=(t[Math.min(n,h+1)][0]-t[Math.max(0,h-1)][0])/(6*(1+r[h]*r[h])),o.push([s||0,r[h]*s||0]);return o},Na=function(t){var e=_a(t),i=t[1],a=t[0],s=[],r=e[1],n=e[0];s.push(a,[a[0]+n[0],a[1]+n[1],i[0]-r[0],i[1]-r[1],i[0],i[1]]);for(var o=2,l=e.length;o1&&a[1].length<6){var s=a[0].length;a[1]=[2*a[0][s-2]-a[0][s-4],2*a[0][s-1]-a[0][s-3]].concat(a[1])}a[0]=a[0].slice(-2)}return a};function Ba(t,e){return(e[1]-t[1])/(e[0]-t[0])}var Ga=function(){function t(e,a,s){i(this,t),this.ctx=e,this.w=e.w,this.xyRatios=a,this.pointsChart=!("bubble"!==this.w.config.chart.type&&"scatter"!==this.w.config.chart.type)||s,this.scatter=new Ui(this.ctx),this.noNegatives=this.w.globals.minX===Number.MAX_VALUE,this.lineHelpers=new Da(this),this.markers=new Vi(this.ctx),this.prevSeriesY=[],this.categoryAxisCorrection=0,this.yaxisIndex=0}return s(t,[{key:"draw",value:function(t,e,i,a){var s,r=this.w,n=new Mi(this.ctx),o=r.globals.comboCharts?e:r.config.chart.type,l=n.group({class:"apexcharts-".concat(o,"-series apexcharts-plot-series")}),h=new Pi(this.ctx,r);this.yRatio=this.xyRatios.yRatio,this.zRatio=this.xyRatios.zRatio,this.xRatio=this.xyRatios.xRatio,this.baseLineY=this.xyRatios.baseLineY,t=h.getLogSeries(t),this.yRatio=h.getLogYRatios(this.yRatio),this.prevSeriesY=[];for(var c=[],d=0;d1?g:0;this._initSerieVariables(t,d,g);var f=[],x=[],b=[],m=r.globals.padHorizontal+this.categoryAxisCorrection;this.ctx.series.addCollapsedClassToSeries(this.elSeries,g),r.globals.isXNumeric&&r.globals.seriesX.length>0&&(m=(r.globals.seriesX[g][0]-r.globals.minX)/this.xRatio),b.push(m);var v,y=m,w=void 0,k=y,A=this.zeroY,C=this.zeroY;A=this.lineHelpers.determineFirstPrevY({i:d,realIndex:g,series:t,prevY:A,lineYPosition:0,translationsIndex:p}).prevY,"monotoneCubic"===r.config.stroke.curve&&null===t[d][0]?f.push(null):f.push(A),v=A;"rangeArea"===o&&(w=C=this.lineHelpers.determineFirstPrevY({i:d,realIndex:g,series:a,prevY:C,lineYPosition:0,translationsIndex:p}).prevY,x.push(null!==f[0]?C:null));var S=this._calculatePathsFrom({type:o,series:t,i:d,realIndex:g,translationsIndex:p,prevX:k,prevY:A,prevY2:C}),L=[f[0]],M=[x[0]],P={type:o,series:t,realIndex:g,translationsIndex:p,i:d,x:m,y:1,pX:y,pY:v,pathsFrom:S,linePaths:[],areaPaths:[],seriesIndex:i,lineYPosition:0,xArrj:b,yArrj:f,y2Arrj:x,seriesRangeEnd:a},I=this._iterateOverDataPoints(u(u({},P),{},{iterations:"rangeArea"===o?t[d].length-1:void 0,isRangeStart:!0}));if("rangeArea"===o){for(var T=this._calculatePathsFrom({series:a,i:d,realIndex:g,prevX:k,prevY:C}),z=this._iterateOverDataPoints(u(u({},P),{},{series:a,xArrj:[m],yArrj:L,y2Arrj:M,pY:w,areaPaths:I.areaPaths,pathsFrom:T,iterations:a[d].length-1,isRangeStart:!1})),X=I.linePaths.length/2,R=0;R=0;E--)l.add(c[E]);else for(var Y=0;Y1&&(this.yaxisIndex=a.globals.seriesYAxisReverseMap[i],r=i),this.isReversed=a.config.yaxis[this.yaxisIndex]&&a.config.yaxis[this.yaxisIndex].reversed,this.zeroY=a.globals.gridHeight-this.baseLineY[r]-(this.isReversed?a.globals.gridHeight:0)+(this.isReversed?2*this.baseLineY[r]:0),this.areaBottomY=this.zeroY,(this.zeroY>a.globals.gridHeight||"end"===a.config.plotOptions.area.fillTo)&&(this.areaBottomY=a.globals.gridHeight),this.categoryAxisCorrection=this.xDivision/2,this.elSeries=s.group({class:"apexcharts-series",zIndex:void 0!==a.config.series[i].zIndex?a.config.series[i].zIndex:i,seriesName:v.escapeString(a.globals.seriesNames[i])}),this.elPointsMain=s.group({class:"apexcharts-series-markers-wrap","data:realIndex":i}),a.globals.hasNullValues){var n=this.markers.plotChartMarkers({pointsPos:{x:[0],y:[a.globals.gridHeight+a.globals.markers.largestSize]},seriesIndex:e,j:0,pSize:.1,alwaysDrawMarker:!0,isVirtualPoint:!0});null!==n&&this.elPointsMain.add(n)}this.elDataLabelsWrap=s.group({class:"apexcharts-datalabels","data:realIndex":i});var o=t[e].length===a.globals.dataPoints;this.elSeries.attr({"data:longestSeries":o,rel:e+1,"data:realIndex":i}),this.appendPathFrom=!0}},{key:"_calculatePathsFrom",value:function(t){var e,i,a,s,r=t.type,n=t.series,o=t.i,l=t.realIndex,h=t.translationsIndex,c=t.prevX,d=t.prevY,u=t.prevY2,g=this.w,p=new Mi(this.ctx);if(null===n[o][0]){for(var f=0;f0){var x=this.lineHelpers.checkPreviousPaths({pathFromLine:a,pathFromArea:s,realIndex:l});a=x.pathFromLine,s=x.pathFromArea}return{prevX:c,prevY:d,linePath:e,areaPath:i,pathFromLine:a,pathFromArea:s}}},{key:"_handlePaths",value:function(t){var e=t.type,i=t.realIndex,a=t.i,s=t.paths,r=this.w,n=new Mi(this.ctx),o=new ji(this.ctx);this.prevSeriesY.push(s.yArrj),r.globals.seriesXvalues[i]=s.xArrj,r.globals.seriesYvalues[i]=s.yArrj;var l=r.config.forecastDataPoints;if(l.count>0&&"rangeArea"!==e){var h=r.globals.seriesXvalues[i][r.globals.seriesXvalues[i].length-l.count-1],c=n.drawRect(h,0,r.globals.gridWidth,r.globals.gridHeight,0);r.globals.dom.elForecastMask.appendChild(c.node);var d=n.drawRect(0,0,h,r.globals.gridHeight,0);r.globals.dom.elNonForecastMask.appendChild(d.node)}this.pointsChart||r.globals.delayedElements.push({el:this.elPointsMain.node,index:i});var g={i:a,realIndex:i,animationDelay:a,initialSpeed:r.config.chart.animations.speed,dataChangeSpeed:r.config.chart.animations.dynamicAnimation.speed,className:"apexcharts-".concat(e)};if("area"===e)for(var p=o.fillPath({seriesNumber:i}),f=0;f0&&"rangeArea"!==e){var A=n.renderPaths(w);A.node.setAttribute("stroke-dasharray",l.dashArray),l.strokeWidth&&A.node.setAttribute("stroke-width",l.strokeWidth),this.elSeries.add(A),A.attr("clip-path","url(#forecastMask".concat(r.globals.cuid,")")),k.attr("clip-path","url(#nonForecastMask".concat(r.globals.cuid,")"))}}}}},{key:"_iterateOverDataPoints",value:function(t){var e,i,a=this,s=t.type,r=t.series,n=t.iterations,o=t.realIndex,l=t.translationsIndex,h=t.i,c=t.x,d=t.y,u=t.pX,g=t.pY,p=t.pathsFrom,f=t.linePaths,x=t.areaPaths,b=t.seriesIndex,m=t.lineYPosition,y=t.xArrj,w=t.yArrj,k=t.y2Arrj,A=t.isRangeStart,C=t.seriesRangeEnd,S=this.w,L=new Mi(this.ctx),M=this.yRatio,P=p.prevY,I=p.linePath,T=p.areaPath,z=p.pathFromLine,X=p.pathFromArea,R=v.isNumber(S.globals.minYArr[o])?S.globals.minYArr[o]:S.globals.minY;n||(n=S.globals.dataPoints>1?S.globals.dataPoints-1:S.globals.dataPoints);var E=function(t,e){return e-t/M[l]+2*(a.isReversed?t/M[l]:0)},Y=d,H=S.config.chart.stacked&&!S.globals.comboCharts||S.config.chart.stacked&&S.globals.comboCharts&&(!this.w.config.chart.stackOnlyBar||"bar"===(null===(e=this.w.config.series[o])||void 0===e?void 0:e.type)||"column"===(null===(i=this.w.config.series[o])||void 0===i?void 0:i.type)),O=S.config.stroke.curve;Array.isArray(O)&&(O=Array.isArray(b)?O[b[h]]:O[h]);for(var F,D=0,_=0;_0&&S.globals.collapsedSeries.length0;e--){if(!(S.globals.collapsedSeriesIndices.indexOf((null==b?void 0:b[e])||e)>-1))return e;e--}return 0}(h-1)][_+1]}else m=this.zeroY;else m=this.zeroY;N?d=E(R,m):(d=E(r[h][_+1],m),"rangeArea"===s&&(Y=E(C[h][_+1],m))),y.push(null===r[h][_+1]?null:c),!N||"smooth"!==S.config.stroke.curve&&"monotoneCubic"!==S.config.stroke.curve?(w.push(d),k.push(Y)):(w.push(null),k.push(null));var B=this.lineHelpers.calculatePoints({series:r,x:c,y:d,realIndex:o,i:h,j:_,prevY:P}),G=this._createPaths({type:s,series:r,i:h,realIndex:o,j:_,x:c,y:d,y2:Y,xArrj:y,yArrj:w,y2Arrj:k,pX:u,pY:g,pathState:D,segmentStartX:F,linePath:I,areaPath:T,linePaths:f,areaPaths:x,curve:O,isRangeStart:A});x=G.areaPaths,f=G.linePaths,u=G.pX,g=G.pY,D=G.pathState,F=G.segmentStartX,T=G.areaPath,I=G.linePath,!this.appendPathFrom||S.globals.hasNullValues||"monotoneCubic"===O&&"rangeArea"===s||(z+=L.line(c,this.areaBottomY),X+=L.line(c,this.areaBottomY)),this.handleNullDataPoints(r,B,h,_,o),this._handleMarkersAndLabels({type:s,pointsPos:B,i:h,j:_,realIndex:o,isRangeStart:A})}return{yArrj:w,xArrj:y,pathFromArea:X,areaPaths:x,pathFromLine:z,linePaths:f,linePath:I,areaPath:T}}},{key:"_handleMarkersAndLabels",value:function(t){var e=t.type,i=t.pointsPos,a=t.isRangeStart,s=t.i,r=t.j,n=t.realIndex,o=this.w,l=new qi(this.ctx);if(this.pointsChart)this.scatter.draw(this.elSeries,r,{realIndex:n,pointsPos:i,zRatio:this.zRatio,elParent:this.elPointsMain});else{o.globals.series[s].length>1&&this.elPointsMain.node.classList.add("apexcharts-element-hidden");var h=this.markers.plotChartMarkers({pointsPos:i,seriesIndex:n,j:r+1});null!==h&&this.elPointsMain.add(h)}var c=l.drawDataLabel({type:e,isRangeStart:a,pos:i,i:n,j:r+1});null!==c&&this.elDataLabelsWrap.add(c)}},{key:"_createPaths",value:function(t){var e=t.type,i=t.series,a=t.i;t.realIndex;var s,r=t.j,n=t.x,o=t.y,l=t.xArrj,h=t.yArrj,c=t.y2,d=t.y2Arrj,u=t.pX,g=t.pY,p=t.pathState,f=t.segmentStartX,x=t.linePath,b=t.areaPath,m=t.linePaths,v=t.areaPaths,y=t.curve,w=t.isRangeStart,k=new Mi(this.ctx),A=this.areaBottomY,C="rangeArea"===e,S="rangeArea"===e&&w;switch(y){case"monotoneCubic":var L=w?h:d;switch(p){case 0:if(null===L[r+1])break;p=1;case 1:if(!(C?l.length===i[a].length:r===i[a].length-2))break;case 2:var M=w?l:l.slice().reverse(),P=w?L:L.slice().reverse(),I=(s=P,M.map((function(t,e){return[t,s[e]]})).filter((function(t){return null!==t[1]}))),T=I.length>1?Na(I):I,z=[];C&&(S?v=I:z=v.reverse());var X=0,R=0;if(function(t,e){for(var i=function(t){var e=[],i=0;return t.forEach((function(t){null!==t?i++:i>0&&(e.push(i),i=0)})),i>0&&e.push(i),e}(t),a=[],s=0,r=0;s4?(e+="C".concat(a[0],", ").concat(a[1]),e+=", ".concat(a[2],", ").concat(a[3]),e+=", ".concat(a[4],", ").concat(a[5])):s>2&&(e+="S".concat(a[0],", ").concat(a[1]),e+=", ".concat(a[2],", ").concat(a[3]))}return e}(t),i=R,a=(R+=t.length)-1;S?x=k.move(I[i][0],I[i][1])+e:C?x=k.move(z[i][0],z[i][1])+k.line(I[i][0],I[i][1])+e+k.line(z[a][0],z[a][1]):(x=k.move(I[i][0],I[i][1])+e,b=x+k.line(I[a][0],A)+k.line(I[i][0],A)+"z",v.push(b)),m.push(x)})),C&&X>1&&!S){var E=m.slice(X).reverse();m.splice(X),E.forEach((function(t){return m.push(t)}))}p=0}break;case"smooth":var Y=.35*(n-u);if(null===i[a][r])p=0;else switch(p){case 0:if(f=u,x=S?k.move(u,d[r])+k.line(u,g):k.move(u,g),b=k.move(u,g),null===i[a][r+1]||void 0===i[a][r+1]){m.push(x),v.push(b);break}if(p=1,r=i[a].length-2&&(S&&(x+=k.curve(n,o,n,o,n,c)+k.move(n,c)),b+=k.curve(n,o,n,o,n,A)+k.line(f,A)+"z",m.push(x),v.push(b),p=-1)}}u=n,g=o;break;default:var F=function(t,e,i){var a=[];switch(t){case"stepline":a=k.line(e,null,"H")+k.line(null,i,"V");break;case"linestep":a=k.line(null,i,"V")+k.line(e,null,"H");break;case"straight":a=k.line(e,i)}return a};if(null===i[a][r])p=0;else switch(p){case 0:if(f=u,x=S?k.move(u,d[r])+k.line(u,g):k.move(u,g),b=k.move(u,g),null===i[a][r+1]||void 0===i[a][r+1]){m.push(x),v.push(b);break}if(p=1,r=i[a].length-2&&(S&&(x+=k.line(n,c)),b+=k.line(n,A)+k.line(f,A)+"z",m.push(x),v.push(b),p=-1)}}u=n,g=o}return{linePaths:m,areaPaths:v,pX:u,pY:g,pathState:p,segmentStartX:f,linePath:x,areaPath:b}}},{key:"handleNullDataPoints",value:function(t,e,i,a,s){var r=this.w;if(null===t[i][a]&&r.config.markers.showNullDataPoints||1===t[i].length){var n=this.strokeWidth-r.config.markers.strokeWidth/2;n>0||(n=0);var o=this.markers.plotChartMarkers({pointsPos:e,seriesIndex:s,j:a+1,pSize:n,alwaysDrawMarker:!0});null!==o&&this.elPointsMain.add(o)}}}]),t}();window.TreemapSquared={},window.TreemapSquared.generate=function(){function t(e,i,a,s){this.xoffset=e,this.yoffset=i,this.height=s,this.width=a,this.shortestEdge=function(){return Math.min(this.height,this.width)},this.getCoordinates=function(t){var e,i=[],a=this.xoffset,s=this.yoffset,n=r(t)/this.height,o=r(t)/this.width;if(this.width>=this.height)for(e=0;e=this.height){var a=e/this.height,s=this.width-a;i=new t(this.xoffset+a,this.yoffset,s,this.height)}else{var r=e/this.width,n=this.height-r;i=new t(this.xoffset,this.yoffset+r,this.width,n)}return i}}function e(e,a,s,n,o){n=void 0===n?0:n,o=void 0===o?0:o;var l=i(function(t,e){var i,a=[],s=e/r(t);for(i=0;i=n}(e,l=t[0],o)?(e.push(l),i(t.slice(1),e,s,n)):(h=s.cutArea(r(e),n),n.push(s.getCoordinates(e)),i(t,[],h,n)),n;n.push(s.getCoordinates(e))}function a(t,e){var i=Math.min.apply(Math,t),a=Math.max.apply(Math,t),s=r(t);return Math.max(Math.pow(e,2)*a/Math.pow(s,2),Math.pow(s,2)/(Math.pow(e,2)*i))}function s(t){return t&&t.constructor===Array}function r(t){var e,i=0;for(e=0;e1&&u&&u.show){var g=i.config.series[o].name||"";if(g&&d.xMin<1/0&&d.yMin<1/0){var p=u.offsetX,f=u.offsetY,x=u.borderColor,b=u.borderWidth,m=u.borderRadius,y=u.style,w=y.color||i.config.chart.foreColor,k={left:y.padding.left,right:y.padding.right,top:y.padding.top,bottom:y.padding.bottom},A=a.getTextRects(g,y.fontSize,y.fontFamily),C=A.width+k.left+k.right,S=A.height+k.top+k.bottom,L=d.xMin+(p||0),M=d.yMin+(f||0),P=a.drawRect(L,M,C,S,m,y.background,1,b,x),I=a.drawText({x:L+k.left,y:M+k.top+.75*A.height,text:g,fontSize:y.fontSize,fontFamily:y.fontFamily,fontWeight:y.fontWeight,foreColor:w,cssClass:y.cssClass||""});l.add(P),l.add(I)}}l.add(c),r.add(l)})),r}},{key:"getFontSize",value:function(t){var e=this.w;var i=function t(e){var i,a=0;if(Array.isArray(e[0]))for(i=0;ir-a&&l.width<=n-s){var h=o.rotateAroundCenter(t.node);t.node.setAttribute("transform","rotate(-90 ".concat(h.x," ").concat(h.y,") translate(").concat(l.height/3,")"))}}},{key:"truncateLabels",value:function(t,e,i,a,s,r){var n=new Mi(this.ctx),o=n.getTextRects(t,e).width+this.w.config.stroke.width+5>s-i&&r-a>s-i?r-a:s-i,l=n.getTextBasedOnMaxWidth({text:t,maxWidth:o,fontSize:e});return t.length!==l.length&&o/e<5?"":l}},{key:"animateTreemap",value:function(t,e,i,a){var s=new y(this.ctx);s.animateRect(t,e,i,a,(function(){s.animationCompleted(t)}))}}]),t}(),Va=86400,Ua=10/Va,qa=function(){function t(e){i(this,t),this.ctx=e,this.w=e.w,this.timeScaleArray=[],this.utc=this.w.config.xaxis.labels.datetimeUTC}return s(t,[{key:"calculateTimeScaleTicks",value:function(t,e){var i=this,a=this.w;if(a.globals.allSeriesCollapsed)return a.globals.labels=[],a.globals.timescaleLabels=[],[];var s=new zi(this.ctx),r=(e-t)/864e5;this.determineInterval(r),a.globals.disableZoomIn=!1,a.globals.disableZoomOut=!1,r5e4&&(a.globals.disableZoomOut=!0);var n=s.getTimeUnitsfromTimestamp(t,e,this.utc),o=a.globals.gridWidth/r,l=o/24,h=l/60,c=h/60,d=Math.floor(24*r),g=Math.floor(1440*r),p=Math.floor(r*Va),f=Math.floor(r),x=Math.floor(r/30),b=Math.floor(r/365),m={minMillisecond:n.minMillisecond,minSecond:n.minSecond,minMinute:n.minMinute,minHour:n.minHour,minDate:n.minDate,minMonth:n.minMonth,minYear:n.minYear},v={firstVal:m,currentMillisecond:m.minMillisecond,currentSecond:m.minSecond,currentMinute:m.minMinute,currentHour:m.minHour,currentMonthDate:m.minDate,currentDate:m.minDate,currentMonth:m.minMonth,currentYear:m.minYear,daysWidthOnXAxis:o,hoursWidthOnXAxis:l,minutesWidthOnXAxis:h,secondsWidthOnXAxis:c,numberOfSeconds:p,numberOfMinutes:g,numberOfHours:d,numberOfDays:f,numberOfMonths:x,numberOfYears:b};switch(this.tickInterval){case"years":this.generateYearScale(v);break;case"months":case"half_year":this.generateMonthScale(v);break;case"months_days":case"months_fortnight":case"days":case"week_days":this.generateDayScale(v);break;case"hours":this.generateHourScale(v);break;case"minutes_fives":case"minutes":this.generateMinuteScale(v);break;case"seconds_tens":case"seconds_fives":case"seconds":this.generateSecondScale(v)}var y=this.timeScaleArray.map((function(t){var e={position:t.position,unit:t.unit,year:t.year,day:t.day?t.day:1,hour:t.hour?t.hour:0,month:t.month+1};return"month"===t.unit?u(u({},e),{},{day:1,value:t.value+1}):"day"===t.unit||"hour"===t.unit?u(u({},e),{},{value:t.value}):"minute"===t.unit?u(u({},e),{},{value:t.value,minute:t.value}):"second"===t.unit?u(u({},e),{},{value:t.value,minute:t.minute,second:t.second}):t}));return y.filter((function(t){var e=1,s=Math.ceil(a.globals.gridWidth/120),r=t.value;void 0!==a.config.xaxis.tickAmount&&(s=a.config.xaxis.tickAmount),y.length>s&&(e=Math.floor(y.length/s));var n=!1,o=!1;switch(i.tickInterval){case"years":"year"===t.unit&&(n=!0);break;case"half_year":e=7,"year"===t.unit&&(n=!0);break;case"months":e=1,"year"===t.unit&&(n=!0);break;case"months_fortnight":e=15,"year"!==t.unit&&"month"!==t.unit||(n=!0),30===r&&(o=!0);break;case"months_days":e=10,"month"===t.unit&&(n=!0),30===r&&(o=!0);break;case"week_days":e=8,"month"===t.unit&&(n=!0);break;case"days":e=1,"month"===t.unit&&(n=!0);break;case"hours":"day"===t.unit&&(n=!0);break;case"minutes_fives":case"seconds_fives":r%5!=0&&(o=!0);break;case"seconds_tens":r%10!=0&&(o=!0)}if("hours"===i.tickInterval||"minutes_fives"===i.tickInterval||"seconds_tens"===i.tickInterval||"seconds_fives"===i.tickInterval){if(!o)return!0}else if((r%e==0||n)&&!o)return!0}))}},{key:"recalcDimensionsBasedOnFormat",value:function(t,e){var i=this.w,a=this.formatDates(t),s=this.removeOverlappingTS(a);i.globals.timescaleLabels=s.slice(),new fa(this.ctx).plotCoords()}},{key:"determineInterval",value:function(t){var e=24*t,i=60*e;switch(!0){case t/365>5:this.tickInterval="years";break;case t>800:this.tickInterval="half_year";break;case t>180:this.tickInterval="months";break;case t>90:this.tickInterval="months_fortnight";break;case t>60:this.tickInterval="months_days";break;case t>30:this.tickInterval="week_days";break;case t>2:this.tickInterval="days";break;case e>2.4:this.tickInterval="hours";break;case i>15:this.tickInterval="minutes_fives";break;case i>5:this.tickInterval="minutes";break;case i>1:this.tickInterval="seconds_tens";break;case 60*i>20:this.tickInterval="seconds_fives";break;default:this.tickInterval="seconds"}}},{key:"generateYearScale",value:function(t){var e=t.firstVal,i=t.currentMonth,a=t.currentYear,s=t.daysWidthOnXAxis,r=t.numberOfYears,n=e.minYear,o=0,l=new zi(this.ctx),h="year";if(e.minDate>1||e.minMonth>0){var c=l.determineRemainingDaysOfYear(e.minYear,e.minMonth,e.minDate);o=(l.determineDaysOfYear(e.minYear)-c+1)*s,n=e.minYear+1,this.timeScaleArray.push({position:o,value:n,unit:h,year:n,month:v.monthMod(i+1)})}else 1===e.minDate&&0===e.minMonth&&this.timeScaleArray.push({position:o,value:n,unit:h,year:a,month:v.monthMod(i+1)});for(var d=n,u=o,g=0;g1){l=(h.determineDaysOfMonths(a+1,e.minYear)-i+1)*r,o=v.monthMod(a+1);var u=s+d,g=v.monthMod(o),p=o;0===o&&(c="year",p=u,g=1,u+=d+=1),this.timeScaleArray.push({position:l,value:p,unit:c,year:u,month:g})}else this.timeScaleArray.push({position:l,value:o,unit:c,year:s,month:v.monthMod(a)});for(var f=o+1,x=l,b=0,m=1;bn.determineDaysOfMonths(e+1,i)?(h=1,o="month",u=e+=1,e):e},d=(24-e.minHour)*s,u=l,g=c(h,i,a);0===e.minHour&&1===e.minDate?(d=0,u=v.monthMod(e.minMonth),o="month",h=e.minDate):1!==e.minDate&&0===e.minHour&&0===e.minMinute&&(d=0,l=e.minDate,u=l,g=c(h=l,i,a),1!==u&&(o="day")),this.timeScaleArray.push({position:d,value:u,unit:o,year:this._getYear(a,g,0),month:v.monthMod(g),day:h});for(var p=d,f=0;fo.determineDaysOfMonths(e+1,s)&&(f=1,e+=1),{month:e,date:f}},c=function(t,e){return t>o.determineDaysOfMonths(e+1,s)?e+=1:e},d=60-(e.minMinute+e.minSecond/60),u=d*r,g=e.minHour+1,p=g;60===d&&(u=0,p=g=e.minHour);var f=i;p>=24&&(p=0,l="day",g=f+=1);var x=h(f,a).month;x=c(f,x),g>31&&(g=f=1),this.timeScaleArray.push({position:u,value:g,unit:l,day:f,hour:p,year:s,month:v.monthMod(x)}),p++;for(var b=u,m=0;m=24)p=0,l="day",x=h(f+=1,x).month,x=c(f,x);var y=this._getYear(s,x,0);b=60*r+b;var w=0===p?f:p;this.timeScaleArray.push({position:b,value:w,unit:l,hour:p,day:f,year:y,month:v.monthMod(x)}),p++}}},{key:"generateMinuteScale",value:function(t){for(var e=t.currentMillisecond,i=t.currentSecond,a=t.currentMinute,s=t.currentHour,r=t.currentDate,n=t.currentMonth,o=t.currentYear,l=t.minutesWidthOnXAxis,h=t.secondsWidthOnXAxis,c=t.numberOfMinutes,d=a+1,u=r,g=n,p=o,f=s,x=(60-i-e/1e3)*h,b=0;b=60&&(d=0,24===(f+=1)&&(f=0)),this.timeScaleArray.push({position:x,value:d,unit:"minute",hour:f,minute:d,day:u,year:this._getYear(p,g,0),month:v.monthMod(g)}),x+=l,d++}},{key:"generateSecondScale",value:function(t){for(var e=t.currentMillisecond,i=t.currentSecond,a=t.currentMinute,s=t.currentHour,r=t.currentDate,n=t.currentMonth,o=t.currentYear,l=t.secondsWidthOnXAxis,h=t.numberOfSeconds,c=i+1,d=a,u=r,g=n,p=o,f=s,x=(1e3-e)/1e3*l,b=0;b=60&&(c=0,++d>=60&&(d=0,24===++f&&(f=0))),this.timeScaleArray.push({position:x,value:c,unit:"second",hour:f,minute:d,second:c,day:u,year:this._getYear(p,g,0),month:v.monthMod(g)}),x+=l,c++}},{key:"createRawDateString",value:function(t,e){var i=t.year;return 0===t.month&&(t.month=1),i+="-"+("0"+t.month.toString()).slice(-2),"day"===t.unit?i+="day"===t.unit?"-"+("0"+e).slice(-2):"-01":i+="-"+("0"+(t.day?t.day:"1")).slice(-2),"hour"===t.unit?i+="hour"===t.unit?"T"+("0"+e).slice(-2):"T00":i+="T"+("0"+(t.hour?t.hour:"0")).slice(-2),"minute"===t.unit?i+=":"+("0"+e).slice(-2):i+=":"+(t.minute?("0"+t.minute).slice(-2):"00"),"second"===t.unit?i+=":"+("0"+e).slice(-2):i+=":00",this.utc&&(i+=".000Z"),i}},{key:"formatDates",value:function(t){var e=this,i=this.w;return t.map((function(t){var a=t.value.toString(),s=new zi(e.ctx),r=e.createRawDateString(t,a),n=s.getDate(s.parseDate(r));if(e.utc||(n=s.getDate(s.parseDateWithTimezone(r))),void 0===i.config.xaxis.labels.format){var o="dd MMM",l=i.config.xaxis.labels.datetimeFormatter;"year"===t.unit&&(o=l.year),"month"===t.unit&&(o=l.month),"day"===t.unit&&(o=l.day),"hour"===t.unit&&(o=l.hour),"minute"===t.unit&&(o=l.minute),"second"===t.unit&&(o=l.second),a=s.formatDate(n,o)}else a=s.formatDate(n,i.config.xaxis.labels.format);return{dateString:r,position:t.position,value:a,unit:t.unit,year:t.year,month:t.month}}))}},{key:"removeOverlappingTS",value:function(t){var e,i=this,a=new Mi(this.ctx),s=!1;t.length>0&&t[0].value&&t.every((function(e){return e.value.length===t[0].value.length}))&&(s=!0,e=a.getTextRects(t[0].value).width);var r=0,n=t.map((function(n,o){if(o>0&&i.w.config.xaxis.labels.hideOverlappingLabels){var l=s?e:a.getTextRects(t[r].value).width,h=t[r].position;return n.position>h+l+10?(r=o,n):null}return n}));return n=n.filter((function(t){return null!==t}))}},{key:"_getYear",value:function(t,e,i){return t+Math.floor(e/12)+i}}]),t}(),Za=function(){function t(e,a){i(this,t),this.ctx=a,this.w=a.w,this.el=e}return s(t,[{key:"setupElements",value:function(){var t=this.w,e=t.globals,i=t.config,a=i.chart.type;e.axisCharts=["line","area","bar","rangeBar","rangeArea","candlestick","boxPlot","scatter","bubble","radar","heatmap","treemap"].includes(a),e.xyCharts=["line","area","bar","rangeBar","rangeArea","candlestick","boxPlot","scatter","bubble"].includes(a),e.isBarHorizontal=["bar","rangeBar","boxPlot"].includes(a)&&i.plotOptions.bar.horizontal,e.chartClass=".apexcharts".concat(e.chartID),e.dom.baseEl=this.el,e.dom.elWrap=document.createElement("div"),Mi.setAttrs(e.dom.elWrap,{id:e.chartClass.substring(1),class:"apexcharts-canvas ".concat(e.chartClass.substring(1))}),this.el.appendChild(e.dom.elWrap),e.dom.Paper=window.SVG().addTo(e.dom.elWrap),e.dom.Paper.attr({class:"apexcharts-svg","xmlns:data":"ApexChartsNS",transform:"translate(".concat(i.chart.offsetX,", ").concat(i.chart.offsetY,")")}),e.dom.Paper.node.style.background="dark"!==i.theme.mode||i.chart.background?"light"!==i.theme.mode||i.chart.background?i.chart.background:"#fff":"#343A3F",this.setSVGDimensions(),e.dom.elLegendForeign=document.createElementNS(e.SVGNS,"foreignObject"),Mi.setAttrs(e.dom.elLegendForeign,{x:0,y:0,width:e.svgWidth,height:e.svgHeight}),e.dom.elLegendWrap=document.createElement("div"),e.dom.elLegendWrap.classList.add("apexcharts-legend"),e.dom.elWrap.appendChild(e.dom.elLegendWrap),e.dom.Paper.node.appendChild(e.dom.elLegendForeign),e.dom.elGraphical=e.dom.Paper.group().attr({class:"apexcharts-inner apexcharts-graphical"}),e.dom.elDefs=e.dom.Paper.defs(),e.dom.Paper.add(e.dom.elGraphical),e.dom.elGraphical.add(e.dom.elDefs)}},{key:"plotChartType",value:function(t,e){var i=this.w,a=this.ctx,s=i.config,r=i.globals,n={line:{series:[],i:[]},area:{series:[],i:[]},scatter:{series:[],i:[]},bubble:{series:[],i:[]},bar:{series:[],i:[]},candlestick:{series:[],i:[]},boxPlot:{series:[],i:[]},rangeBar:{series:[],i:[]},rangeArea:{series:[],seriesRangeEnd:[],i:[]}},o=s.chart.type||"line",l=null,h=0;r.series.forEach((function(e,a){var s,c,d="column"===(null===(s=t[a])||void 0===s?void 0:s.type)?"bar":(null===(c=t[a])||void 0===c?void 0:c.type)||("column"===o?"bar":o);n[d]?("rangeArea"===d?(n[d].series.push(r.seriesRangeStart[a]),n[d].seriesRangeEnd.push(r.seriesRangeEnd[a])):n[d].series.push(e),n[d].i.push(a),"bar"===d&&(i.globals.columnSeries=n.bar)):["heatmap","treemap","pie","donut","polarArea","radialBar","radar"].includes(d)?l=d:console.warn("You have specified an unrecognized series type (".concat(d,").")),o!==d&&"scatter"!==d&&h++})),h>0&&(l&&console.warn("Chart or series type ".concat(l," cannot appear with other chart or series types.")),n.bar.series.length>0&&s.plotOptions.bar.horizontal&&(h-=n.bar.series.length,n.bar={series:[],i:[]},i.globals.columnSeries={series:[],i:[]},console.warn("Horizontal bars are not supported in a mixed/combo chart. Please turn off `plotOptions.bar.horizontal`"))),r.comboCharts||(r.comboCharts=h>0);var c=new Ga(a,e),d=new za(a,e);a.pie=new Ya(a);var u=new Oa(a);a.rangeBar=new Fa(a,e);var g=new Ha(a),p=[];if(r.comboCharts){var x,b,m=new Pi(a);if(n.area.series.length>0)(x=p).push.apply(x,f(m.drawSeriesByGroup(n.area,r.areaGroups,"area",c)));if(n.bar.series.length>0)if(s.chart.stacked){var v=new Ta(a,e);p.push(v.draw(n.bar.series,n.bar.i))}else a.bar=new Ia(a,e),p.push(a.bar.draw(n.bar.series,n.bar.i));if(n.rangeArea.series.length>0&&p.push(c.draw(n.rangeArea.series,"rangeArea",n.rangeArea.i,n.rangeArea.seriesRangeEnd)),n.line.series.length>0)(b=p).push.apply(b,f(m.drawSeriesByGroup(n.line,r.lineGroups,"line",c)));if(n.candlestick.series.length>0&&p.push(d.draw(n.candlestick.series,"candlestick",n.candlestick.i)),n.boxPlot.series.length>0&&p.push(d.draw(n.boxPlot.series,"boxPlot",n.boxPlot.i)),n.rangeBar.series.length>0&&p.push(a.rangeBar.draw(n.rangeBar.series,n.rangeBar.i)),n.scatter.series.length>0){var y=new Ga(a,e,!0);p.push(y.draw(n.scatter.series,"scatter",n.scatter.i))}if(n.bubble.series.length>0){var w=new Ga(a,e,!0);p.push(w.draw(n.bubble.series,"bubble",n.bubble.i))}}else switch(s.chart.type){case"line":p=c.draw(r.series,"line");break;case"area":p=c.draw(r.series,"area");break;case"bar":if(s.chart.stacked)p=new Ta(a,e).draw(r.series);else a.bar=new Ia(a,e),p=a.bar.draw(r.series);break;case"candlestick":p=new za(a,e).draw(r.series,"candlestick");break;case"boxPlot":p=new za(a,e).draw(r.series,s.chart.type);break;case"rangeBar":p=a.rangeBar.draw(r.series);break;case"rangeArea":p=c.draw(r.seriesRangeStart,"rangeArea",void 0,r.seriesRangeEnd);break;case"heatmap":p=new Ra(a,e).draw(r.series);break;case"treemap":p=new ja(a,e).draw(r.series);break;case"pie":case"donut":case"polarArea":p=a.pie.draw(r.series);break;case"radialBar":p=u.draw(r.series);break;case"radar":p=g.draw(r.series);break;default:p=c.draw(r.series)}return p}},{key:"setSVGDimensions",value:function(){var t=this.w,e=t.globals,i=t.config;i.chart.width=i.chart.width||"100%",i.chart.height=i.chart.height||"auto",e.svgWidth=i.chart.width,e.svgHeight=i.chart.height;var a=v.getDimensions(this.el),s=i.chart.width.toString().split(/[0-9]+/g).pop();"%"===s?v.isNumber(a[0])&&(0===a[0].width&&(a=v.getDimensions(this.el.parentNode)),e.svgWidth=a[0]*parseInt(i.chart.width,10)/100):"px"!==s&&""!==s||(e.svgWidth=parseInt(i.chart.width,10));var r=String(i.chart.height).toString().split(/[0-9]+/g).pop();if("auto"!==e.svgHeight&&""!==e.svgHeight)if("%"===r){var n=v.getDimensions(this.el.parentNode);e.svgHeight=n[1]*parseInt(i.chart.height,10)/100}else e.svgHeight=parseInt(i.chart.height,10);else e.svgHeight=e.axisCharts?e.svgWidth/1.61:e.svgWidth/1.2;if(e.svgWidth=Math.max(e.svgWidth,0),e.svgHeight=Math.max(e.svgHeight,0),Mi.setAttrs(e.dom.Paper.node,{width:e.svgWidth,height:e.svgHeight}),"%"!==r){var o=i.chart.sparkline.enabled?0:e.axisCharts?i.chart.parentHeightOffset:0;e.dom.Paper.node.parentNode.parentNode.style.minHeight="".concat(e.svgHeight+o,"px")}e.dom.elWrap.style.width="".concat(e.svgWidth,"px"),e.dom.elWrap.style.height="".concat(e.svgHeight,"px")}},{key:"shiftGraphPosition",value:function(){var t=this.w.globals,e=t.translateY,i=t.translateX;Mi.setAttrs(t.dom.elGraphical.node,{transform:"translate(".concat(i,", ").concat(e,")")})}},{key:"resizeNonAxisCharts",value:function(){var t=this.w,e=t.globals,i=0,a=t.config.chart.sparkline.enabled?1:15;a+=t.config.grid.padding.bottom,["top","bottom"].includes(t.config.legend.position)&&t.config.legend.show&&!t.config.legend.floating&&(i=new ba(this.ctx).legendHelpers.getLegendDimensions().clwh+7);var s=t.globals.dom.baseEl.querySelector(".apexcharts-radialbar, .apexcharts-pie"),r=2.05*t.globals.radialSize;if(s&&!t.config.chart.sparkline.enabled&&0!==t.config.plotOptions.radialBar.startAngle){var n=v.getBoundingClientRect(s);r=n.bottom;var o=n.bottom-n.top;r=Math.max(2.05*t.globals.radialSize,o)}var l=Math.ceil(r+e.translateY+i+a);e.dom.elLegendForeign&&e.dom.elLegendForeign.setAttribute("height",l),t.config.chart.height&&String(t.config.chart.height).includes("%")||(e.dom.elWrap.style.height="".concat(l,"px"),Mi.setAttrs(e.dom.Paper.node,{height:l}),e.dom.Paper.node.parentNode.parentNode.style.minHeight="".concat(l,"px"))}},{key:"coreCalculations",value:function(){new ia(this.ctx).init()}},{key:"resetGlobals",value:function(){var t=this,e=function(){return t.w.config.series.map((function(){return[]}))},i=new Bi,a=this.w.globals,s={dataWasParsed:a.dataWasParsed,originalSeries:a.originalSeries};i.initGlobalVars(a),a.seriesXvalues=e(),a.seriesYvalues=e(),s.dataWasParsed&&(a.dataWasParsed=s.dataWasParsed,a.originalSeries=s.originalSeries)}},{key:"isMultipleY",value:function(){return!!(Array.isArray(this.w.config.yaxis)&&this.w.config.yaxis.length>1)&&(this.w.globals.isMultipleYAxis=!0,!0)}},{key:"xySettings",value:function(){var t=this.w,e=null;if(t.globals.axisCharts){if("back"===t.config.xaxis.crosshairs.position&&new oa(this.ctx).drawXCrosshairs(),"back"===t.config.yaxis[0].crosshairs.position&&new oa(this.ctx).drawYCrosshairs(),"datetime"===t.config.xaxis.type&&void 0===t.config.xaxis.labels.formatter){this.ctx.timeScale=new qa(this.ctx);var i=[];isFinite(t.globals.minX)&&isFinite(t.globals.maxX)&&!t.globals.isBarHorizontal?i=this.ctx.timeScale.calculateTimeScaleTicks(t.globals.minX,t.globals.maxX):t.globals.isBarHorizontal&&(i=this.ctx.timeScale.calculateTimeScaleTicks(t.globals.minY,t.globals.maxY)),this.ctx.timeScale.recalcDimensionsBasedOnFormat(i)}e=new Pi(this.ctx).getCalculatedRatios()}return e}},{key:"updateSourceChart",value:function(t){this.ctx.w.globals.selection=void 0,this.ctx.updateHelpers._updateOptions({chart:{selection:{xaxis:{min:t.w.globals.minX,max:t.w.globals.maxX}}}},!1,!1)}},{key:"setupBrushHandler",value:function(){var t=this,e=this.ctx,i=this.w;if(i.config.chart.brush.enabled&&"function"!=typeof i.config.chart.events.selection){var a=Array.isArray(i.config.chart.brush.targets)?i.config.chart.brush.targets:[i.config.chart.brush.target];a.forEach((function(i){var a=e.constructor.getChartByID(i);a.w.globals.brushSource=t.ctx,"function"!=typeof a.w.config.chart.events.zoomed&&(a.w.config.chart.events.zoomed=function(){return t.updateSourceChart(a)}),"function"!=typeof a.w.config.chart.events.scrolled&&(a.w.config.chart.events.scrolled=function(){return t.updateSourceChart(a)})})),i.config.chart.events.selection=function(t,i){a.forEach((function(t){e.constructor.getChartByID(t).ctx.updateHelpers._updateOptions({xaxis:{min:i.xaxis.min,max:i.xaxis.max}},!1,!1,!1,!1)}))}}}}]),t}(),$a=function(){function t(e){i(this,t),this.ctx=e,this.w=e.w}return s(t,[{key:"_updateOptions",value:function(t){var e=this,i=arguments.length>1&&void 0!==arguments[1]&&arguments[1],a=!(arguments.length>2&&void 0!==arguments[2])||arguments[2],s=!(arguments.length>3&&void 0!==arguments[3])||arguments[3],r=arguments.length>4&&void 0!==arguments[4]&&arguments[4];return new Promise((function(n){var o=[e.ctx];s&&(o=e.ctx.getSyncedCharts()),e.ctx.w.globals.isExecCalled&&(o=[e.ctx],e.ctx.w.globals.isExecCalled=!1),o.forEach((function(s,l){var h=s.w;if(h.globals.shouldAnimate=a,i||(h.globals.resized=!0,h.globals.dataChanged=!0,a&&s.series.getPreviousPaths()),t&&"object"===b(t)&&(s.config=new Wi(t),t=Pi.extendArrayProps(s.config,t,h),s.w.globals.chartID!==e.ctx.w.globals.chartID&&delete t.series,h.config=v.extend(h.config,t),r&&(h.globals.lastXAxis=t.xaxis?v.clone(t.xaxis):[],h.globals.lastYAxis=t.yaxis?v.clone(t.yaxis):[],h.globals.initialConfig=v.extend({},h.config),h.globals.initialSeries=v.clone(h.config.series),t.series))){for(var c=0;c2&&void 0!==arguments[2]&&arguments[2];return new Promise((function(s){var r=i.w;return r.globals.shouldAnimate=e,r.globals.dataChanged=!0,e&&i.ctx.series.getPreviousPaths(),i.ctx.data.resetParsingFlags(),i.ctx.data.parseData(t),a&&(r.globals.initialConfig.series=v.clone(r.config.series),r.globals.initialSeries=v.clone(r.config.series)),i.ctx.update().then((function(){s(i.ctx)}))}))}},{key:"_extendSeries",value:function(t,e){var i=this.w,a=i.config.series[e];return u(u({},i.config.series[e]),{},{name:t.name?t.name:null==a?void 0:a.name,color:t.color?t.color:null==a?void 0:a.color,type:t.type?t.type:null==a?void 0:a.type,group:t.group?t.group:null==a?void 0:a.group,hidden:void 0!==t.hidden?t.hidden:null==a?void 0:a.hidden,data:t.data?t.data:null==a?void 0:a.data,zIndex:void 0!==t.zIndex?t.zIndex:e})}},{key:"toggleDataPointSelection",value:function(t,e){var i=this.w,a=null,s=".apexcharts-series[data\\:realIndex='".concat(t,"']");return i.globals.axisCharts?a=i.globals.dom.Paper.findOne("".concat(s," path[j='").concat(e,"'], ").concat(s," circle[j='").concat(e,"'], ").concat(s," rect[j='").concat(e,"']")):void 0===e&&(a=i.globals.dom.Paper.findOne("".concat(s," path[j='").concat(t,"']")),"pie"!==i.config.chart.type&&"polarArea"!==i.config.chart.type&&"donut"!==i.config.chart.type||this.ctx.pie.pieClicked(t)),a?(new Mi(this.ctx).pathMouseDown(a,null),a.node?a.node:null):(console.warn("toggleDataPointSelection: Element not found"),null)}},{key:"forceXAxisUpdate",value:function(t){var e=this.w;if(["min","max"].forEach((function(i){void 0!==t.xaxis[i]&&(e.config.xaxis[i]=t.xaxis[i],e.globals.lastXAxis[i]=t.xaxis[i])})),t.xaxis.categories&&t.xaxis.categories.length&&(e.config.xaxis.categories=t.xaxis.categories),e.config.xaxis.convertedCatToNumeric){var i=new Ni(t);t=i.convertCatToNumericXaxis(t,this.ctx)}return t}},{key:"forceYAxisUpdate",value:function(t){return t.chart&&t.chart.stacked&&"100%"===t.chart.stackType&&(Array.isArray(t.yaxis)?t.yaxis.forEach((function(e,i){t.yaxis[i].min=0,t.yaxis[i].max=100})):(t.yaxis.min=0,t.yaxis.max=100)),t}},{key:"revertDefaultAxisMinMax",value:function(t){var e=this,i=this.w,a=i.globals.lastXAxis,s=i.globals.lastYAxis;t&&t.xaxis&&(a=t.xaxis),t&&t.yaxis&&(s=t.yaxis),i.config.xaxis.min=a.min,i.config.xaxis.max=a.max;var r=function(t){void 0!==s[t]&&(i.config.yaxis[t].min=s[t].min,i.config.yaxis[t].max=s[t].max)};i.config.yaxis.map((function(t,a){i.globals.zoomed||void 0!==s[a]?r(a):void 0!==e.ctx.opts.yaxis[a]&&(t.min=e.ctx.opts.yaxis[a].min,t.max=e.ctx.opts.yaxis[a].max)}))}}]),t}();!function(){function t(){for(var t=arguments.length>0&&arguments[0]!==h?arguments[0]:[],s=arguments.length>1?arguments[1]:h,r=arguments.length>2?arguments[2]:h,n=arguments.length>3?arguments[3]:h,o=arguments.length>4?arguments[4]:h,l=arguments.length>5?arguments[5]:h,h=arguments.length>6?arguments[6]:h,c=t.slice(s,r||h),d=n.slice(o,l||h),u=0,g={pos:[0,0],start:[0,0]},p={pos:[0,0],start:[0,0]};;){if(c[u]=e.call(g,c[u]),d[u]=e.call(p,d[u]),c[u][0]!=d[u][0]||"M"==c[u][0]||"A"==c[u][0]&&(c[u][4]!=d[u][4]||c[u][5]!=d[u][5])?(Array.prototype.splice.apply(c,[u,1].concat(a.call(g,c[u]))),Array.prototype.splice.apply(d,[u,1].concat(a.call(p,d[u])))):(c[u]=i.call(g,c[u]),d[u]=i.call(p,d[u])),++u==c.length&&u==d.length)break;u==c.length&&c.push(["C",g.pos[0],g.pos[1],g.pos[0],g.pos[1],g.pos[0],g.pos[1]]),u==d.length&&d.push(["C",p.pos[0],p.pos[1],p.pos[0],p.pos[1],p.pos[0],p.pos[1]])}return{start:c,dest:d}}function e(t){switch(t[0]){case"z":case"Z":t[0]="L",t[1]=this.start[0],t[2]=this.start[1];break;case"H":t[0]="L",t[2]=this.pos[1];break;case"V":t[0]="L",t[2]=t[1],t[1]=this.pos[0];break;case"T":t[0]="Q",t[3]=t[1],t[4]=t[2],t[1]=this.reflection[1],t[2]=this.reflection[0];break;case"S":t[0]="C",t[6]=t[4],t[5]=t[3],t[4]=t[2],t[3]=t[1],t[2]=this.reflection[1],t[1]=this.reflection[0]}return t}function i(t){var e=t.length;return this.pos=[t[e-2],t[e-1]],-1!="SCQT".indexOf(t[0])&&(this.reflection=[2*this.pos[0]-t[e-4],2*this.pos[1]-t[e-3]]),t}function a(t){var e=[t];switch(t[0]){case"M":return this.pos=this.start=[t[1],t[2]],e;case"L":t[5]=t[3]=t[1],t[6]=t[4]=t[2],t[1]=this.pos[0],t[2]=this.pos[1];break;case"Q":t[6]=t[4],t[5]=t[3],t[4]=1*t[4]/3+2*t[2]/3,t[3]=1*t[3]/3+2*t[1]/3,t[2]=1*this.pos[1]/3+2*t[2]/3,t[1]=1*this.pos[0]/3+2*t[1]/3;break;case"A":e=function(t,e){var i,a,s,r,n,o,l,h,c,d,u,g,p,f,x,b,m,v,y,w,k,A,C,S,L,M,P=Math.abs(e[1]),I=Math.abs(e[2]),T=e[3]%360,z=e[4],X=e[5],R=e[6],E=e[7],Y=new bt(t),H=new bt(R,E),O=[];if(0===P||0===I||Y.x===H.x&&Y.y===H.y)return[["C",Y.x,Y.y,H.x,H.y,H.x,H.y]];i=new bt((Y.x-H.x)/2,(Y.y-H.y)/2).transform((new vt).rotate(T)),a=i.x*i.x/(P*P)+i.y*i.y/(I*I),a>1&&(P*=a=Math.sqrt(a),I*=a);s=(new vt).rotate(T).scale(1/P,1/I).rotate(-T),Y=Y.transform(s),H=H.transform(s),r=[H.x-Y.x,H.y-Y.y],o=r[0]*r[0]+r[1]*r[1],n=Math.sqrt(o),r[0]/=n,r[1]/=n,l=o<4?Math.sqrt(1-o/4):0,z===X&&(l*=-1);h=new bt((H.x+Y.x)/2+l*-r[1],(H.y+Y.y)/2+l*r[0]),c=new bt(Y.x-h.x,Y.y-h.y),d=new bt(H.x-h.x,H.y-h.y),u=Math.acos(c.x/Math.sqrt(c.x*c.x+c.y*c.y)),c.y<0&&(u*=-1);g=Math.acos(d.x/Math.sqrt(d.x*d.x+d.y*d.y)),d.y<0&&(g*=-1);X&&u>g&&(g+=2*Math.PI);!X&&u0&&void 0!==arguments[0]?arguments[0]:[],e=arguments.length>1?arguments[1]:void 0;if(!1===e)return!1;for(var i=e,a=t.length;i(t.changedTouches&&(t=t.changedTouches[0]),{x:t.clientX,y:t.clientY});class Qa{constructor(t){t.remember("_draggable",this),this.el=t,this.drag=this.drag.bind(this),this.startDrag=this.startDrag.bind(this),this.endDrag=this.endDrag.bind(this)}init(t){t?(this.el.on("mousedown.drag",this.startDrag),this.el.on("touchstart.drag",this.startDrag,{passive:!1})):(this.el.off("mousedown.drag"),this.el.off("touchstart.drag"))}startDrag(t){const e=!t.type.indexOf("mouse");if(e&&1!==t.which&&0!==t.buttons)return;if(this.el.dispatch("beforedrag",{event:t,handler:this}).defaultPrevented)return;t.preventDefault(),t.stopPropagation(),this.init(!1),this.box=this.el.bbox(),this.lastClick=this.el.point(Ja(t));const i=(e?"mouseup":"touchend")+".drag";zt(window,(e?"mousemove":"touchmove")+".drag",this.drag,this,{passive:!1}),zt(window,i,this.endDrag,this,{passive:!1}),this.el.fire("dragstart",{event:t,handler:this,box:this.box})}drag(t){const{box:e,lastClick:i}=this,a=this.el.point(Ja(t)),s=a.x-i.x,r=a.y-i.y;if(!s&&!r)return e;const n=e.x+s,o=e.y+r;this.box=new kt(n,o,e.w,e.h),this.lastClick=a,this.el.dispatch("dragmove",{event:t,handler:this,box:this.box}).defaultPrevented||this.move(n,o)}move(t,e){"svg"===this.el.type?gi.prototype.move.call(this.el,t,e):this.el.move(t,e)}endDrag(t){this.drag(t),this.el.fire("dragend",{event:t,handler:this,box:this.box}),Xt(window,"mousemove.drag"),Xt(window,"touchmove.drag"),Xt(window,"mouseup.drag"),Xt(window,"touchend.drag"),this.init(!0)}} +/*! + * @svgdotjs/svg.select.js - An extension of svg.js which allows to select elements with mouse + * @version 4.0.1 + * https://github.com/svgdotjs/svg.select.js + * + * @copyright Ulrich-Matthias Schäfer + * @license MIT + * + * BUILT: Mon Jul 01 2024 15:04:42 GMT+0200 (Central European Summer Time) + */ +function Ka(t,e,i,a=null){return function(s){s.preventDefault(),s.stopPropagation();var r=s.pageX||s.touches[0].pageX,n=s.pageY||s.touches[0].pageY;e.fire(t,{x:r,y:n,event:s,index:a,points:i})}}function ts([t,e],{a:i,b:a,c:s,d:r,e:n,f:o}){return[t*i+e*s+n,t*a+e*r+o]}Q(Gt,{draggable(t=!0){return(this.remember("_draggable")||new Qa(this)).init(t),this}});let es=class{constructor(t){this.el=t,t.remember("_selectHandler",this),this.selection=new gi,this.order=["lt","t","rt","r","rb","b","lb","l","rot"],this.mutationHandler=this.mutationHandler.bind(this);const e=F();this.observer=new e.MutationObserver(this.mutationHandler)}init(t){this.createHandle=t.createHandle||this.createHandleFn,this.createRot=t.createRot||this.createRotFn,this.updateHandle=t.updateHandle||this.updateHandleFn,this.updateRot=t.updateRot||this.updateRotFn,this.el.root().put(this.selection),this.updatePoints(),this.createSelection(),this.createResizeHandles(),this.updateResizeHandles(),this.createRotationHandle(),this.updateRotationHandle(),this.observer.observe(this.el.node,{attributes:!0})}active(t,e){if(!t)return this.selection.clear().remove(),void this.observer.disconnect();this.init(e)}createSelection(){this.selection.polygon(this.handlePoints).addClass("svg_select_shape")}updateSelection(){this.selection.get(0).plot(this.handlePoints)}createResizeHandles(){this.handlePoints.forEach(((t,e,i)=>{const a=this.order[e];this.createHandle.call(this,this.selection,t,e,i,a),this.selection.get(e+1).addClass("svg_select_handle svg_select_handle_"+a).on("mousedown.selection touchstart.selection",Ka(a,this.el,this.handlePoints,e))}))}createHandleFn(t){t.polyline()}updateHandleFn(t,e,i,a){const s=a.at(i-1),r=a[(i+1)%a.length],n=e,o=[n[0]-s[0],n[1]-s[1]],l=[n[0]-r[0],n[1]-r[1]],h=Math.sqrt(o[0]*o[0]+o[1]*o[1]),c=Math.sqrt(l[0]*l[0]+l[1]*l[1]),d=[o[0]/h,o[1]/h],u=[l[0]/c,l[1]/c],g=[n[0]-10*d[0],n[1]-10*d[1]],p=[n[0]-10*u[0],n[1]-10*u[1]];t.plot([g,n,p])}updateResizeHandles(){this.handlePoints.forEach(((t,e,i)=>{const a=this.order[e];this.updateHandle.call(this,this.selection.get(e+1),t,e,i,a)}))}createRotFn(t){t.line(),t.circle(5)}getPoint(t){return this.handlePoints[this.order.indexOf(t)]}getPointHandle(t){return this.selection.get(this.order.indexOf(t)+1)}updateRotFn(t,e){const i=this.getPoint("t");t.get(0).plot(i[0],i[1],e[0],e[1]),t.get(1).center(e[0],e[1])}createRotationHandle(){const t=this.selection.group().addClass("svg_select_handle_rot").on("mousedown.selection touchstart.selection",Ka("rot",this.el,this.handlePoints));this.createRot.call(this,t)}updateRotationHandle(){const t=this.selection.findOne("g.svg_select_handle_rot");this.updateRot(t,this.rotationPoint,this.handlePoints)}updatePoints(){const t=this.el.bbox(),e=this.el.parent().screenCTM().inverseO().multiplyO(this.el.screenCTM());this.handlePoints=this.getHandlePoints(t).map((t=>ts(t,e))),this.rotationPoint=ts(this.getRotationPoint(t),e)}getHandlePoints({x:t,x2:e,y:i,y2:a,cx:s,cy:r}=this.el.bbox()){return[[t,i],[s,i],[e,i],[e,r],[e,a],[s,a],[t,a],[t,r]]}getRotationPoint({y:t,cx:e}=this.el.bbox()){return[e,t-20]}mutationHandler(){this.updatePoints(),this.updateSelection(),this.updateResizeHandles(),this.updateRotationHandle()}};const is=t=>function(e=!0,i={}){"object"==typeof e&&(i=e,e=!0);let a=this.remember("_"+t.name);return a||(e.prototype instanceof es?(a=new e(this),e=!0):a=new t(this),this.remember("_"+t.name,a)),a.active(e,i),this}; +/*! + * @svgdotjs/svg.resize.js - An extension for svg.js which allows to resize elements which are selected + * @version 2.0.4 + * https://github.com/svgdotjs/svg.resize.js + * + * @copyright [object Object] + * @license MIT + * + * BUILT: Fri Sep 13 2024 12:43:14 GMT+0200 (Central European Summer Time) + */ +/*! + * @svgdotjs/svg.select.js - An extension of svg.js which allows to select elements with mouse + * @version 4.0.1 + * https://github.com/svgdotjs/svg.select.js + * + * @copyright Ulrich-Matthias Schäfer + * @license MIT + * + * BUILT: Mon Jul 01 2024 15:04:42 GMT+0200 (Central European Summer Time) + */ +function as(t,e,i,a=null){return function(s){s.preventDefault(),s.stopPropagation();var r=s.pageX||s.touches[0].pageX,n=s.pageY||s.touches[0].pageY;e.fire(t,{x:r,y:n,event:s,index:a,points:i})}}function ss([t,e],{a:i,b:a,c:s,d:r,e:n,f:o}){return[t*i+e*s+n,t*a+e*r+o]}Q(Gt,{select:is(es)}),Q([Ge,je,xe],{pointSelect:is(class{constructor(t){this.el=t,t.remember("_pointSelectHandler",this),this.selection=new gi,this.order=["lt","t","rt","r","rb","b","lb","l","rot"],this.mutationHandler=this.mutationHandler.bind(this);const e=F();this.observer=new e.MutationObserver(this.mutationHandler)}init(t){this.createHandle=t.createHandle||this.createHandleFn,this.updateHandle=t.updateHandle||this.updateHandleFn,this.el.root().put(this.selection),this.updatePoints(),this.createSelection(),this.createPointHandles(),this.updatePointHandles(),this.observer.observe(this.el.node,{attributes:!0})}active(t,e){if(!t)return this.selection.clear().remove(),void this.observer.disconnect();this.init(e)}createSelection(){this.selection.polygon(this.points).addClass("svg_select_shape_pointSelect")}updateSelection(){this.selection.get(0).plot(this.points)}createPointHandles(){this.points.forEach(((t,e,i)=>{this.createHandle.call(this,this.selection,t,e,i),this.selection.get(e+1).addClass("svg_select_handle_point").on("mousedown.selection touchstart.selection",Ka("point",this.el,this.points,e))}))}createHandleFn(t){t.circle(5)}updateHandleFn(t,e){t.center(e[0],e[1])}updatePointHandles(){this.points.forEach(((t,e,i)=>{this.updateHandle.call(this,this.selection.get(e+1),t,e,i)}))}updatePoints(){const t=this.el.parent().screenCTM().inverseO().multiplyO(this.el.screenCTM());this.points=this.el.array().map((e=>ts(e,t)))}mutationHandler(){this.updatePoints(),this.updateSelection(),this.updatePointHandles()}})});class rs{constructor(t){this.el=t,t.remember("_selectHandler",this),this.selection=new gi,this.order=["lt","t","rt","r","rb","b","lb","l","rot"],this.mutationHandler=this.mutationHandler.bind(this);const e=F();this.observer=new e.MutationObserver(this.mutationHandler)}init(t){this.createHandle=t.createHandle||this.createHandleFn,this.createRot=t.createRot||this.createRotFn,this.updateHandle=t.updateHandle||this.updateHandleFn,this.updateRot=t.updateRot||this.updateRotFn,this.el.root().put(this.selection),this.updatePoints(),this.createSelection(),this.createResizeHandles(),this.updateResizeHandles(),this.createRotationHandle(),this.updateRotationHandle(),this.observer.observe(this.el.node,{attributes:!0})}active(t,e){if(!t)return this.selection.clear().remove(),void this.observer.disconnect();this.init(e)}createSelection(){this.selection.polygon(this.handlePoints).addClass("svg_select_shape")}updateSelection(){this.selection.get(0).plot(this.handlePoints)}createResizeHandles(){this.handlePoints.forEach(((t,e,i)=>{const a=this.order[e];this.createHandle.call(this,this.selection,t,e,i,a),this.selection.get(e+1).addClass("svg_select_handle svg_select_handle_"+a).on("mousedown.selection touchstart.selection",as(a,this.el,this.handlePoints,e))}))}createHandleFn(t){t.polyline()}updateHandleFn(t,e,i,a){const s=a.at(i-1),r=a[(i+1)%a.length],n=e,o=[n[0]-s[0],n[1]-s[1]],l=[n[0]-r[0],n[1]-r[1]],h=Math.sqrt(o[0]*o[0]+o[1]*o[1]),c=Math.sqrt(l[0]*l[0]+l[1]*l[1]),d=[o[0]/h,o[1]/h],u=[l[0]/c,l[1]/c],g=[n[0]-10*d[0],n[1]-10*d[1]],p=[n[0]-10*u[0],n[1]-10*u[1]];t.plot([g,n,p])}updateResizeHandles(){this.handlePoints.forEach(((t,e,i)=>{const a=this.order[e];this.updateHandle.call(this,this.selection.get(e+1),t,e,i,a)}))}createRotFn(t){t.line(),t.circle(5)}getPoint(t){return this.handlePoints[this.order.indexOf(t)]}getPointHandle(t){return this.selection.get(this.order.indexOf(t)+1)}updateRotFn(t,e){const i=this.getPoint("t");t.get(0).plot(i[0],i[1],e[0],e[1]),t.get(1).center(e[0],e[1])}createRotationHandle(){const t=this.selection.group().addClass("svg_select_handle_rot").on("mousedown.selection touchstart.selection",as("rot",this.el,this.handlePoints));this.createRot.call(this,t)}updateRotationHandle(){const t=this.selection.findOne("g.svg_select_handle_rot");this.updateRot(t,this.rotationPoint,this.handlePoints)}updatePoints(){const t=this.el.bbox(),e=this.el.parent().screenCTM().inverseO().multiplyO(this.el.screenCTM());this.handlePoints=this.getHandlePoints(t).map((t=>ss(t,e))),this.rotationPoint=ss(this.getRotationPoint(t),e)}getHandlePoints({x:t,x2:e,y:i,y2:a,cx:s,cy:r}=this.el.bbox()){return[[t,i],[s,i],[e,i],[e,r],[e,a],[s,a],[t,a],[t,r]]}getRotationPoint({y:t,cx:e}=this.el.bbox()){return[e,t-20]}mutationHandler(){this.updatePoints(),this.updateSelection(),this.updateResizeHandles(),this.updateRotationHandle()}}const ns=t=>function(e=!0,i={}){"object"==typeof e&&(i=e,e=!0);let a=this.remember("_"+t.name);return a||(e.prototype instanceof rs?(a=new e(this),e=!0):a=new t(this),this.remember("_"+t.name,a)),a.active(e,i),this};Q(Gt,{select:ns(rs)}),Q([Ge,je,xe],{pointSelect:ns(class{constructor(t){this.el=t,t.remember("_pointSelectHandler",this),this.selection=new gi,this.order=["lt","t","rt","r","rb","b","lb","l","rot"],this.mutationHandler=this.mutationHandler.bind(this);const e=F();this.observer=new e.MutationObserver(this.mutationHandler)}init(t){this.createHandle=t.createHandle||this.createHandleFn,this.updateHandle=t.updateHandle||this.updateHandleFn,this.el.root().put(this.selection),this.updatePoints(),this.createSelection(),this.createPointHandles(),this.updatePointHandles(),this.observer.observe(this.el.node,{attributes:!0})}active(t,e){if(!t)return this.selection.clear().remove(),void this.observer.disconnect();this.init(e)}createSelection(){this.selection.polygon(this.points).addClass("svg_select_shape_pointSelect")}updateSelection(){this.selection.get(0).plot(this.points)}createPointHandles(){this.points.forEach(((t,e,i)=>{this.createHandle.call(this,this.selection,t,e,i),this.selection.get(e+1).addClass("svg_select_handle_point").on("mousedown.selection touchstart.selection",as("point",this.el,this.points,e))}))}createHandleFn(t){t.circle(5)}updateHandleFn(t,e){t.center(e[0],e[1])}updatePointHandles(){this.points.forEach(((t,e,i)=>{this.updateHandle.call(this,this.selection.get(e+1),t,e,i)}))}updatePoints(){const t=this.el.parent().screenCTM().inverseO().multiplyO(this.el.screenCTM());this.points=this.el.array().map((e=>ss(e,t)))}mutationHandler(){this.updatePoints(),this.updateSelection(),this.updatePointHandles()}})});const os=t=>(t.changedTouches&&(t=t.changedTouches[0]),{x:t.clientX,y:t.clientY}),ls=t=>{let e=1/0,i=1/0,a=-1/0,s=-1/0;for(let r=0;r{const s=t-e[0],r=(a-e[1])*i;return[s*i+e[0],r+e[1]]}));return ls(a)}(this.box,s,r)}this.el.dispatch("resize",{box:new kt(l),angle:0,eventType:this.eventType,event:t,handler:this}).defaultPrevented||this.el.size(l.width,l.height).move(l.x,l.y)}movePoint(t){this.lastEvent=t;const{x:e,y:i}=this.snapToGrid(this.el.point(os(t))),a=this.el.array().slice();a[this.index]=[e,i],this.el.dispatch("resize",{box:ls(a),angle:0,eventType:this.eventType,event:t,handler:this}).defaultPrevented||this.el.plot(a)}rotate(t){this.lastEvent=t;const e=this.startPoint,i=this.el.point(os(t)),{cx:a,cy:s}=this.box,r=e.x-a,n=e.y-s,o=i.x-a,l=i.y-s,h=Math.sqrt(r*r+n*n)*Math.sqrt(o*o+l*l);if(0===h)return;let c=Math.acos((r*o+n*l)/h)/Math.PI*180;if(!c)return;i.xdiv {\n margin: 4px 0\n}\n\n.apexcharts-tooltip-box span.value {\n font-weight: 700\n}\n\n.apexcharts-tooltip-rangebar {\n padding: 5px 8px\n}\n\n.apexcharts-tooltip-rangebar .category {\n font-weight: 600;\n color: #777\n}\n\n.apexcharts-tooltip-rangebar .series-name {\n font-weight: 700;\n display: block;\n margin-bottom: 5px\n}\n\n.apexcharts-xaxistooltip,\n.apexcharts-yaxistooltip {\n opacity: 0;\n pointer-events: none;\n color: #373d3f;\n font-size: 13px;\n text-align: center;\n border-radius: 2px;\n position: absolute;\n z-index: 10;\n background: #eceff1;\n border: 1px solid #90a4ae\n}\n\n.apexcharts-xaxistooltip {\n padding: 9px 10px;\n transition: .15s ease all\n}\n\n.apexcharts-xaxistooltip.apexcharts-theme-dark {\n background: rgba(0, 0, 0, .7);\n border: 1px solid rgba(0, 0, 0, .5);\n color: #fff\n}\n\n.apexcharts-xaxistooltip:after,\n.apexcharts-xaxistooltip:before {\n left: 50%;\n border: solid transparent;\n content: " ";\n height: 0;\n width: 0;\n position: absolute;\n pointer-events: none\n}\n\n.apexcharts-xaxistooltip:after {\n border-color: transparent;\n border-width: 6px;\n margin-left: -6px\n}\n\n.apexcharts-xaxistooltip:before {\n border-color: transparent;\n border-width: 7px;\n margin-left: -7px\n}\n\n.apexcharts-xaxistooltip-bottom:after,\n.apexcharts-xaxistooltip-bottom:before {\n bottom: 100%\n}\n\n.apexcharts-xaxistooltip-top:after,\n.apexcharts-xaxistooltip-top:before {\n top: 100%\n}\n\n.apexcharts-xaxistooltip-bottom:after {\n border-bottom-color: #eceff1\n}\n\n.apexcharts-xaxistooltip-bottom:before {\n border-bottom-color: #90a4ae\n}\n\n.apexcharts-xaxistooltip-bottom.apexcharts-theme-dark:after,\n.apexcharts-xaxistooltip-bottom.apexcharts-theme-dark:before {\n border-bottom-color: rgba(0, 0, 0, .5)\n}\n\n.apexcharts-xaxistooltip-top:after {\n border-top-color: #eceff1\n}\n\n.apexcharts-xaxistooltip-top:before {\n border-top-color: #90a4ae\n}\n\n.apexcharts-xaxistooltip-top.apexcharts-theme-dark:after,\n.apexcharts-xaxistooltip-top.apexcharts-theme-dark:before {\n border-top-color: rgba(0, 0, 0, .5)\n}\n\n.apexcharts-xaxistooltip.apexcharts-active {\n opacity: 1;\n transition: .15s ease all\n}\n\n.apexcharts-yaxistooltip {\n padding: 4px 10px\n}\n\n.apexcharts-yaxistooltip.apexcharts-theme-dark {\n background: rgba(0, 0, 0, .7);\n border: 1px solid rgba(0, 0, 0, .5);\n color: #fff\n}\n\n.apexcharts-yaxistooltip:after,\n.apexcharts-yaxistooltip:before {\n top: 50%;\n border: solid transparent;\n content: " ";\n height: 0;\n width: 0;\n position: absolute;\n pointer-events: none\n}\n\n.apexcharts-yaxistooltip:after {\n border-color: transparent;\n border-width: 6px;\n margin-top: -6px\n}\n\n.apexcharts-yaxistooltip:before {\n border-color: transparent;\n border-width: 7px;\n margin-top: -7px\n}\n\n.apexcharts-yaxistooltip-left:after,\n.apexcharts-yaxistooltip-left:before {\n left: 100%\n}\n\n.apexcharts-yaxistooltip-right:after,\n.apexcharts-yaxistooltip-right:before {\n right: 100%\n}\n\n.apexcharts-yaxistooltip-left:after {\n border-left-color: #eceff1\n}\n\n.apexcharts-yaxistooltip-left:before {\n border-left-color: #90a4ae\n}\n\n.apexcharts-yaxistooltip-left.apexcharts-theme-dark:after,\n.apexcharts-yaxistooltip-left.apexcharts-theme-dark:before {\n border-left-color: rgba(0, 0, 0, .5)\n}\n\n.apexcharts-yaxistooltip-right:after {\n border-right-color: #eceff1\n}\n\n.apexcharts-yaxistooltip-right:before {\n border-right-color: #90a4ae\n}\n\n.apexcharts-yaxistooltip-right.apexcharts-theme-dark:after,\n.apexcharts-yaxistooltip-right.apexcharts-theme-dark:before {\n border-right-color: rgba(0, 0, 0, .5)\n}\n\n.apexcharts-yaxistooltip.apexcharts-active {\n opacity: 1\n}\n\n.apexcharts-yaxistooltip-hidden {\n display: none\n}\n\n.apexcharts-xcrosshairs,\n.apexcharts-ycrosshairs {\n pointer-events: none;\n opacity: 0;\n transition: .15s ease all\n}\n\n.apexcharts-xcrosshairs.apexcharts-active,\n.apexcharts-ycrosshairs.apexcharts-active {\n opacity: 1;\n transition: .15s ease all\n}\n\n.apexcharts-ycrosshairs-hidden {\n opacity: 0\n}\n\n.apexcharts-selection-rect {\n cursor: move\n}\n\n.svg_select_shape {\n stroke-width: 1;\n stroke-dasharray: 10 10;\n stroke: black;\n stroke-opacity: 0.1;\n pointer-events: none;\n fill: none;\n}\n\n.svg_select_handle {\n stroke-width: 3;\n stroke: black;\n fill: none;\n}\n\n.svg_select_handle_r {\n cursor: e-resize;\n}\n\n.svg_select_handle_l {\n cursor: w-resize;\n}\n\n.apexcharts-svg.apexcharts-zoomable.hovering-zoom {\n cursor: crosshair\n}\n\n.apexcharts-svg.apexcharts-zoomable.hovering-pan {\n cursor: move\n}\n\n.apexcharts-menu-icon,\n.apexcharts-pan-icon,\n.apexcharts-reset-icon,\n.apexcharts-selection-icon,\n.apexcharts-toolbar-custom-icon,\n.apexcharts-zoom-icon,\n.apexcharts-zoomin-icon,\n.apexcharts-zoomout-icon {\n cursor: pointer;\n width: 20px;\n height: 20px;\n line-height: 24px;\n color: #6e8192;\n text-align: center\n}\n\n.apexcharts-menu-icon svg,\n.apexcharts-reset-icon svg,\n.apexcharts-zoom-icon svg,\n.apexcharts-zoomin-icon svg,\n.apexcharts-zoomout-icon svg {\n fill: #6e8192\n}\n\n.apexcharts-selection-icon svg {\n fill: #444;\n transform: scale(.76)\n}\n\n.apexcharts-theme-dark .apexcharts-menu-icon svg,\n.apexcharts-theme-dark .apexcharts-pan-icon svg,\n.apexcharts-theme-dark .apexcharts-reset-icon svg,\n.apexcharts-theme-dark .apexcharts-selection-icon svg,\n.apexcharts-theme-dark .apexcharts-toolbar-custom-icon svg,\n.apexcharts-theme-dark .apexcharts-zoom-icon svg,\n.apexcharts-theme-dark .apexcharts-zoomin-icon svg,\n.apexcharts-theme-dark .apexcharts-zoomout-icon svg {\n fill: #f3f4f5\n}\n\n.apexcharts-canvas .apexcharts-reset-zoom-icon.apexcharts-selected svg,\n.apexcharts-canvas .apexcharts-selection-icon.apexcharts-selected svg,\n.apexcharts-canvas .apexcharts-zoom-icon.apexcharts-selected svg {\n fill: #008ffb\n}\n\n.apexcharts-theme-light .apexcharts-menu-icon:hover svg,\n.apexcharts-theme-light .apexcharts-reset-icon:hover svg,\n.apexcharts-theme-light .apexcharts-selection-icon:not(.apexcharts-selected):hover svg,\n.apexcharts-theme-light .apexcharts-zoom-icon:not(.apexcharts-selected):hover svg,\n.apexcharts-theme-light .apexcharts-zoomin-icon:hover svg,\n.apexcharts-theme-light .apexcharts-zoomout-icon:hover svg {\n fill: #333\n}\n\n.apexcharts-menu-icon,\n.apexcharts-selection-icon {\n position: relative\n}\n\n.apexcharts-reset-icon {\n margin-left: 5px\n}\n\n.apexcharts-menu-icon,\n.apexcharts-reset-icon,\n.apexcharts-zoom-icon {\n transform: scale(.85)\n}\n\n.apexcharts-zoomin-icon,\n.apexcharts-zoomout-icon {\n transform: scale(.7)\n}\n\n.apexcharts-zoomout-icon {\n margin-right: 3px\n}\n\n.apexcharts-pan-icon {\n transform: scale(.62);\n position: relative;\n left: 1px;\n top: 0\n}\n\n.apexcharts-pan-icon svg {\n fill: #fff;\n stroke: #6e8192;\n stroke-width: 2\n}\n\n.apexcharts-pan-icon.apexcharts-selected svg {\n stroke: #008ffb\n}\n\n.apexcharts-pan-icon:not(.apexcharts-selected):hover svg {\n stroke: #333\n}\n\n.apexcharts-toolbar {\n position: absolute;\n z-index: 11;\n max-width: 176px;\n text-align: right;\n border-radius: 3px;\n padding: 0 6px 2px;\n display: flex;\n justify-content: space-between;\n align-items: center\n}\n\n.apexcharts-menu {\n background: #fff;\n position: absolute;\n top: 100%;\n border: 1px solid #ddd;\n border-radius: 3px;\n padding: 3px;\n right: 10px;\n opacity: 0;\n min-width: 110px;\n transition: .15s ease all;\n pointer-events: none\n}\n\n.apexcharts-menu.apexcharts-menu-open {\n opacity: 1;\n pointer-events: all;\n transition: .15s ease all\n}\n\n.apexcharts-menu-item {\n padding: 6px 7px;\n font-size: 12px;\n cursor: pointer\n}\n\n.apexcharts-theme-light .apexcharts-menu-item:hover {\n background: #eee\n}\n\n.apexcharts-theme-dark .apexcharts-menu {\n background: rgba(0, 0, 0, .7);\n color: #fff\n}\n\n@media screen and (min-width:768px) {\n .apexcharts-canvas:hover .apexcharts-toolbar {\n opacity: 1\n }\n}\n\n.apexcharts-canvas .apexcharts-element-hidden,\n.apexcharts-datalabel.apexcharts-element-hidden,\n.apexcharts-hide .apexcharts-series-points {\n opacity: 0;\n}\n\n.apexcharts-hidden-element-shown {\n opacity: 1;\n transition: 0.25s ease all;\n}\n\n.apexcharts-datalabel,\n.apexcharts-datalabel-label,\n.apexcharts-datalabel-value,\n.apexcharts-datalabels,\n.apexcharts-pie-label {\n cursor: default;\n pointer-events: none\n}\n\n.apexcharts-pie-label-delay {\n opacity: 0;\n animation-name: opaque;\n animation-duration: .3s;\n animation-fill-mode: forwards;\n animation-timing-function: ease\n}\n\n.apexcharts-radialbar-label {\n cursor: pointer;\n}\n\n.apexcharts-annotation-rect,\n.apexcharts-area-series .apexcharts-area,\n.apexcharts-gridline,\n.apexcharts-line,\n.apexcharts-point-annotation-label,\n.apexcharts-radar-series path:not(.apexcharts-marker),\n.apexcharts-radar-series polygon,\n.apexcharts-toolbar svg,\n.apexcharts-tooltip .apexcharts-marker,\n.apexcharts-xaxis-annotation-label,\n.apexcharts-yaxis-annotation-label,\n.apexcharts-zoom-rect,\n.no-pointer-events {\n pointer-events: none\n}\n\n.apexcharts-tooltip-active .apexcharts-marker {\n transition: .15s ease all\n}\n\n.apexcharts-radar-series .apexcharts-yaxis {\n pointer-events: none;\n}\n\n.resize-triggers {\n animation: 1ms resizeanim;\n visibility: hidden;\n opacity: 0;\n height: 100%;\n width: 100%;\n overflow: hidden\n}\n\n.contract-trigger:before,\n.resize-triggers,\n.resize-triggers>div {\n content: " ";\n display: block;\n position: absolute;\n top: 0;\n left: 0\n}\n\n.resize-triggers>div {\n height: 100%;\n width: 100%;\n background: #eee;\n overflow: auto\n}\n\n.contract-trigger:before {\n overflow: hidden;\n width: 200%;\n height: 200%\n}\n\n.apexcharts-bar-goals-markers {\n pointer-events: none\n}\n\n.apexcharts-bar-shadows {\n pointer-events: none\n}\n\n.apexcharts-rangebar-goals-markers {\n pointer-events: none\n}\n\n.apexcharts-disable-transitions * {\n transition: none !important;\n}';var h=(null===(l=t.opts.chart)||void 0===l?void 0:l.nonce)||t.w.config.chart.nonce;h&&o.setAttribute("nonce",h),r?s.prepend(o):!1!==t.w.config.chart.injectStyleSheet&&n.head.appendChild(o)}var c=t.create(t.w.config.series,{});if(!c)return e(t);t.mount(c).then((function(){"function"==typeof t.w.config.chart.events.mounted&&t.w.config.chart.events.mounted(t,t.w),t.events.fireEvent("mounted",[t,t.w]),e(c)})).catch((function(t){i(t)}))}else i(new Error("Element not found"))}))}},{key:"create",value:function(t,e){var i=this,a=this.w;new cs(this).initModules();var s=this.w.globals;if(s.noData=!1,s.animationEnded=!1,!v.elementExists(this.el))return s.animationEnded=!0,null;(this.responsive.checkResponsiveConfig(e),a.config.xaxis.convertedCatToNumeric)&&new Ni(a.config).convertCatToNumericXaxis(a.config,this.ctx);if(this.core.setupElements(),"treemap"===a.config.chart.type&&(a.config.grid.show=!1,a.config.yaxis[0].show=!1),0===s.svgWidth)return s.animationEnded=!0,null;var r=t;t.forEach((function(t,e){t.hidden&&(r=i.legend.legendHelpers.getSeriesAfterCollapsing({realIndex:e}))}));var n=Pi.checkComboSeries(r,a.config.chart.type);s.comboCharts=n.comboCharts,s.comboBarCount=n.comboBarCount;var o=r.every((function(t){return t.data&&0===t.data.length}));(0===r.length||o&&s.collapsedSeries.length<1)&&this.series.handleNoData(),this.events.setupEventHandlers(),this.data.parseData(r),this.theme.init(),new Vi(this).setGlobalMarkerSize(),this.formatters.setLabelFormatters(),this.titleSubtitle.draw(),s.noData&&s.collapsedSeries.length!==s.series.length&&!a.config.legend.showForSingleSeries||this.legend.init(),this.series.hasAllSeriesEqualX(),s.axisCharts&&(this.core.coreCalculations(),"category"!==a.config.xaxis.type&&this.formatters.setLabelFormatters(),this.ctx.toolbar.minX=a.globals.minX,this.ctx.toolbar.maxX=a.globals.maxX),this.formatters.heatmapLabelFormatters(),new Pi(this).getLargestMarkerSize(),this.dimensions.plotCoords();var l=this.core.xySettings();this.grid.createGridMask();var h=this.core.plotChartType(r,l),c=new qi(this);return c.bringForward(),a.config.dataLabels.background.enabled&&c.dataLabelsBackground(),this.core.shiftGraphPosition(),a.globals.dataPoints>50&&a.globals.dom.elWrap.classList.add("apexcharts-disable-transitions"),{elGraph:h,xyRatios:l,dimensions:{plot:{left:a.globals.translateX,top:a.globals.translateY,width:a.globals.gridWidth,height:a.globals.gridHeight}}}}},{key:"mount",value:function(){var t=this,e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:null,i=this,a=i.w;return new Promise((function(s,r){if(null===i.el)return r(new Error("Not enough data to display or target element not found"));(null===e||a.globals.allSeriesCollapsed)&&i.series.handleNoData(),i.grid=new ta(i);var n,o,l=i.grid.drawGrid();(i.annotations=new Fi(i),i.annotations.drawImageAnnos(),i.annotations.drawTextAnnos(),"back"===a.config.grid.position)&&(l&&a.globals.dom.elGraphical.add(l.el),null!=l&&null!==(n=l.elGridBorders)&&void 0!==n&&n.node&&a.globals.dom.elGraphical.add(l.elGridBorders));if(Array.isArray(e.elGraph))for(var h=0;h0&&a.globals.memory.methodsToExec.forEach((function(t){t.method(t.params,!1,t.context)})),a.globals.axisCharts||a.globals.noData||i.core.resizeNonAxisCharts(),s(i)}))}},{key:"destroy",value:function(){window.removeEventListener("resize",this.windowResizeHandler),function(t,e){var i=us.get(e);i&&(i.disconnect(),us.delete(e))}(this.el.parentNode,this.parentResizeHandler);var t=this.w.config.chart.id;t&&Apex._chartInstances.forEach((function(e,i){e.id===v.escapeString(t)&&Apex._chartInstances.splice(i,1)})),new ds(this.ctx).clear({isUpdating:!1})}},{key:"updateOptions",value:function(t){var e=this,i=arguments.length>1&&void 0!==arguments[1]&&arguments[1],a=!(arguments.length>2&&void 0!==arguments[2])||arguments[2],s=!(arguments.length>3&&void 0!==arguments[3])||arguments[3],r=!(arguments.length>4&&void 0!==arguments[4])||arguments[4],n=this.w;return n.globals.selection=void 0,this.lastUpdateOptions&&JSON.stringify(this.lastUpdateOptions)===JSON.stringify(t)?this:(t.series&&(this.data.resetParsingFlags(),this.series.resetSeries(!1,!0,!1),t.series.length&&t.series[0].data&&(t.series=t.series.map((function(t,i){return e.updateHelpers._extendSeries(t,i)}))),this.updateHelpers.revertDefaultAxisMinMax()),t.xaxis&&(t=this.updateHelpers.forceXAxisUpdate(t)),t.yaxis&&(t=this.updateHelpers.forceYAxisUpdate(t)),n.globals.collapsedSeriesIndices.length>0&&this.series.clearPreviousPaths(),t.theme&&(t=this.theme.updateThemeOptions(t)),this.updateHelpers._updateOptions(t,i,a,s,r))}},{key:"updateSeries",value:function(){var t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:[],e=!(arguments.length>1&&void 0!==arguments[1])||arguments[1],i=!(arguments.length>2&&void 0!==arguments[2])||arguments[2];return this.data.resetParsingFlags(),this.series.resetSeries(!1),this.updateHelpers.revertDefaultAxisMinMax(),this.updateHelpers._updateSeries(t,e,i)}},{key:"appendSeries",value:function(t){var e=!(arguments.length>1&&void 0!==arguments[1])||arguments[1],i=!(arguments.length>2&&void 0!==arguments[2])||arguments[2];this.data.resetParsingFlags();var a=this.w.config.series.slice();return a.push(t),this.series.resetSeries(!1),this.updateHelpers.revertDefaultAxisMinMax(),this.updateHelpers._updateSeries(a,e,i)}},{key:"appendData",value:function(t){var e=!(arguments.length>1&&void 0!==arguments[1])||arguments[1],i=this;i.data.resetParsingFlags(),i.w.globals.dataChanged=!0,i.series.getPreviousPaths();for(var a=i.w.config.series.slice(),s=0;s0&&void 0!==arguments[0])||arguments[0],e=!(arguments.length>1&&void 0!==arguments[1])||arguments[1];this.series.resetSeries(t,e)}},{key:"addEventListener",value:function(t,e){this.events.addEventListener(t,e)}},{key:"removeEventListener",value:function(t,e){this.events.removeEventListener(t,e)}},{key:"addXaxisAnnotation",value:function(t){var e=!(arguments.length>1&&void 0!==arguments[1])||arguments[1],i=arguments.length>2&&void 0!==arguments[2]?arguments[2]:void 0,a=this;i&&(a=i),a.annotations.addXaxisAnnotationExternal(t,e,a)}},{key:"addYaxisAnnotation",value:function(t){var e=!(arguments.length>1&&void 0!==arguments[1])||arguments[1],i=arguments.length>2&&void 0!==arguments[2]?arguments[2]:void 0,a=this;i&&(a=i),a.annotations.addYaxisAnnotationExternal(t,e,a)}},{key:"addPointAnnotation",value:function(t){var e=!(arguments.length>1&&void 0!==arguments[1])||arguments[1],i=arguments.length>2&&void 0!==arguments[2]?arguments[2]:void 0,a=this;i&&(a=i),a.annotations.addPointAnnotationExternal(t,e,a)}},{key:"clearAnnotations",value:function(){var t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:void 0,e=this;t&&(e=t),e.annotations.clearAnnotations(e)}},{key:"removeAnnotation",value:function(t){var e=arguments.length>1&&void 0!==arguments[1]?arguments[1]:void 0,i=this;e&&(i=e),i.annotations.removeAnnotation(i,t)}},{key:"getChartArea",value:function(){return this.w.globals.dom.baseEl.querySelector(".apexcharts-inner")}},{key:"getSeriesTotalXRange",value:function(t,e){return this.coreUtils.getSeriesTotalsXRange(t,e)}},{key:"getHighestValueInSeries",value:function(){var t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:0;return new ia(this.ctx).getMinYMaxY(t).highestY}},{key:"getLowestValueInSeries",value:function(){var t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:0;return new ia(this.ctx).getMinYMaxY(t).lowestY}},{key:"getSeriesTotal",value:function(){return this.w.globals.seriesTotals}},{key:"toggleDataPointSelection",value:function(t,e){return this.updateHelpers.toggleDataPointSelection(t,e)}},{key:"zoomX",value:function(t,e){this.ctx.toolbar.zoomUpdateOptions(t,e)}},{key:"setLocale",value:function(t){this.localization.setCurrentLocaleValues(t)}},{key:"dataURI",value:function(t){return new Qi(this.ctx).dataURI(t)}},{key:"getSvgString",value:function(t){return new Qi(this.ctx).getSvgString(t)}},{key:"exportToCSV",value:function(){var t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{};return new Qi(this.ctx).exportToCSV(t)}},{key:"paper",value:function(){return this.w.globals.dom.Paper}},{key:"_parentResizeCallback",value:function(){this.w.globals.animationEnded&&this.w.config.chart.redrawOnParentResize&&this._windowResize()}},{key:"_windowResize",value:function(){var t=this;clearTimeout(this.w.globals.resizeTimer),this.w.globals.resizeTimer=window.setTimeout((function(){t.w.globals.resized=!0,t.w.globals.dataChanged=!1,t.ctx.update()}),150)}},{key:"_windowResizeHandler",value:function(){var t=this.w.config.chart.redrawOnWindowResize;"function"==typeof t&&(t=t()),t&&this._windowResize()}}],[{key:"getChartByID",value:function(t){var e=v.escapeString(t);if(Apex._chartInstances){var i=Apex._chartInstances.filter((function(t){return t.id===e}))[0];return i&&i.chart}}},{key:"initOnLoad",value:function(){for(var e=document.querySelectorAll("[data-apexcharts]"),i=0;i2?s-2:0),n=2;n - + diff --git a/examples/chart_text.html b/examples/chart_text.html index 80392b83b..0cc6c333c 100644 --- a/examples/chart_text.html +++ b/examples/chart_text.html @@ -11,7 +11,7 @@ - + diff --git a/examples/custom-gauge.html b/examples/custom-gauge.html index 9c896d5b0..2a14ae44e 100644 --- a/examples/custom-gauge.html +++ b/examples/custom-gauge.html @@ -11,7 +11,7 @@ - + diff --git a/examples/custom-gauge.js b/examples/custom-gauge.js index a7f76cd1d..1de2655dd 100644 --- a/examples/custom-gauge.js +++ b/examples/custom-gauge.js @@ -112,8 +112,8 @@ function getCustomLayout(model, level, arrowColor) { showgrid: false, range: [-1, 1], }, - plot_bgcolor: model.backgroundColor, - paper_bgcolor: model.backgroundColor, + plot_bgcolor: "transparent", + paper_bgcolor: "transparent", }; } diff --git a/examples/custom-vis.html b/examples/custom-vis.html index 346d8f535..80b8c2d1e 100644 --- a/examples/custom-vis.html +++ b/examples/custom-vis.html @@ -11,7 +11,7 @@ - + diff --git a/examples/customDateRange.html b/examples/customDateRange.html new file mode 100644 index 000000000..b4c64873f --- /dev/null +++ b/examples/customDateRange.html @@ -0,0 +1,124 @@ + + + + + Date Range Example + + + + + + + + + + + + + + + + + + +

+ +
+ + + +
+
+
+
Loading...
+
+
+
+
+
+
Loading...
+
+
+
+
+
+
Loading...
+
+
+
+
+
+ + + + \ No newline at end of file diff --git a/examples/customDateRange.js b/examples/customDateRange.js new file mode 100644 index 000000000..1e5d4ecec --- /dev/null +++ b/examples/customDateRange.js @@ -0,0 +1,224 @@ +var json = { + "elements": [ + { + "type": "radiogroup", + "name": "product_discovering", + "title": "How did you first discover our product?", + "choices": [ + "Search engine", + "GitHub", + "Friend or colleague", + { + "value": "Redit", + "text": "Reddit" + }, + "Medium", + "Twitter", + "Facebook" + ] + }, + { + "type": "radiogroup", + "name": "useproduct", + "title": "Do you currently use our libraries?", + "isRequired": true, + "choices": ["Yes", "No"] + }, + { + "type": "checkbox", + "name": "uselibraries", + "title": "Which libraries do you use?", + "choices": [ + { + "text": "Form Library", + "value": "Survey Library (Runner)" + }, { + "text": "Survey Creator", + "value": "Survey Creator (Designer)" + } + ] + }, + { + "type": "rating", + "name": "nps_score", + "title": "How likely are you to recommend our product to a friend or colleague?" + }, { + "type": "radiogroup", + "name": "product_recommend", + "title": "Have you recommended our product to anyone?", + "choices": ["Yes", "No"] + }, { + "type": "checkbox", + "name": "javascript_frameworks", + "title": "Which JavaScript frameworks do you use?", + "showOtherItem": true, + "choices": [ + "React", + "Angular", + "jQuery", + "Vue", + "Meteor", + "Ember", + "Backbone", + "Knockout", + "Aurelia", + "Polymer", + "Mithril" + ] + }, { + "type": "checkbox", + "name": "backend_language", + "title": "Which web backend programming languages do you use?", + "showOtherItem": true, + "choices": [ + "Java", + "Python", + "Node.js", + "Go", + "Django", { + "value": "Asp.net", + "text": "ASP.NET" + }, + "Ruby" + ] + }, { + "type": "checkbox", + "name": "supported_devices", + "title": "Which device types do you need to support?", + "isRequired": true, + "choices": [ + "Desktop", { + "value": "Tablete", + "text": "Tablet" + }, + "Mobile" + ] + } + ] +}; +const survey = new Survey.Model(json); +const npsQuestionNames = ["product_recommend", "nps_score"]; +const customerSegmentationQuestionNames = ["useproduct", "product_discovering", "uselibraries"]; +const frameworksQuestionNames = ["javascript_frameworks", "backend_language", "supported_devices"]; +let vizPanels = []; +function createVizPanels(data, ...args) { + const panels = []; + args.forEach((questions) => { + panels.push(new SurveyAnalytics.VisualizationPanel(questions, data)); + }); + return panels; +} +function renderVizPanels(panels) { + for (let i = 0; i < panels.length; i++) { + const node = document.getElementById(`vizPanel${ + i + 1 + }`); + panels[i].render(node); + document + .getElementById(`loadingIndicator${ + i + 1 + }`) + .style + .display = "none"; + } +} + +var timer = undefined; +var isUpdating = false; +var currMin = undefined; +var currMax = undefined; +function createValsUpdater(parent, vizPanel, data) { + return function() { + var sliders = parent.getElementsByTagName("input"); + var slide1 = parseFloat(sliders[0].value); + var slide2 = parseFloat(sliders[1].value); + if(slide1 > slide2) + { var tmp = slide2; slide2 = slide1; slide1 = tmp; } + currMin = slide1; + currMax = slide2; + // var currData = data.filter(function(item) { + // return item.HappendAt >= currMin && item.HappendAt <= currMax; + // }); + var displayElement = parent.getElementsByClassName("rangeValues")[0]; + displayElement.innerHTML = new Date(slide1).toLocaleDateString() + " - " + new Date(slide2).toLocaleDateString(); + displayElement = parent.getElementsByClassName("rangeValuesCount")[0]; + displayElement.innerHTML = vizPanel.dataProvider.filteredData.length + " item(s)"; + if(isUpdating) { + return; + } + if(timer !== undefined) { + clearTimeout(timer); + timer = undefined; + } + timer = setTimeout(function() { + isUpdating = true; + vizPanel.setFilter("HappendAt", { start: slide1, end: slide2 }); + timer = undefined; + isUpdating = false; + }, 100); + } +} +function setupDateRange(vizPanel, data) { + vizPanel.registerToolbarItem("dateRange", (toolbar) => { + var itemRoot = undefined; + if (data.length > 10 && !!data[0].HappendAt) { + var min = data[0].HappendAt; + var max = data[data.length-1].HappendAt; + itemRoot = document.createElement("div"); + itemRoot.style.display = "inline-block"; + itemRoot.innerHTML = `
+ + + +
+
`; + toolbar.appendChild(itemRoot); + var slider1 = itemRoot.children[0].children[1]; + var slider2 = itemRoot.children[0].children[2]; + slider1.oninput = createValsUpdater(itemRoot.children[0], vizPanel, data); + slider1.oninput(); + slider2.oninput = createValsUpdater(itemRoot.children[0], vizPanel, data); + slider2.oninput(); + } + return itemRoot; + }); +} +fetch("https://api.surveyjs.io/private/surveys/nps/").then(response => response.json()).then(data => { + data.Data.forEach(function(item) { + item.HappendAt = Date.parse(item.HappendAt); + }); + data.Data.sort(function(d1, d2) { + return d1.HappendAt > d2.HappendAt; + }); + currMin = data.Data[0].HappendAt; + currMax = data.Data[data.Data.length-1].HappendAt; + + const allQuestions = survey.getAllQuestions(); + const customerSegmentationQuestions = allQuestions.filter(question => customerSegmentationQuestionNames.indexOf(question.name) > -1); + const npsQuestions = allQuestions.filter(question => npsQuestionNames.indexOf(question.name) > -1); + const frameworksQuestions = allQuestions.filter(question => frameworksQuestionNames.indexOf(question.name) > -1); + vizPanels = createVizPanels(data.Data, customerSegmentationQuestions, npsQuestions, frameworksQuestions); + setupDateRange(vizPanels[0], data.Data); + renderVizPanels(vizPanels); +}); +function openTabNo(evt, number) { + const tabcontent = document.getElementsByClassName("tabcontent"); + for (let i = 0; i < tabcontent.length; i++) { + tabcontent[i].style.display = "none"; + } + const tablinks = document.getElementsByClassName("tablinks"); + for (let i = 0; i < tablinks.length; i++) { + tablinks[i].className = tablinks[i].className.replace(" active", ""); + } + document + .getElementById(`tab${number}`) + .style + .display = "block"; + const vizPanel = vizPanels[number - 1]; + if (vizPanel) { + vizPanel.refresh(); + } + evt.currentTarget.className += " active"; +} +window.openTabNo = openTabNo; +document.getElementsByClassName("tablinks")[0].click(); \ No newline at end of file diff --git a/examples/custom_tabulator.js b/examples/custom_tabulator.js index 33b7e2ab7..70b17d31c 100644 --- a/examples/custom_tabulator.js +++ b/examples/custom_tabulator.js @@ -29,16 +29,11 @@ SurveyAnalyticsTabulator.TableExtensions.registerExtension({ name: "showinsurvey", visibleIndex: 0, render: (table, opt) => { - const btn = SurveyAnalyticsTabulator.DocumentHelper.createElement( - "button", - "rounded-button", - { - innerText: "Show in Survey", - onclick: (e) => { + const btn = SurveyAnalyticsTabulator.DocumentHelper.createButton((e) => { e.stopPropagation(); - }, - } + }, "Show in Survey", "sa-button" ); + btn.className += " sa-button-brand-tertiary"; return btn; }, }); @@ -48,17 +43,13 @@ SurveyAnalyticsTabulator.TableExtensions.registerExtension({ name: "delete", visibleIndex: 1, render: (table, opt) => { - const btn = SurveyAnalyticsTabulator.DocumentHelper.createElement( - "button", - "rounded-button rounded-button--danger", - { - innerText: "Delete Result", - onclick: (e) => { + const btn = SurveyAnalyticsTabulator.DocumentHelper.createButton( + (e) => { e.stopPropagation(); opt.row.remove(); - }, - } + }, "Delete Result", "sa-button" ); + btn.className += " sa-button-brand-tertiary"; return btn; }, }); @@ -68,6 +59,17 @@ var surveyAnalyticsDataTables = new SurveyAnalyticsTabulator.Tabulator( normalizedData ); +const checkbox = document.getElementById('toggle-checkbox'); +checkbox.addEventListener('change', () => { + if (checkbox.checked) { + surveyAnalyticsTabulator.applyTheme(SurveyAnalyticsTabulator.DefaultDark); + } else { + surveyAnalyticsTabulator.applyTheme(SurveyAnalyticsTabulator.Default); + } +}); +// surveyAnalyticsTabulator.applyTheme(SurveyAnalyticsTabulator.DefaultDark); +// surveyAnalyticsTabulator.applyTheme(SurveyAnalyticsTabulator.Default); + SurveyAnalyticsTabulator.TableExtensions.findExtension( "row", "details" diff --git a/examples/data.js b/examples/data.js index 41fc018e7..a44de795e 100644 --- a/examples/data.js +++ b/examples/data.js @@ -359,6 +359,7 @@ var json = { var data = [ { + timestamp: "2025-10-13", Quality: { affordable: "2", }, @@ -393,6 +394,7 @@ var data = [ "signature": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAASwAAADICAYAAABS39xVAAAWSklEQVR4Xu2dCZAV1RWGDyooAgKiArKERXFYnEEFBFkijhvEMoogLon7mlRpjEmM2ZSkorHiljKmKgrGoCmDgruIICKgDoIaZlgFnEEZQEIgLCIESEj9Df240/Nm5vV7vdzlv1WpSkn37XO+c+d/954+93ajffv27RM2EiABEjCAQCMKlgFRookkQAIeAQoWBwIJkIAxBChYxoSKhpIACVCwOAZIgASMIUDBMiZUNJQESICCxTFAAiRgDAEKljGhoqEkQAIULI4BEiABYwhQsIwJFQ0lARKgYHEMkAAJGEOAgmVMqGgoCZAABYtjgARIwBgCFCxjQkVDSYAEKFgcAyRAAsYQoGAZEyoaSgIkQMHiGCABEjCGAAXLmFDRUBIgAQoWxwAJkIAxBChYxoSKhpIACVCwOAZIgASMIUDBMiZUNJQESICCxTFAAiRgDAEKljGhoqEkQAIULI4BEiABYwhQsIwJFQ0lARKgYHEMkAAJGEOAgmVMqGgoCZAABYtjgARIwBgCFCxjQkVDSYAEKFgcAyRAAsYQoGAZEyoaSgIkQMHiGCABEjCGAAXLmFDRUBIgAQoWxwAJkIAxBChYxoSKhpIACVCwOAZIgASMIUDBMiZUNJQESICCxTFAAiRgDAEKljGhoqEkQAIULI4BEiABYwhQsIwJFQ0lARKgYHEMkAAJGEOAgmVMqGgoCZAABYtjgARIwBgCFCxjQkVDSYAEKFgcAyRAAsYQoGAZEyoaSgIkQMHiGCABEjCGAAXLmFDRUBIgAQoWxwAJkIAxBChYxoSKhpIACVCwOAZIgASMIUDBMiZUNJQESICCxTFAAiRgDAEKljGhoqEkQAIULI4BEiABYwhQsIwJFQ0lARKgYHEMkAAJGEOAgmVMqGgoCZAABYtjgARIwBgCFCxjQkVDSYAEKFgcAyRAAsYQoGAZEyoaSgIkQMHiGCABEjCGAAXLmFDRUBIgAQoWxwAJkIAxBChYxoSKhpIACVCwOAZIgASMIUDBMiZUNJQE0iNwx8KZsnDrP2XWNy9PzwgRcUawnl+zXMo2r5U1X2/PAD+jTQc5r11X6X3UMakGgQ8nAZ0JrPzq3/Ld+a/Lmq+3yR/6ni2jO56UmrnWC9a0LyvljvJ3ZNue/2SFfEijRtKzRRuBeI3pVETxSm0o8sG6Erj4gxdl/ub1MqhNB5k86KJUzbRasJ6sKpd7l7xXA3Cvo46Rlo2beP+tYstG2fHfPTX+HbOtSzsVyXltu0mnI1ukGhw+nATSJjDtyyq5/qOpnhnPDLhAzjruG6maZK1g3bPkPRlfVZ6BO6jN8fJIydm1RGjJtn8JZmFYMlbvPLhcxI34RRnbqUjGdCxKNUh8OAmkRWB02ctStmmtXN3lZLmvz7C0zMg810rBCs6sftijv9zZY0CDsBEY/KJMWrNMtu/dnbn+qMaHy/ntusoNXUu4ZGyQIi+whcBDK+bLwysWeO68OfRSKW55bOquWSdYwZwVRGZc7yGhQXuzrurl8taXVTXu5awrNEreYCCByh1b5NvvT5HNu3dJrj/4SbhplWBhhoQprN+wlHu0b2lBHPFWcdqGShlfWV5jyYhZ141dS7zlInNdBSHmzRoSuPnjt+T19avktNbt5NXBl2hjoTWChVwUkoN+2QJyVpMHXRwpaMy6kBcr27Su1nLxhycOoHBFSpudpUVg4ueL5e5Fs73H460gVhW6NCsECyIFsYJooXVs2kJmDBsrmAXF0fA8CFcw14W3ixSuOIizzyQJjJj7vFRs3SgXHX+iPH7quUk+usFnGS9YEI8x817KzKxaHNZEZgy7LJHZDp79fPUyebKyvEaSHsI1rteQ2ASzwajyAhLIk8BdFe/Ks18s8e5ee8H38+wlvtuMFqxsYjW/9KrEhQJFqXgzGRQuvJm8oWtx4vbEN1zYs80EXqheLj9YONNz8bFTzpFRHXpo566xgoW6qTvK98P1l4HIWaWZAIdwPbRiQY2lIuwZ12uotwWIjQRAALnQpds2eSmM8q0bZMfevV65DPKuuZTfxEERP/4/WTRLlm3b5AnVr3oNjuMxBfdpnGBN31Alf/rsH7Jg8/qM86hef6rfyFTFSo0Egn/P0rk1SiLOb9dN7u01RBsbCx457CAUAYyJh1fO9+r86tomhg7TKiG47MNXZO7Gaunb6jh5Y8iYUL4lebExgrVlzy6ZUFUhz32xTNbv+irDCGUFv+6tZ74Iv6DXLZiaKYfASwDktpDjYnODAMQJxZdIGairAbx5w+wbe1i/2rtHJld/6pURXND+BPnzaeclCkcttH7pjFEy4Oj2iT4/zMOMECxU3E6p/lQ+/3pbDd8eKSnV/o8/W34Ls61HSs5ibivMSDXw2mARM9ICl3YsEsQ/2NSq8iST3fhRRe0ixmlas7swodVesMYtfV+eqFxYw6ceLY729jXpVB/SEPRss62n+o0wyoeGfOS/7yeAWGMvKwqZ0fzcVH3jVRWsJGufTp850VsBwEakVeIqBYpqbGgrWCu2b/aUf9PunbXEKu1DxPKF7yfl1U3ZqJa/N4+tQ/nawPviI4D4jq+qEIgPGuoBkUTPJQVw28K3vVUE2muDL5FTW7eLz9ADPV/30dRMnnXeWVcZkV/VUrDUXxs1aljf/7RooHRt1jL2YMb5ACwV8PrY32CNX17MtnT/dYuTiel94601foj84mXsYb2zR/+cYzp89nOCH2m0X/YcLLd07xsrEvVvDD+Y+OE0oWklWPgDnr3xC8E+pmBLIxkZZwDx1mh02UuZhDwSsC8MTLcsI05/be37w83r5faFM2Trnt1eHgh5KpSxhC2vOWfOJFl6YKdG3Lkkdc9tvocDpBVPrQQLFbaotM0mVg8Uf1NaNT4iLU6xPBcD/AflMzPTcsywkL/gkc2x4I60U8ykMKPCzAoNpTWYpeSy/MtmCH68/D2qUWzar8tZ/FCeO3eSJ66wecqgi3KeBUYKMM/OtBEsHHKP41yC7aZufeUeTYvY8mRe67bgEtiEt59R+W5aP/iDn4BdDQfKFPBHf2v3vjKqQ2HnnCNFgEpzNMzSkACPukGkkBeG2Ca5hS1KP7QQrGsWvCEzNqyu5VfcU+MoQRbaV7ByH8la+M+mDwHECMWf/okgiA9mVVHkHtUTcuM4aQQU1WdM6Dcia3mFPrSzW5K6YP1+xXx59MCphqqJ3+ncWx4oPlN3fpHaF0zGY3mB2RZbugQgUNgG5pcp5Junqs8LdZaNlMD0YWMjdRpj6/qP3vT6NHkikKpgIUjjKytk296DX7RpflgTGYnCygIP3os02gl2FjyEkEWmCcLP8igs/VCpjuUUllE4EDJb4WehVsYpWLD99Hee8XyIa/ZWqP+53p+aYGGrzci5L9SoXscnt67rUpzXkca5OmzCdcE3iPgDwRSeLTkCiMG9S9/zNiqjYVb1aElpJMu/bF6ogoU3jKiLiqr5+bG4z4mLyt76+klNsPyvcfjGndTiaLn/5DPldI33MSUREP8Z+IM5Z87fM7VaWCZM0GiDd5Iskn6WuqUmzlmV6pcqWEjk4wDKKJqfG03Kjyhs1k6wgm8EbauxiipowZkWRSsqstn7wZIJH91VZ1X51FTlY2UcgqWWMJhWb1UXw8RnWNiRrhaG6vA12XwGWFL3sMA0GdLIHSKxDt6Yjdx50oBEq79VwYoqzzSm7GX5YNNaOb5pc1lQenUyIGN+SqKChUHx9OrF3jEaaJhZXdOlDzcANxBk/PJfUvZyphIar9GnDx0bupo65rFkZPfBuqo43gDmAiZqwVKPjHnxjFHWpFoSFawOrz+eiR3Eysbq9VwGZz7XBEULiVnktFgVnw/N/feodVWYVf2699C8K9Xzt2L/napgFVo4qh4ZE2fVfKE+53N/YoL1s8Vz5K+rF3k2tj2imffW65RWbfOx2dl7IFrYYe9v4YBooU7LpGN2dAieL/44VgX/X4dDIFXBKrROyj8yxoa3gsHxkohgqWIFA/BhRnygkS08ASxhIFr+RlmIFo5ejqM2KLx1et/hH1Os7v/DiQo6sItKsNQjY0w6hSHXkRO7YKnbAWAUjn/FcpCtMALq7n7ktHgYYN08MYvCPlVsVoZoYebxve6nytVd+hQWhAjvVgUr372kajV7ocvKCF2LtKvYBesXi+fIXw4sBTmzijR2oooWek7ypMpoPYmvN/wRowDU3/+nw/Ivm7eqYOWzz0+tZkf/phzIFzbysQvWup1fyWvrV3mviq/o3Cusfby+HgLBnBYuzWew2wgZb6TxyTV//x+KMfGxEl3zfYUekawuBQvNgek8HmIXLJ2dt8G2/Rtz384k4uHTgyXD5fJObv44BLfUYPl3Q7cSGduxKLZtNVGMI7UMARufw7z9VZeCUVbJR+FX1H1QsKImmkJ/2UTLteUhGOA8Kf88dYQB1d34X9jTP1MIoby6bqXc+sl0aXLIoVI18pacTcAsGwfy+Ute2+NOwcp5aOh9IQbulR++Jp9s2ZAx9On+35Jz2nbR2/AIrFNPVEB3SDjjPLEws5QIzCioi7n/WiOXzXtV2jRpKnOHXyktGx+eU3/qUtK2mqtsAChYOQ0LMy7CdxvvW1aW2UmAz6GZ+oWhXIgHD9TDckiXMoVc7FevySeHhR+pnm+N97pBjnh+6VVaL3vDMqFgRUFM8z6CezWfG3ihDDumk+ZWhzMv+N0/P09lypdfsnmLsgscCoCW6xs+22uuKFjh/i6MvVr9tR7Xe4iXx7GhBRPqaWxSjotjWMGCaJ87Z5JnDgT7w9Lozs+Ky8co+uWSMAqKmvVRcyNtB68+y+RWV0I9zHf/dPc/rGCpsyuXSlkoWLqP5DzsUz+XZvpZY8E8FRLLSKib8OYvTOjC5LDUY7SjOoomjK1pXkvBSpN+TM8et/R9eaJyodf7fX2GydVdTo7pSfF1+/aG1fKLJXMyr+tNfPMXhk6YGZb6DUPbyxiCDClYYUaVIdcit4EcR9hX5Dq4F6xQR34GM6p8P1Cqg0+52KDOmtZe8P06b1E/B2frfsH6eFGwchlNBl0zfUOVXLtgqmexSctBCCy+TuMfT4yE+t1Fg7TaoBznMMhlhoUyhsGznpXNu3d5puT6NjFOu5Pum4KVNPGYn/f4Z594tVhoP+85yDuVQOcWPPIFttqap6ovDrnksNSTT1AQjMJg1xoFy7KI47x81GK1P6KZTBs6Vo45vKmWHgaPJoaRWP7hu3+6blCOE2RDgqWeIgo7XMtd+ewpWHGOwoT73rrnPzJ01t9k0+6dWi8HvQ/oVlV4p32iYfl3Y7eSyD77njD2SB7XkGCpiXaX6q6CcClYkQw3PTqp2LpRRsx93jNGxyNGgnv+YGdaH33QI2IHragvh6WexoA7bDxJNNd4ULByJWXAdTgzH8dRoz3St1Qu7VikhdX4g0NCHcsav2GWgCp8HY4n1gHS/M3r5eIPXpQjD20sK0fcVMMk/4x2fzbqwp7BumJCwdJhtEZkg7qPUIc3SPuPvZmZOUSPy7+6A13XaQ1quQPuduFEhvr+HChYEYmFDt18sGmdjCl7SZoeepisGnFzaiYhN4UZ1aTq5Zk8lb/8e7Sk1PoTBfIBX1cOS81doV9Xk+0+UwpWPqNL03v8GVaaBaPBM9SBCttHUPzp4tu/XIdKthyWusEZ/bicbKdg5TqSDLquoTdNcbqC5d/1H02tladyoUo9Cq7ZYhf84pSOL1Ki8D1MH5xhhaGl+bXqrzQO7sMBfnE3CNX9y8vklXUrM4/yj33R/Rz1uNmE6T+bYBVNe1K2792d6UaHvGQYn+K4loIVB9WU+vz431/Khe9P8Z4ed64jW4U6nutilXoU4Q4uCZFsxwsLv9n+cYlcGVKwciVlwHXqG6W4BKuuhPrxTZvLb3oPZZlCnuMkuPk5+M3JfD+umqc52t5GwdI2NOENi1uwUPg54cDXk1XrXH/VHj5Ste9Ql4QPFg+XH1XMqrHEXn7+jVE8xvg+KFjGh/CgA3EJVvAMdf+JyFVh7x+LPwsfRKpgnXlsZ3l34xeZTvmDcJAvBavwsaZVDx1ef9yzJ4o3Sv7yDzOrYEOpwlP9RrKmKqLoq6fENjussezYuyfTc9gPq0ZkkpbdULC0DEv+RvmChZqnQs5yDx5NrFrk8l62/CNT/53BEgb/ateOQG6ILwWrIUKG/XuhgoVlJf541H1/PgK8qcIS0KQPlJoSPvUcM9Xmn5x0utx+Yj9T3IjdTgpW7IiTfcDvls+Tx1Z9HLoqOnjip2o1j3+JP4ajy16usecST+zWrJX3FWg25rCsHQN3LXpXnv18iedffWeD+wCqdmyViZ8vzny0IgiGdVXJDBV/hnVIo0byv337vIf+vOcZ8r3upyRjgCFP4QzLkEDlauaU6k/ltoVv5yRY6pupYP84pwpfUub+v1zJF3bd/cvnyR9XfVyjk9lnXiEnNG9dWMeW3U3BsiygasV0XZ/4wocqnqgsr7UEAYr+R7eX3/YZxjxVwuMiuCQ8tXVbeW3w6ISt0P9xFCz9YxTKQmyZGfjORO+eoGDhNIfJ1Z/KjA2ra/WJmdT1XYtlRLtuoZ7Hi6Mh4L8s8XuLoiwlGsv06oWCpVc8CrYGn4A6efoEr5/2RzSXyzv3FCwTWzY+XHCEcrbGP46CsRfcQVCwktq8XrDhCXdAwUoYeBKPGzhzoqzZub3BR+EI5Wu7Fktxy2MbvJYXxEtAPQb5pm595Z5eg+N9oKG9U7AMDVx9ZteXTMd9WP7d2aM/E+oaxX7R1o3ys0Wz5bTW7byPTLBlJ0DBsnBkbNmzS35c/q4s2vZP6dj0KM/D7s1aecvC4cd1plBZGHNXXKJguRJp+kkCFhCgYFkQRLpAAq4QoGC5Emn6SQIWEKBgWRBEukACrhCgYLkSafpJAhYQoGBZEES6QAKuEKBguRJp+kkCFhCgYFkQRLpAAq4QoGC5Emn6SQIWEKBgWRBEukACrhCgYLkSafpJAhYQoGBZEES6QAKuEKBguRJp+kkCFhCgYFkQRLpAAq4QoGC5Emn6SQIWEKBgWRBEukACrhCgYLkSafpJAhYQoGBZEES6QAKuEKBguRJp+kkCFhCgYFkQRLpAAq4QoGC5Emn6SQIWEKBgWRBEukACrhCgYLkSafpJAhYQoGBZEES6QAKuEKBguRJp+kkCFhCgYFkQRLpAAq4QoGC5Emn6SQIWEKBgWRBEukACrhCgYLkSafpJAhYQoGBZEES6QAKuEKBguRJp+kkCFhCgYFkQRLpAAq4QoGC5Emn6SQIWEKBgWRBEukACrhCgYLkSafpJAhYQoGBZEES6QAKuEKBguRJp+kkCFhCgYFkQRLpAAq4QoGC5Emn6SQIWEKBgWRBEukACrhCgYLkSafpJAhYQoGBZEES6QAKuEKBguRJp+kkCFhCgYFkQRLpAAq4QoGC5Emn6SQIWEKBgWRBEukACrhCgYLkSafpJAhYQoGBZEES6QAKuEKBguRJp+kkCFhCgYFkQRLpAAq4QoGC5Emn6SQIWEKBgWRBEukACrhCgYLkSafpJAhYQoGBZEES6QAKuEKBguRJp+kkCFhCgYFkQRLpAAq4QoGC5Emn6SQIWEKBgWRBEukACrhD4Py9mPU4PwXnuAAAAAElFTkSuQmCC" }, { + timestamp: "2025-09-13", custom: { min: 3, max: 9 }, boolValue: true, organization_type: "other", @@ -421,6 +423,7 @@ var data = [ survey_cloud_platform: "", }, { + timestamp: "2025-10-14", Quality: { affordable: "1", "does what it claims": "1", @@ -450,6 +453,7 @@ var data = [ product_improvement: "", }, { + timestamp: "2025-10-15", Quality: { affordable: "3", "does what it claims": "4", @@ -477,6 +481,7 @@ var data = [ survey_cloud_platform: "", }, { + timestamp: "2025-10-16", Quality: { affordable: "3", "does what it claims": "4", @@ -503,6 +508,7 @@ var data = [ product_improvement: "", }, { + timestamp: "2025-10-17", organization_type: "Consulting", developer_count: "> 10", VerticalMarket: "Telecommunications", @@ -525,6 +531,7 @@ var data = [ product_improvement: "", }, { + timestamp: "2025-10-18", organization_type: "In-house", developer_count: "2", VerticalMarket: "Healthcare", @@ -551,6 +558,7 @@ var data = [ favorite_functionality: "", }, { + timestamp: "2025-10-19", organization_type: "Consulting", developer_count: "> 10", VerticalMarket: "Banking", @@ -572,6 +580,7 @@ var data = [ product_improvement: "", }, { + timestamp: "2024-10-13", organization_type: "Custom", developer_count: "3-5", VerticalMarket: "Financial", @@ -597,6 +606,7 @@ var data = [ product_improvement: "", }, { + timestamp: "2024-09-13", organization_type: "In-house", developer_count: "1", VerticalMarket: "Education", @@ -619,6 +629,7 @@ var data = [ favorite_functionality: "", }, { + timestamp: "2025-10-21", organization_type: "Consulting", developer_count: "3-5", VerticalMarket: "Government (federal, state, local)", @@ -644,6 +655,7 @@ var data = [ product_improvement: "", }, { + timestamp: "2025-10-22", organization_type: "In-house", developer_count: "3-5", VerticalMarket: "Retail", diff --git a/examples/date_period_field_name_apexcharts.html b/examples/date_period_field_name_apexcharts.html new file mode 100644 index 000000000..5450b3ee8 --- /dev/null +++ b/examples/date_period_field_name_apexcharts.html @@ -0,0 +1,29 @@ + + + + + Summary Example + + + + + + + + + + + + + + +
+ + + + + \ No newline at end of file diff --git a/examples/date_period_field_name_apexcharts.js b/examples/date_period_field_name_apexcharts.js new file mode 100644 index 000000000..0ee8b720b --- /dev/null +++ b/examples/date_period_field_name_apexcharts.js @@ -0,0 +1,22 @@ +var survey = new Survey.SurveyModel(json); + +var options = { + datePeriodFieldName: "timestamp", +}; + +var visPanel = new SurveyAnalyticsApexcharts.VisualizationPanel( + // [ survey.getQuestionByName("organization_type"), survey.getQuestionByName("backend_language") ], + survey.getAllQuestions(), + data, + options +); +visPanel.onDatePeriodElementShown.add((sender, options) => { + options.initialRange = { + start: Date.parse("2025-10-15"), + end: Date.parse("2025-10-15") + }; + // options.showTotalCount = false; + // options.chipsConfig = null; +}); +visPanel.showToolbar = true; +visPanel.render(document.getElementById("summaryContainer")); diff --git a/examples/debug.html b/examples/debug.html index 1821133f0..9fa4e9558 100644 --- a/examples/debug.html +++ b/examples/debug.html @@ -5,7 +5,8 @@ Debug Example - + + diff --git a/examples/debug_apexcharts.html b/examples/debug_apexcharts.html new file mode 100644 index 000000000..2145702b7 --- /dev/null +++ b/examples/debug_apexcharts.html @@ -0,0 +1,26 @@ + + + + + Debug Example + + + + + + + + + + + + + +
+ + + + + + \ No newline at end of file diff --git a/examples/debug_apexcharts.js b/examples/debug_apexcharts.js new file mode 100644 index 000000000..6f77781a4 --- /dev/null +++ b/examples/debug_apexcharts.js @@ -0,0 +1,124 @@ + +// var json = JSON.parse(jsonStr); +const json = { + "locale": "fr", + "elements": [ + { + "type": "dropdown", + "name": "satisfaction", + "title": { + "default": "How satisfied are you with our product?", + "fr": "Êtes-vous satisfait du produit?", + "es": "¿Qué tan satisfecho estás con nuestro producto?" + }, + "choices": [ + { + "value": 0, + "text": { + "default": "Not satisfied", + "fr": "Pas satisfait", + "es": "No satisfecho" + } + }, + { + "value": 1, + "text": { + "default": "Satisfied", + "fr": "Satisfait", + "es": "Satisfecho" + } + }, + { + "value": 2, + "text": { + "default": "Completely satisfied", + "fr": "Complètement satisfait", + "es": "Completamente satisfecho" + } + } + ] + }, + { + "type": "dropdown", + "name": "recommendation", + "title": { + "default": "How likely are you to recommend our product to a friend or colleague?", + "fr": "Quelle est la probabilité que vous recommandiez notre produit à un ami ou un collègue ?", + "es": "¿Qué probabilidades hay de que recomiende nuestro producto a un amigo o colega?" + }, + "choices": [ + { + "value": 1, + "text": { + "default": "I won't recommend", + "fr": "Je ne recommanderai pas", + "es": "No lo recomendaré" + } + }, + { + "value": 2, + "text": { + "default": "Unlikely", + "fr": "Je ne le recommanderais pas", + "es": "Yo no lo recomendaría" + } + }, + { + "value": 3, + "text": { + "default": "Possibly", + "fr": "Je pourrais le recommander", + "es": "Podría recomendarlo" + } + }, + { + "value": 4, + "text": { + "default": "Likely", + "fr": "Très probablement à recommander", + "es": "Lo más probable es que lo recomienden" + } + }, + { + "value": 5, + "text": { + "default": "I will recommend", + "fr": "Je le recommande vivement", + "es": "Lo recomiendo altamente" + } + } + ] + } + ] +}; + +function randomIntFromInterval(min, max) { + return Math.floor(Math.random() * (max - min + 1) + min); +} +function generateData() { + const data = []; + for (let index = 0; index < 100; index++) { + data.push({ + satisfaction: randomIntFromInterval(0, 2), + recommendation: randomIntFromInterval(0, 5) + }); + } + return data; +} +const dataFromServer = generateData(); + +const survey = new Survey.Model(json); + + const vizPanel = new SurveyAnalyticsApexcharts.VisualizationPanel( + survey.getAllQuestions(), + dataFromServer, + { + allowHideQuestions: false, + survey: survey + } + ); + + + // vizPanel.render("surveyDashboardContainer"); + +vizPanel.render(document.getElementById("summaryContainer")); diff --git a/examples/declarative.html b/examples/declarative.html new file mode 100644 index 000000000..889d221d3 --- /dev/null +++ b/examples/declarative.html @@ -0,0 +1,21 @@ + + + + + Declarative dashboard example + + + + + + + + + + + +
+ + + + \ No newline at end of file diff --git a/examples/declarative.js b/examples/declarative.js new file mode 100644 index 000000000..866a57b64 --- /dev/null +++ b/examples/declarative.js @@ -0,0 +1,140 @@ +function generateValues (maxValue, stepsCount) { + const values = []; + + for (let i = 0; i < stepsCount; i++) { + values.push(maxValue / stepsCount); + } + values.push(maxValue); + + return values; +} + +function getData (visualizer, minValue, maxValue, level, arrowColor) { + const stepsCount = SurveyAnalytics.GaugePlotly.stepsCount; + const values = generateValues(maxValue, stepsCount); + const text = [ "Most likely", "Likely", "Neutral", "Unlikely", "Most unlikely" ]; + const colors = visualizer.generateColors(maxValue, minValue, stepsCount); + + return [ + // Draw a dot for the gauge arrow + // https://plotly.com/javascript/reference/scatter/ + { + type: "scatter", + name: name, + text: level, + x: [0], + y: [0], + marker: { + size: 20, + color: arrowColor + }, + showlegend: false, + hoverinfo: "text+name" + }, + + // Draw gauge sectors + // https://plotly.com/javascript/reference/pie/ + { + type: "pie", + values: values, + rotation: 90, + text: text, + textinfo: "text", + textposition: "inside", + marker: { + colors: colors + }, + hole: 0.55, + showlegend: false, + hoverinfo: "skip" + } + ]; +} + +function getLayout (maxValue, level, arrowColor) { + const degrees = maxValue - level; + const radius = 0.5; + const radians = (degrees * Math.PI) / maxValue; + const x = radius * Math.cos(radians); + const y = radius * Math.sin(radians); + const baseX = 0.49; + const baseY = 0.25; + // Build SVG markup for the gauge arrow + const path = "M " + (baseX - 0.01) + " " + baseY + " L " + (baseX + 0.01) + " " + baseY + " L " + (baseX + x) + " " + (baseY + y) + " Z"; + + // https://plotly.com/javascript/reference/layout/ + const layout = { + title: level, + height: 600, + width: 600, + // Draw the gauge arrow + shapes: [{ + type: "path", + path: path, + fillcolor: arrowColor, + line: { + color: arrowColor + } + }], + plot_bgcolor: "transparent", + paper_bgcolor: "transparent", + }; + + return layout; +} + +SurveyAnalytics.PlotlySetup.onPlotCreating.add((visualizer, options) => { + const arrowColor = "#4e6198"; + const level = options.data.datasets[0][options.data.labels.indexOf("average")]; + const maxValue = options.data.datasets[0][options.data.labels.indexOf("max")]; + const minValue = options.data.datasets[0][options.data.labels.indexOf("min")]; + options.data = getData(visualizer, minValue, maxValue, level, arrowColor); + options.layout = getLayout(maxValue, level, arrowColor); +}); + +var options = { + // allowDynamicLayout: false, + // allowDragDrop: false, + // allowHideQuestions: false, + // allowShowPercentages: true, + // showPercentages: true, + // showOnlyPercentages: true, + // useValuesAsLabels: false + // haveCommercialLicense: false, + // allowSortAnswers: true, + // answersOrder: "desc" + // allowHideEmptyAnswers: true, + // hideEmptyAnswers: true, + // allowTopNAnswers: true, + // showCorrectAnswers: true + // labelTruncateLength: 27, +}; + +const visualizerDefinition1 = { + visualizerType: "card", + dataName: "test", + displayValueName: "count", + title: "Total answers count - Card" +}; + +const visualizerDefinition2 = { + visualizerType: "gauge", + chartType: "bullet", + dataName: "test", + displayValueName: "count", + title: "Total answers count - Gauge bullet" +}; + +const visualizerDefinition3 = { + visualizerType: "gauge", + chartType: "gauge", + dataName: "test", + title: "Total answers count - Gauge gauge" +}; + +const data = [{ test: 1 }, { test: 10 }, { test: 8 }, { test: 7 }, { test: 9 }, { test: 9 }, {}]; +let visPanel = new SurveyAnalytics.VisualizationPanel([visualizerDefinition1, visualizerDefinition2, visualizerDefinition3], data, options); + + +visPanel.showToolbar = true; +visPanel.render(document.getElementById("summaryContainer")); diff --git a/examples/disable_layout_engine_apexcharts.html b/examples/disable_layout_engine_apexcharts.html new file mode 100644 index 000000000..2de53d711 --- /dev/null +++ b/examples/disable_layout_engine_apexcharts.html @@ -0,0 +1,29 @@ + + + + + Disable the Layout Engine + + + + + + + + + + + + + + +
+ + + + + \ No newline at end of file diff --git a/examples/disable_layout_engine_apexcharts.js b/examples/disable_layout_engine_apexcharts.js new file mode 100644 index 000000000..bc1db67d8 --- /dev/null +++ b/examples/disable_layout_engine_apexcharts.js @@ -0,0 +1,29 @@ +var survey = new Survey.SurveyModel(json); +var options = { + // allowTransposeData: true, + // allowDragDrop: false, + // allowHideQuestions: false, + // allowShowPercentages: true, + // showPercentages: true, + // showOnlyPercentages: true, + // useValuesAsLabels: false + // haveCommercialLicense: false, + // allowSortAnswers: true, + // answersOrder: "desc" + // allowHideEmptyAnswers: true, + // hideEmptyAnswers: true, + // allowTopNAnswers: true, + // showCorrectAnswers: true + // labelTruncateLength: 27, + allowDynamicLayout: false, +}; + +var visPanel = new SurveyAnalyticsApexcharts.VisualizationPanel( + [ survey.getQuestionByName("organization_type"), survey.getQuestionByName("backend_language") ], + // survey.getAllQuestions(), + data, + options +); + +visPanel.showToolbar = true; +visPanel.render(document.getElementById("summaryContainer")); diff --git a/examples/histogram.html b/examples/histogram.html index 0d7812590..fa23849a5 100644 --- a/examples/histogram.html +++ b/examples/histogram.html @@ -15,6 +15,9 @@ + + +

diff --git a/examples/histogram.js b/examples/histogram.js index 202eafdcc..290664781 100644 --- a/examples/histogram.js +++ b/examples/histogram.js @@ -159,6 +159,24 @@ var data = [ data.forEach(function(item) { delete item.date; }); data = data.concat(salesData); +// SurveyAnalytics.DashboardTheme.backgroundColor = "gray"; +// SurveyAnalytics.DashboardTheme["--dsb-item-background-color"] = "gray"; +// SurveyAnalytics.DashboardTheme["--sa-dropdown-bg"] = "gray"; + +// SurveyAnalytics.VisualizerBase.customColors = [ +// "#f3cec9", +// "#e7a4b6", +// "#cd7eaf", +// "#a262a9", +// "#6f4d96", +// "#3d3b72", +// "#182844", +// "#6f4d96", +// "#3d3b72", +// "#182844", +// ]; + + var visPanel = new SurveyAnalytics.VisualizationPanel( // [survey.getQuestionByName("date")], survey.getAllQuestions(), @@ -187,6 +205,18 @@ var visPanel = new SurveyAnalytics.VisualizationPanel( } } ); + +const checkbox = document.getElementById('toggle-checkbox'); +checkbox.addEventListener('change', () => { + if (checkbox.checked) { + visPanel.applyTheme(SurveyAnalytics.DefaultDark); + } else { + visPanel.applyTheme(SurveyAnalytics.Default); + } +}); + +// visPanel.applyTheme(SurveyAnalytics.DefaultDark); + visPanel.showToolbar = true; // visPanel.onAlternativeVisualizerChanged.add(function(sender, options) { // visPanel.visualizers.forEach(visualizer => { diff --git a/examples/histogram_apexcharts.html b/examples/histogram_apexcharts.html new file mode 100644 index 000000000..ba1dfa6d4 --- /dev/null +++ b/examples/histogram_apexcharts.html @@ -0,0 +1,30 @@ + + + + + Date and number histogram visualization Example with ApexCharts + + + + + + + + + + + + + + + + + + +

+
+ + + + + \ No newline at end of file diff --git a/examples/histogram_apexcharts.js b/examples/histogram_apexcharts.js new file mode 100644 index 000000000..53d6bc238 --- /dev/null +++ b/examples/histogram_apexcharts.js @@ -0,0 +1,479 @@ +var json = { + elements: [ + { + "type": "rating", + "name": "nps_score", + "title": "How likely are you to recommend our product to a friend or colleague?" + }, + { + type: "text", + inputType: "date", + name: "date", + }, + { + type: "text", + inputType: "number", + name: "age", + }, + { "type": "rating", "name": "question1", "rateValues": [{ "value": 1, "text": "15 minutes" }, { "value": 2, "text": "30 minutes" }, { "value": 3, "text": "1 hour" }] }, + { + "type": "text", + "name": "question2", + "inputType": "number" + }, + { + type: "matrixdropdown", + name: "question2", + title: "What do you feel about these brands?", + isRequired: true, + columns: [ + { + name: "Column 1", + title: "My Opinion", + choices: ["High Quality", "Natural", "Trustworthy"], + }, + { + name: "Column 2", + title: "Review Mark", + choices: [1, 2, 3, 4, 5], + }, + ], + rows: ["Lizol", "Harpic"], + }, + { + type: "dropdown", + name: "m0", + choices: [ + { value: "FRA", text: "France" }, + { value: "ATG", text: "Antigua and Barbuda" }, + { value: "ALB", text: "Albania" }, + ], + }, + ] +} +var survey = new Survey.SurveyModel(json); + +var data = [ + { + nps_score: 1, + date: "2021-10-13", + age: 17 + }, + { + nps_score: 1, + date: "2021-10-13", + age: 17 + }, + { + nps_score: 5, + date: "2021-10-13", + age: 17 + }, + { + nps_score: 10, + date: "2011-10-13", + age: 30 + }, + { + nps_score: 5, + date: "2011-10-13", + age: 30 + }, + { + nps_score: 5, + date: "2004-10-13", + age: 40 + }, + { + nps_score: 5, + date: "2004-10-13", + age: 40 + }, + { + nps_score: 5, + date: "2016-10-13", + age: 25 + }, + { + nps_score: 6, + date: "2017-10-13", + age: 25 + }, + { + date: "2018-10-13", + age: 25 + }, + { + date: "2019-10-13", + age: 25 + }, + { + date: "2020-10-13", + age: 25 + }, + { + date: "2021-10-13", + age: 25 + }, + { + nps_score: 7, + date: "2022-10-13", + age: 25 + }, + { + nps_score: 8, + date: "2023-10-13", + age: 25 + }, + { + nps_score: 9, + date: "2024-10-13", + age: 25 + }, + { + nps_score: 2, + date: "2025-10-13", + age: 25 + }, + { + nps_score: 2, + date: "2026-10-13", + age: 25 + }, + { + nps_score: 3, + date: "2027-10-13", + age: 25 + }, + { + nps_score: 4, + date: "2028-10-13", + age: 25 + }, + { + nps_score: 4, + date: "2029-10-13", + age: 25 + }, + { + nps_score: 0, + date: "2030-10-13", + age: 25 + }, + // { "question1": 3 }, + // { "question1": 1 }, + // { "question1": 3 }, + + { + "hystogram-without-series-labels-rows": { + "Row 1": { + "Column 1": 1, + "Column 2": 1, + }, + "Row 2": { + "Column 1": 2, + "Column 2": 2 + }, + // "Row 3": { + // "Column 1": 3, + // "Column 2": 1 + // }, + // "Row 4": { + // "Column 1": 4, + // "Column 2": 4 + // }, + // "Row 5": { + // "Column 1": 5, + // "Column 2": 5 + // } + }, + "hystogram-matrixdynamic": [ + { + "Column 1": 1, + "Column 2": 1, + }, + { + "Column 1": 2, + "Column 2": 2 + }, + { + "Column 1": 3, + "Column 2": 3 + }, + { + "Column 1": 4, + "Column 2": 4 + }, + { + "Column 1": 5, + "Column 2": 5 + } + ], + question1: { Lizol: "Excellent", Harpic: "Excellent" }, + question2: { + Lizol: { "Column 1": "Trustworthy", "Column 2": 3 }, + Harpic: { "Column 1": "High Quality", "Column 2": 4 }, + }, + }, + { + "hystogram-without-series-labels-rows": { + "Row 1": { + "Column 1": 5 + }, + "Row 2": { + "Column 1": 4 + }, + // "Row 3": { + // "Column 1": 3 + // }, + // "Row 4": { + // "Column 1": 2 + // }, + // "Row 5": { + // "Column 1": 1 + // } + }, + question1: { Lizol: "Very Good", Harpic: "Very Good" }, + question2: { + Lizol: { "Column 1": "Natural", "Column 2": 3 }, + Harpic: { "Column 1": "Natural", "Column 2": 4 }, + }, + }, + { + "hystogram-without-series-labels-rows": { + "Row 1": { + "Column 1": 1 + }, + "Row 2": { + "Column 1": 1 + }, + // "Row 3": { + // "Column 1": 1 + // }, + // "Row 4": { + // "Column 1": 1 + // }, + // "Row 5": { + // "Column 1": 1 + // } + }, + question1: { Lizol: "Very Good", Harpic: "Good" }, + question2: { + Lizol: { "Column 1": "Natural", "Column 2": 1 }, + Harpic: { "Column 1": "Trustworthy", "Column 2": 5 }, + }, + }, + +]; + +data = data.concat([ + { + m0: "FRA", + m11: "FRA", + m1: "FRA", + }, + { + m0: "FRA", + m11: "FRA", + m1: "FRA", + }, + { + m0: "ALB", + m11: "ALB", + m1: "ALB", + }, + { + m0: "ATG", + m11: "ATG", + m1: "ATG", + }, +]); + +// class ApexChartsHistogramVisualizer extends SurveyAnalyticsCore.VisualizerBase { +// constructor(question, data, options = {}) { +// super(question, data, options); +// this.chart = null; +// } + +// get name() { +// return "apexcharts-histogram"; +// } + +// get displayName() { +// return "ApexCharts Histogram"; +// } + +// get iconClass() { +// return "sa-visualizer-bar"; +// } + +// getSupportedTypes() { +// return ["number", "text"]; +// } + +// afterRender(container) { +// const chartContainer = document.createElement("div"); +// chartContainer.style.width = "100%"; +// chartContainer.style.height = "400px"; +// container.appendChild(chartContainer); + +// const chartData = this.getChartData(); + +// const options = { +// series: [{ +// name: this.question.title || this.question.name, +// data: chartData.data +// }], +// chart: { +// type: 'bar', +// height: 350, +// toolbar: { +// show: true +// } +// }, +// plotOptions: { +// bar: { +// horizontal: false, +// columnWidth: '55%', +// endingShape: 'rounded' +// }, +// }, +// dataLabels: { +// enabled: false +// }, +// stroke: { +// show: true, +// width: 2, +// colors: ['transparent'] +// }, +// xaxis: { +// categories: chartData.categories, +// title: { +// text: this.question.title || this.question.name +// } +// }, +// yaxis: { +// title: { +// text: 'Frequency' +// } +// }, +// fill: { +// opacity: 1 +// }, +// tooltip: { +// y: { +// formatter: function (val) { +// return val + " responses" +// } +// } +// } +// }; + +// this.chart = new ApexCharts(chartContainer, options); +// this.chart.render(); +// } + +// getChartData() { +// const values = this.getValues(); +// const valueCounts = {}; + +// values.forEach(value => { +// if (value !== undefined && value !== null) { +// const key = value.toString(); +// valueCounts[key] = (valueCounts[key] || 0) + 1; +// } +// }); + +// const categories = Object.keys(valueCounts).sort((a, b) => { +// const numA = parseFloat(a); +// const numB = parseFloat(b); +// return isNaN(numA) || isNaN(numB) ? a.localeCompare(b) : numA - numB; +// }); + +// const data = categories.map(cat => valueCounts[cat]); + +// return { categories, data }; +// } + +// getValues() { +// return this.data.map(item => item[this.question.name]).filter(val => val !== undefined && val !== null); +// } + +// destroy() { +// if (this.chart) { +// this.chart.destroy(); +// this.chart = null; +// } +// } +// } + +// SurveyAnalyticsCore.VisualizationManager.registerVisualizer("apexcharts-histogram", ApexChartsHistogramVisualizer); + +// SurveyAnalyticsCore.VisualizationManager.registerVisualizer("date", ApexChartsHistogramVisualizer); +// SurveyAnalyticsCore.VisualizationManager.registerVisualizer("number", ApexChartsHistogramVisualizer); +// SurveyAnalyticsCore.VisualizationManager.registerVisualizer("rating", ApexChartsHistogramVisualizer); + + +var options = { + // allowDynamicLayout: false, + // allowDragDrop: false, + // allowHideQuestions: false, + // allowShowPercentages: true, + // showPercentages: true, + // showOnlyPercentages: true, + // useValuesAsLabels: false + // haveCommercialLicense: false, + // allowSortAnswers: true, + // answersOrder: "desc" + // allowHideEmptyAnswers: true, + // hideEmptyAnswers: true, + // allowTopNAnswers: true, + // showCorrectAnswers: true + // labelTruncateLength: 27, +}; + +var visPanel = new SurveyAnalyticsApexcharts.VisualizationPanel( + survey.getAllQuestions(), + data, + { + allowSortAnswers: true, + allowShowPercentages: true, + allowTransposeData: true, + allowTopNAnswers: true, + age: { + intervals: [ + { start: 0, end: 7, label: "childhood" }, + { start: 7, end: 14, label: "adolescence" }, + { start: 14, end: 19, label: "youth" }, + { start: 19, end: 70, label: "adult" }, + { start: 70, end: 100, label: "old age" } + ] + } + } +); + +const checkbox = document.getElementById('toggle-checkbox'); +checkbox.addEventListener('change', () => { + if (checkbox.checked) { + visPanel.applyTheme(SurveyAnalyticsApexcharts.DefaultDark); + } else { + visPanel.applyTheme(SurveyAnalyticsApexcharts.Default); + } +}); + +visPanel.showToolbar = true; +visPanel.onAlternativeVisualizerChanged.add(function(sender, options) { + visPanel.visualizers.forEach(visualizer => { + if(typeof visualizer.setVisualizer === "function") { + visualizer.setVisualizer(options.visualizer.type, true); + } + }); +}); + +// visPanel.visualizers.forEach(visualizer => { +// if (visualizer.question.getType() === "rating" || visualizer.question.getType() === "text") { +// visualizer.setVisualizer("apexcharts-histogram", true); +// } +// }); + +visPanel.render(document.getElementById("summaryContainer")); \ No newline at end of file diff --git a/examples/matrix-one-row_apexcharts.html b/examples/matrix-one-row_apexcharts.html new file mode 100644 index 000000000..b18784483 --- /dev/null +++ b/examples/matrix-one-row_apexcharts.html @@ -0,0 +1,29 @@ + + + + + Matrix with One Row Example + + + + + + + + + + + + + + + +
+ + + + \ No newline at end of file diff --git a/examples/matrix-one-row_apexcharts.js b/examples/matrix-one-row_apexcharts.js new file mode 100644 index 000000000..2349514c4 --- /dev/null +++ b/examples/matrix-one-row_apexcharts.js @@ -0,0 +1,77 @@ +var json = { + "pages": [ + { + "name": "page_info", + "elements": [ + { + "type": "matrix", + "name": "Quality", + "title": "Please indicate if you agree or disagree with the following statements", + "columns": [ + { + "value": 1, + "text": "Strongly Disagree" + }, + { + "value": 2, + "text": "Disagree" + }, + { + "value": 3, + "text": "Neutral" + }, + { + "value": 4, + "text": "Agree" + }, + { + "value": 5, + "text": "Strongly Agree" + } + ], + "rows": [ + { + "value": "affordable", + "text": "Product is affordable" + } + ] + } + ] + } + ] +}; + +var survey = new Survey.SurveyModel(json); + +var data = [ + { + Quality: { + affordable: "3", + }, + }, + { + Quality: { + affordable: "3", + }, + }, + { + Quality: { + affordable: "5", + }, + }, +]; + +var options = { + // allowDynamicLayout: false, + // allowHideQuestions: false, + // allowSortAnswers: true, + allowTransposeData: true +}; + +var visPanel = new SurveyAnalyticsApexcharts.VisualizationPanel( + survey.getAllQuestions(), + data, + options +); +visPanel.showToolbar = true; +visPanel.render(document.getElementById("summaryContainer")); diff --git a/examples/matrixdropdown-grouped_apexcharts.html b/examples/matrixdropdown-grouped_apexcharts.html new file mode 100644 index 000000000..6e4d1d993 --- /dev/null +++ b/examples/matrixdropdown-grouped_apexcharts.html @@ -0,0 +1,31 @@ + + + + + Matrixes Dropdown Grouped Columns Example + + + + + + + + + + + + + + + +
+ + + + \ No newline at end of file diff --git a/examples/matrixdropdown-grouped_apexcharts.js b/examples/matrixdropdown-grouped_apexcharts.js new file mode 100644 index 000000000..27ee85362 --- /dev/null +++ b/examples/matrixdropdown-grouped_apexcharts.js @@ -0,0 +1,86 @@ +var json = { + "title": "question11", + "pages": [ + { + "name": "page2", + "elements": [ + { + "type": "matrixdropdown", + "name": "question4", + "title": "Please select the top 3 processes that you perceived as most difficult or troublesome.", + "showHeader": false, + "columns": [ + { + "name": "1st Most Difficult", + }, + { + "name": "2nd Most Difficult", + }, + { + "name": "3rd Most Difficult", + } + ], + "choices": [ + "Process 1", + "Process 2", + "Process 3", + "Process 4", + "Process 5", + "Process 6" + ], + "rows": [ + "Process" + ] + } + ] + } + ] +}; + +var survey = new Survey.SurveyModel(json); + +var data = [ + { + "question4": { + "Process": { + "1st Most Difficult": "Process 2", + "2nd Most Difficult": "Process 3", + "3rd Most Difficult": "Process 5" + } + } + }, + { + "question4": { + "Process": { + "1st Most Difficult": "Process 3", + "2nd Most Difficult": "Process 1", + "3rd Most Difficult": "Process 4" + } + } + }, + { + "question4": { + "Process": { + "1st Most Difficult": "Process 1", + "2nd Most Difficult": "Process 2", + "3rd Most Difficult": "Process 3" + } + } + }, +]; + +var options = { + // allowDynamicLayout: false, + // allowHideQuestions: false, + allowShowPercentages: true, + allowSortAnswers: true, + allowTransposeData: true +}; + +var visPanel = new SurveyAnalyticsApexcharts.VisualizationPanel( + survey.getAllQuestions(), + data, + options +); +visPanel.showToolbar = true; +visPanel.render(document.getElementById("summaryContainer")); diff --git a/examples/matrixes.html b/examples/matrixes.html index 8ef6fd84c..b2839aa46 100644 --- a/examples/matrixes.html +++ b/examples/matrixes.html @@ -11,7 +11,7 @@ - + diff --git a/examples/matrixes_apexcharts.html b/examples/matrixes_apexcharts.html new file mode 100644 index 000000000..c9782ea4d --- /dev/null +++ b/examples/matrixes_apexcharts.html @@ -0,0 +1,31 @@ + + + + + Matrixes Example + + + + + + + + + + + + + + + +
+ + + + \ No newline at end of file diff --git a/examples/matrixes_apexcharts.js b/examples/matrixes_apexcharts.js new file mode 100644 index 000000000..b77240a95 --- /dev/null +++ b/examples/matrixes_apexcharts.js @@ -0,0 +1,199 @@ +var json = { + pages: [ + { + name: "page1", + elements: [ + { + type: "matrix", + name: "question1", + title: "What is your perception of these brands?", + columns: [ + "Excellent", + "Very Good", + "Good", + "Fair", + "Neither Fair Nor Poor", + "Poor", + ], + rows: ["Lizol", "Harpic"], + }, + { + type: "matrixdropdown", + name: "question2", + title: "What do you feel about these brands?", + isRequired: true, + columns: [ + { + name: "Column 1", + title: "My Opinion", + choices: ["High Quality", "Natural", "Trustworthy"], + }, + { + name: "Column 2", + title: "Review Mark", + choices: [1, 2, 3, 4, 5], + }, + ], + rows: ["Lizol", "Harpic"], + }, + { + "type": "matrixdropdown", + "name": "hystogram-without-series-labels-rows", + "columns": [ + { + "name": "Column 1", + "cellType": "rating", + }, + { + "name": "Column 2", + "cellType": "text", + "inputType": "number" + } + ], + "rows": [ + "Row 1", + "Row 2", + // "Row 3", + // "Row 4", + // "Row 5" + ] + }, + { + "type": "matrixdynamic", + "name": "hystogram-matrixdynamic", + "columns": [ + { + "name": "Column 1", + "cellType": "rating", + choices: [1, 2, 3, 4, 5], + }, + { + "name": "Column 2", + "cellType": "text", + "inputType": "number" + } + ], + }, + ], + }, + ], +}; + +var survey = new Survey.SurveyModel(json); + +var data = [ + { + "hystogram-without-series-labels-rows": { + "Row 1": { + "Column 1": 1, + "Column 2": 1, + }, + "Row 2": { + "Column 1": 2, + "Column 2": 2 + }, + // "Row 3": { + // "Column 1": 3, + // "Column 2": 1 + // }, + // "Row 4": { + // "Column 1": 4, + // "Column 2": 4 + // }, + // "Row 5": { + // "Column 1": 5, + // "Column 2": 5 + // } + }, + "hystogram-matrixdynamic": [ + { + "Column 1": 1, + "Column 2": 1, + }, + { + "Column 1": 2, + "Column 2": 2 + }, + { + "Column 1": 3, + "Column 2": 3 + }, + { + "Column 1": 4, + "Column 2": 4 + }, + { + "Column 1": 5, + "Column 2": 5 + } + ], + question1: { Lizol: "Excellent", Harpic: "Excellent" }, + question2: { + Lizol: { "Column 1": "Trustworthy", "Column 2": 3 }, + Harpic: { "Column 1": "High Quality", "Column 2": 4 }, + }, + }, + { + "hystogram-without-series-labels-rows": { + "Row 1": { + "Column 1": 5 + }, + "Row 2": { + "Column 1": 4 + }, + // "Row 3": { + // "Column 1": 3 + // }, + // "Row 4": { + // "Column 1": 2 + // }, + // "Row 5": { + // "Column 1": 1 + // } + }, + question1: { Lizol: "Very Good", Harpic: "Very Good" }, + question2: { + Lizol: { "Column 1": "Natural", "Column 2": 3 }, + Harpic: { "Column 1": "Natural", "Column 2": 4 }, + }, + }, + { + "hystogram-without-series-labels-rows": { + "Row 1": { + "Column 1": 1 + }, + "Row 2": { + "Column 1": 1 + }, + // "Row 3": { + // "Column 1": 1 + // }, + // "Row 4": { + // "Column 1": 1 + // }, + // "Row 5": { + // "Column 1": 1 + // } + }, + question1: { Lizol: "Very Good", Harpic: "Good" }, + question2: { + Lizol: { "Column 1": "Natural", "Column 2": 1 }, + Harpic: { "Column 1": "Trustworthy", "Column 2": 5 }, + }, + }, +]; + +var options = { + allowTransposeData: true, + allowShowPercentages: true, + // allowDynamicLayout: false, + // allowHideQuestions: false +}; + +var visPanel = new SurveyAnalyticsApexcharts.VisualizationPanel( + survey.getAllQuestions(), + data, + options +); +visPanel.showToolbar = true; +visPanel.render(document.getElementById("summaryContainer")); diff --git a/examples/nps.html b/examples/nps.html new file mode 100644 index 000000000..30e5a78fa --- /dev/null +++ b/examples/nps.html @@ -0,0 +1,22 @@ + + + + + NPS visualization Example + + + + + + + + + + + +
+ + + + + \ No newline at end of file diff --git a/examples/nps.js b/examples/nps.js new file mode 100644 index 000000000..f669d1676 --- /dev/null +++ b/examples/nps.js @@ -0,0 +1,44 @@ +var json = { + "pages": [ + { + "name": "promotion", + "elements": [ + { + "type": "rating", + "name": "nps", + "title": "How likely are you to recommend our product to a friend or colleague?", + "isRequired": true, + "rateMin": 0, + "rateMax": 10, + "minRateDescription": "Most unlikely", + "maxRateDescription": "Most likely" + } + ] + } + ] +}; +var survey = new Survey.SurveyModel(json); + +function randomIntFromInterval(min, max) { + return Math.floor(Math.random() * (max - min + 1) + min); +} +function generateData() { + const data = []; + for (let index = 0; index < 1000; index++) { + data.push({ + nps: (index % 2) ? randomIntFromInterval(0, 10) : randomIntFromInterval(8, 10) + }); + } + return data; +} +var dataFromServer = generateData(); + +var vizPanel = new SurveyAnalytics.VisualizationPanel( + [{ + visualizerType: "nps", + question: survey.getAllQuestions()[0] + }], + dataFromServer, + { allowDynamicLayout: false, allowHideQuestions: false } +); +vizPanel.render(document.getElementById("container")); diff --git a/examples/pivot.html b/examples/pivot.html index 7733b9626..518f9699b 100644 --- a/examples/pivot.html +++ b/examples/pivot.html @@ -5,7 +5,6 @@ Pivot Chart Example - diff --git a/examples/pivot_apexcharts.html b/examples/pivot_apexcharts.html new file mode 100644 index 000000000..1c8e24fe9 --- /dev/null +++ b/examples/pivot_apexcharts.html @@ -0,0 +1,24 @@ + + + + + Pivot Chart Example + + + + + + + + + + +
+
+
+ + + + + \ No newline at end of file diff --git a/examples/pivot_apexcharts.js b/examples/pivot_apexcharts.js new file mode 100644 index 000000000..1d16747d4 --- /dev/null +++ b/examples/pivot_apexcharts.js @@ -0,0 +1,88 @@ +var json = { + "elements": [ + { + "type": "radiogroup", + "name": "question1", + "title": "Gender", + "choices": [ + "female", + "male" + ] + }, + { + "type": "dropdown", + "name": "question2", + "title": "Item kind", + "choices": [ + "Item 1", + "Item 2", + "Item 3" + ], + }, + { + "type": "text", + "inputType": "number", + "name": "question3", + "title": "Bill amount", + } + ] +}; +var data = [ + { question1: "male", question2: "Item 1", question3: 100 }, + { question1: "male", question2: "Item 1", question3: 200 }, + { question1: "male", question2: "Item 2", question3: 300 }, + { question1: "male", question2: "Item 3", question3: 400 }, + { question1: "female", question2: "Item 2", question3: 500 }, + { question1: "female", question2: "Item 2", question3: 600 }, + { question1: "female", question2: "Item 2", question3: 100 }, + { question1: "female", question2: "Item 3", question3: 200 }, + { question1: "female", question2: "Item 3", question3: 300 }, + { question1: "female", question2: "Item 3", question3: 300 }, + { question1: "female", question2: "Item 3", question3: 400 }, + { question1: "female", question2: "Item 3", question3: 150 }, + { question1: "female", question2: "Item 1", question3: 250 }, +]; + +var options = { + // allowDynamicLayout: false, + // allowDragDrop: false, + // allowHideQuestions: false, + // allowShowPercentages: true, + // showPercentages: true, + // showOnlyPercentages: true, + // useValuesAsLabels: false + // haveCommercialLicense: false, + // allowSortAnswers: true, + // answersOrder: "desc" + // allowHideEmptyAnswers: true, + // hideEmptyAnswers: true, + // allowTopNAnswers: true, + // showCorrectAnswers: true + // labelTruncateLength: 27, +}; + +var survey = new Survey.SurveyModel(json); + +var pivotChart = new SurveyAnalyticsApexcharts.PivotModel( + survey.getAllQuestions(), + data, + options +); +pivotChart.render(document.getElementById("pivotContainer")); + +var visPanel = new SurveyAnalyticsApexcharts.VisualizationPanel( + [ [ survey.getQuestionByName("question2"), survey.getQuestionByName("question1") ], [ survey.getQuestionByName("question1"), survey.getQuestionByName("question2") ] ], + data, + options +); +visPanel.showToolbar = true; +visPanel.render(document.getElementById("summaryContainer")); + +var pivot_survey = new Survey.SurveyModel(pivot_json); + +// var crossQuestion = new SurveyAnalyticsApexcharts.PivotModel( +// pivot_survey.getAllQuestions(), +// pivot_data, +// options +// ); +// crossQuestion.render(document.getElementById("groupContainer")); diff --git a/examples/poll-visualizer.html b/examples/poll-visualizer.html new file mode 100644 index 000000000..efdeea938 --- /dev/null +++ b/examples/poll-visualizer.html @@ -0,0 +1,61 @@ + + + + + Poll Visualizer Example + + + + + + + + + + + + +
+ + + + + \ No newline at end of file diff --git a/examples/poll-visualizer.js b/examples/poll-visualizer.js new file mode 100644 index 000000000..59c642cf1 --- /dev/null +++ b/examples/poll-visualizer.js @@ -0,0 +1,104 @@ +function PollVisualizer(question, data, options) { + // Step 1: Implement a rendering function + function renderContent (contentContainer, visualizer) { + visualizer.getAnswersData().then((vizData) => { + const polls = vizData.datasets; + const choices = vizData.labels; + const percentages = vizData.texts; + if (polls.length === 0 || polls[0].length === 0) { + const emptyResultsHtml = `

` + SurveyAnalytics.localization.getString("noResults") + `

`; + contentContainer.insertAdjacentHTML("beforeend", emptyResultsHtml); + return; + } + polls.forEach((poll, idx) => { + const tableNode = document.createElement("table"); + tableNode.classList.add("sa-poll-table"); + tableNode.style.backgroundColor = visualizer.backgroundColor; + poll.forEach((voteCount, index) => { + const textRow = + ` + ` + + choices[index] + " - " + percentages[idx][index] + "%" + " (" + voteCount + " votes)" + ` + + `; + const graphRow = + ` + +
+
+
+ + `; + tableNode.insertAdjacentHTML("beforeend", textRow); + tableNode.insertAdjacentHTML("beforeend", graphRow); + }); + contentContainer.appendChild(tableNode); + }); + }); + }; + // Step 2: Instantiate the visualizer + const visualizer = new SurveyAnalytics.SelectBase( + question, + data, + { renderContent: renderContent, dataProvider: options.dataProvider }, + "pollVisualizer" + ); + visualizer.answersOrder = "asc"; + visualizer.showPercentages = true; + return visualizer; +} + +SurveyAnalytics.VisualizationManager.registerVisualizer("radiogroup", PollVisualizer, 0); + +var json = { + "elements": [{ + "type": "radiogroup", + "name": "organization_type", + "title": "Which of the following best describes you or your organization?", + "showOtherItem": true, + "choices": [{ + "value": "ISV", + "text": "ISV (building commercial/shrink-wrapped software)" + }, { + "value": "Consulting", + "text": "Software consulting firm (providing development services to other organizations)" + }, { + "value": "Custom", + "text": "Custom software development (as a freelancer/contractor)" + }, { + "value": "In-house", + "text": "In-house software development" + }, { + "value": "Hobbyist", + "text": "Hobbyist (developing apps for personal use)" + }], + "colCount": 2 + }] +}; +var survey = new Survey.SurveyModel(json); + +var dataFromServer = [ + { organization_type: "In-house" }, + { organization_type: "other" }, + { organization_type: "Hobbyist" }, + { organization_type: "Hobbyist" }, + { organization_type: "Hobbyist" }, + { organization_type: "Consulting" }, + { organization_type: "In-house" }, + { organization_type: "Consulting" }, + { organization_type: "Hobbyist" }, + { organization_type: "Hobbyist" }, + { organization_type: "ISV" }, + { organization_type: "ISV" }, + { organization_type: "Custom" }, + { organization_type: "ISV" }, + { organization_type: "Custom" } +];; + +var vizPanel = new SurveyAnalytics.VisualizationPanel( + survey.getAllQuestions(), + dataFromServer, + { allowDynamicLayout: false, allowHideQuestions: false } +); + +vizPanel.render(document.getElementById("container")); diff --git a/examples/poll.js b/examples/poll.js index ab4ddfb45..522bd24fb 100644 --- a/examples/poll.js +++ b/examples/poll.js @@ -44,12 +44,11 @@ function PollVisualizer(question, data) { var texts = answersData.texts; var seriesLabels = answersData.seriesLabels; var hasSeries = seriesLabels.length > 1; - - var emptyTextNode = SurveyAnalytics.DocumentHelper.createElement("p", "", { - innerText: SurveyAnalytics.localization.getString("noResults"), - }); - + if (datasets.length === 0 || datasets[0].length === 0) { + var emptyTextNode = SurveyAnalytics.DocumentHelper.createElement("p", "", { + innerText: SurveyAnalytics.localization.getString("noResults"), + }); contentContainer.appendChild(emptyTextNode); return; } diff --git a/examples/ranking_apexcharts.html b/examples/ranking_apexcharts.html new file mode 100644 index 000000000..35b8fe89f --- /dev/null +++ b/examples/ranking_apexcharts.html @@ -0,0 +1,28 @@ + + + + + Ranking Example + + + + + + + + + + + + + + +
+ + + + \ No newline at end of file diff --git a/examples/ranking_apexcharts.js b/examples/ranking_apexcharts.js new file mode 100644 index 000000000..c560205ad --- /dev/null +++ b/examples/ranking_apexcharts.js @@ -0,0 +1,121 @@ +var surveyId = ""; +var accessKey = ""; + +var json = { + elements: [ + { + type: "ranking", + name: "smartphone-features", + title: + "Please rank the following smartphone features in order of importance:", + isRequired: true, + choices: [ + "Battery life", + "Screen size", + "Storage space", + "Camera quality", + "Durability", + "Processor power", + "Price", + ], + }, + ], +}; + +var data = [ + { + "smartphone-features": [ + "Price", + "Battery life", + "Screen size", + "Storage space", + "Camera quality", + "Durability", + "Processor power", + ], + }, + { + "smartphone-features": [ + "Battery life", + "Screen size", + "Storage space", + "Camera quality", + "Durability", + "Processor power", + "Price", + ], + }, + { + "smartphone-features": [ + "Battery life", + "Screen size", + "Storage space", + "Camera quality", + "Durability", + "Processor power", + "Price", + ], + }, +]; + +// var data = [ +// { +// "smartphone-features": [ +// "Battery life", +// "Screen size", +// "Storage space", +// "Camera quality", +// "Durability", +// "Processor power", +// "Price", +// ], +// }, +// { +// "smartphone-features": [ +// "Price", +// "Processor power", +// "Battery life", +// "Screen size", +// "Storage space", +// "Camera quality", +// "Durability", +// ], +// }, +// { +// "smartphone-features": [ +// "Durability", +// "Screen size", +// "Battery life", +// "Storage space", +// "Processor power", +// "Price", +// "Camera quality", +// ], +// }, +// ]; + +var survey = new Survey.SurveyModel(json); + +// SurveyAnalytics.PlotlySetup.onImageSaving.add(function ( +// selectBaseVisualizer, +// options +// ) { +// options.filename = "Exported " + selectBaseVisualizer.question.name; +// }); + +// SurveyAnalytics.PlotlySetup.onPlotCreating.add(function ( +// selectBaseVisualizer, +// options +// ) { +// options.config.modeBarButtonsToRemove.push("lasso2d"); +// }); + +var options = {}; + +var visPanel = new SurveyAnalyticsApexcharts.VisualizationPanel( + // [ survey.getQuestionByName("organization_type"), survey.getQuestionByName("backend_language") ], + survey.getAllQuestions(), + data +); +visPanel.showToolbar = true; +visPanel.render(document.getElementById("rankingContainer")); diff --git a/examples/rating_apexcharts.html b/examples/rating_apexcharts.html new file mode 100644 index 000000000..78633c085 --- /dev/null +++ b/examples/rating_apexcharts.html @@ -0,0 +1,20 @@ + + + + + Rating Question Example + + + + + + + + + + +
+ + + + \ No newline at end of file diff --git a/examples/rating_apexcharts.js b/examples/rating_apexcharts.js new file mode 100644 index 000000000..f95184d96 --- /dev/null +++ b/examples/rating_apexcharts.js @@ -0,0 +1,74 @@ +var json = { + "pages": [ + { + "name": "page1", + "elements": [ + { + type: "rating", + name: "score", + title: "How likely are you to recommend SurveyJS to a friend or colleague?", + rateMin: 1, + rateMax: 10, + minRateDescription: "Most unlikely", + maxRateDescription: "Most likely", + }, + { + "type": "rating", + "name": "question1", + title: "What item do you prefer?", + "autoGenerate": false, + "rateCount": 2, + "rateValues": [ + "Item 1", + "Item 2" + ] + } + ] + } + ] +}; +var data = [ + { question1: "Item 1", "score": 1 }, + { question1: "Item 1", "score": 2 }, + { question1: "Item 2", "score": 3 }, + { question1: "Item 2", "score": 4 }, + { question1: "Item 2", "score": 5 }, + { question1: "Item 2", "score": 6 }, + { question1: "Item 2", "score": 1 }, + { question1: "Item 1", "score": 2 }, + { question1: "Item 3", "score": 7 }, + { question1: "Item 1", "score": 9 }, + { question1: "Item 2", "score": 9 }, + { question1: "Item 1", "score": 1 }, + { question1: "Item 1", "score": 2 }, + { question1: "Item 1", "score": 10 }, + { question1: "Item 1", "score": 3 }, +]; + +var options = { + // allowDynamicLayout: false, + // allowDragDrop: false, + // allowHideQuestions: false, + // allowShowPercentages: true, + // showPercentages: true, + // showOnlyPercentages: true, + // useValuesAsLabels: false + // haveCommercialLicense: false, + // allowSortAnswers: true, + // answersOrder: "desc" + // allowHideEmptyAnswers: true, + // hideEmptyAnswers: true, + // allowTopNAnswers: true, + // showCorrectAnswers: true + // labelTruncateLength: 27, +}; + +var survey = new Survey.SurveyModel(json); + +var visPanel = new SurveyAnalyticsApexcharts.VisualizationPanel( + survey.getAllQuestions(), + data, + options +); +visPanel.showToolbar = true; +visPanel.render(document.getElementById("summaryContainer")); diff --git a/examples/summary.html b/examples/summary.html index d9ef5f6cb..e8146275e 100644 --- a/examples/summary.html +++ b/examples/summary.html @@ -22,6 +22,9 @@ } + + +

diff --git a/examples/summary.js b/examples/summary.js index a4e3a5f6a..eb9a9d900 100644 --- a/examples/summary.js +++ b/examples/summary.js @@ -77,5 +77,17 @@ var visPanel = new SurveyAnalytics.VisualizationPanel( data, options ); + +const checkbox = document.getElementById('toggle-checkbox'); +checkbox.addEventListener('change', () => { + if (checkbox.checked) { + visPanel.applyTheme(SurveyAnalytics.DefaultDark); + } else { + visPanel.applyTheme(SurveyAnalytics.Default); + } +}); + +// visPanel.applyTheme(SurveyAnalytics.DefaultDark); +// visPanel.applyTheme(SurveyAnalytics.Default); visPanel.showToolbar = true; visPanel.render(document.getElementById("summaryContainer")); diff --git a/examples/summary_apexcharts.html b/examples/summary_apexcharts.html new file mode 100644 index 000000000..472412187 --- /dev/null +++ b/examples/summary_apexcharts.html @@ -0,0 +1,32 @@ + + + + + Summary Example + + + + + + + + + + + + + + + + +

+
+ + + + + \ No newline at end of file diff --git a/examples/summary_apexcharts.js b/examples/summary_apexcharts.js new file mode 100644 index 000000000..9b76c2a02 --- /dev/null +++ b/examples/summary_apexcharts.js @@ -0,0 +1,92 @@ +var surveyId = ""; +var accessKey = ""; + +var survey = new Survey.SurveyModel(json); + +// var xhr = new XMLHttpRequest(); +// xhr.open( +// "GET", +// "http://surveyjs.io/api/MySurveys/getSurveyResults/" + +// surveyId + +// "?accessKey=" + +// accessKey +// ); +// xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded"); +// xhr.onload = function() { +// var result = xhr.response ? JSON.parse(xhr.response) : []; + +// // SurveyAnalytics.SelectBasePlotly.types = ["pie", "scatter"]; +// // SurveyAnalytics.VisualizerBase.customColors = [ +// // "F85A40", +// // "185A32", +// // "BC1CEC", +// // "DC4E75", +// // "747F4B", +// // "000000" +// // ]; + +// var visPanel = new SurveyAnalytics.VisualizationPanel( +// survey.getAllQuestions(), +// data +// ); +// visPanel.showToolbar = true; +// visPanel.render(document.getElementById("summaryContainer")); +// }; +// xhr.send(); + +// SurveyAnalytics.SelectBasePlotly.displayModeBar = false; + +// SurveyAnalytics.VisualizerBase.suppressVisualizerStubRendering = true; + +// SurveyAnalytics.VisualizationManager.registerVisualizer("rating", SurveyAnalytics.NpsVisualizer); + +// SurveyAnalytics.PlotlySetup.onImageSaving.add(function (selectBaseVisualizer, options) { +// options.filename = "Exported " + selectBaseVisualizer.question.name; +// }); + +// SurveyAnalytics.PlotlySetup.onPlotCreating.add(function(selectBaseVisualizer, options) { +// options.config.modeBarButtonsToRemove.push("lasso2d"); +// }); + +var options = { + // allowTransposeData: true, + // allowDynamicLayout: false, + // allowDragDrop: false, + // allowHideQuestions: false, + // allowShowPercentages: true, + // showPercentages: true, + // showOnlyPercentages: true, + // useValuesAsLabels: false + // haveCommercialLicense: false, + // allowSortAnswers: true, + // answersOrder: "desc" + // allowHideEmptyAnswers: true, + // hideEmptyAnswers: true, + // allowTopNAnswers: true, + // showCorrectAnswers: true + // labelTruncateLength: 27, + datePeriodFieldName: "timestamp", +}; + +// SurveyAnalytics.WordCloudAdapter.drawOutOfBound = false; +// SurveyAnalytics.WordCloudAdapter.shrinkToFit = true; +// SurveyAnalytics.WordCloudAdapter.weightFactor = 30; + +var visPanel = new SurveyAnalyticsApexcharts.VisualizationPanel( + // [ survey.getQuestionByName("organization_type"), survey.getQuestionByName("backend_language") ], + survey.getAllQuestions(), + data, + options +); + +const checkbox = document.getElementById('toggle-checkbox'); +checkbox.addEventListener('change', () => { + if (checkbox.checked) { + visPanel.applyTheme(SurveyAnalyticsApexcharts.DefaultDark); + } else { + visPanel.applyTheme(SurveyAnalyticsApexcharts.Default); + } +}); + +visPanel.showToolbar = true; +visPanel.render(document.getElementById("summaryContainer")); diff --git a/examples/summary_themed.html b/examples/summary_themed.html new file mode 100644 index 000000000..7eb4e148f --- /dev/null +++ b/examples/summary_themed.html @@ -0,0 +1,37 @@ + + + + + Summary Example + + + + + + + + + + + + + + + + + +

+
+ + + + + \ No newline at end of file diff --git a/examples/summary_themed.js b/examples/summary_themed.js new file mode 100644 index 000000000..02595e71e --- /dev/null +++ b/examples/summary_themed.js @@ -0,0 +1,63 @@ +var survey = new Survey.SurveyModel(json); + +var options = { + // allowTransposeData: true, + // allowDynamicLayout: false, + // allowDragDrop: false, + // allowHideQuestions: false, + // allowShowPercentages: true, + // showPercentages: true, + // showOnlyPercentages: true, + // useValuesAsLabels: false + // haveCommercialLicense: false, + // allowSortAnswers: true, + // answersOrder: "desc" + // allowHideEmptyAnswers: true, + // hideEmptyAnswers: true, + // allowTopNAnswers: true, + // showCorrectAnswers: true + // labelTruncateLength: 27, +}; + +SurveyAnalytics.VisualizerBase.customColors = [ + "#f3cec9", + "#e7a4b6", + "#cd7eaf", + "#a262a9", + "#6f4d96", + "#3d3b72", + "#182844", + "#6f4d96", + "#3d3b72", + "#182844", +]; + +var visPanel = new SurveyAnalytics.VisualizationPanel( + survey.getAllQuestions(), + data, + options +); + +// visPanel.applyTheme(SurveyAnalytics.DefaultDark); +// visPanel.applyTheme(SurveyAnalytics.Default); +const newTheme = {}; +Object.assign(newTheme, SurveyAnalytics.Default, { + cssVariables: { + "--sjs2-color-bg-basic-primary": "gray", + "--sjs2-color-utility-sheet": "gray", + "--sjs2-color-control-formbox-focused-bg": "darkgray", + } +}); +visPanel.applyTheme(newTheme); + +visPanel.showToolbar = true; +visPanel.render(document.getElementById("summaryContainer")); + +const checkbox = document.getElementById('toggle-checkbox'); +checkbox.addEventListener('change', () => { + if (checkbox.checked) { + visPanel.applyTheme(SurveyAnalytics.DefaultDark); + } else { + visPanel.applyTheme(SurveyAnalytics.Default); + } +}); \ No newline at end of file diff --git a/examples/summarytest.html b/examples/summarytest.html index a8f927775..bdd8ce1a8 100644 --- a/examples/summarytest.html +++ b/examples/summarytest.html @@ -18,7 +18,6 @@ -
diff --git a/examples/tabulator.html b/examples/tabulator.html index 548f893f2..e56187ced 100644 --- a/examples/tabulator.html +++ b/examples/tabulator.html @@ -18,6 +18,9 @@ + + +

diff --git a/index.html b/index.html index a97900c24..1a8dd16d6 100644 --- a/index.html +++ b/index.html @@ -18,6 +18,8 @@

You can check the following examples of SurveyJS Analytics:

  • Change Language
  • Chart from text
  • Histograms
  • +
  • NPS
  • +
  • Poll Visualizer
  • diff --git a/package.json b/package.json index 582f4fb42..3a0cb193c 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,7 @@ { "scripts": { "start": "webpack-dev-server --env buildType=dev", + "serve": "http-server --silent", "test": "jest", "test:dev": "jest --watch", "test:debug": "node --inspect-brk ./node_modules/jest/bin/jest.js --runInBand", @@ -11,14 +12,18 @@ "doc:update": "chmod +x ./docupdate_npm.sh && ./docupdate_npm.sh", "watch:dev": "concurrently \"webpack --env buildType=dev --env emitStyles\" \"rollup -c -w\" ", "build": "webpack --env buildType=dev --env emitNonSourceFiles --env emitStyles && webpack --env buildType=prod --env emitStyles && rollup -c && npm run build:types", - "build:types": "npm run build:types:core && npm run build:types:summary && npm run build:types:tabulator && npm run build:types:mongo", - "build:types:core": "tsc --p tsconfig.summary.core.json && echo \"export * from './survey-analytics.types/entries/summary.core';\" >> build/survey.analytics.core.d.ts", - "build:types:summary": "tsc --p tsconfig.summary.json && echo \"export * from './survey-analytics.types/entries/summary';\" >> build/survey.analytics.d.ts", - "build:types:tabulator": "tsc --p tsconfig.tabulator.json && echo \"export * from './survey-analytics-tabulator.types/entries/tabulator';\" >> build/survey.analytics.tabulator.d.ts", + "build:types": "npm run build:types:core && npm run build:types:summary && npm run build:types:tabulator && npm run build:types:apexcharts && npm run build:types:plotly && npm run build:types:mongo", + "build:types:core": "tsc --p tsconfig.types.summary.core.json && echo \"export * from './survey-analytics.types/entries/summary.core';\" >> build/survey.analytics.core.d.ts", + "build:types:summary": "tsc --p tsconfig.types.summary.json && echo \"export * from './survey-analytics.types/entries/summary';\" >> build/survey.analytics.d.ts", + "build:types:tabulator": "tsc --p tsconfig.types.tabulator.json && echo \"export * from './survey-analytics-tabulator.types/entries/tabulator';\" >> build/survey.analytics.tabulator.d.ts", + "build:types:apexcharts": "tsc --p tsconfig.types.apexcharts.json && echo \"export * from './survey-analytics-apexcharts.types/entries/apexcharts';\" >> build/survey.analytics.apexcharts.d.ts", + "build:types:plotly": "tsc --p tsconfig.types.plotly.json && echo \"export * from './survey-analytics-plotly.types/entries/plotly';\" >> build/survey.analytics.plotly.d.ts", "build:types:mongo": "tsc --p tsconfig.types.mongo.json && echo \"export * from './survey-analytics.types/entries/mongo';\" >> build/survey.analytics.mongo.d.ts", "lint": "eslint ./src --quiet", "pre-push-check": "npm run lint && npm run test", - "pwinst": "playwright install chromium" + "pwinst": "playwright install chromium", + "accessibility-tests": "playwright test --project a11y --ui", + "accessibility-tests:ci": "playwright test --project a11y --reporter dot --quiet" }, "version": "2.3.12", "name": "survey-analytics", @@ -47,7 +52,8 @@ "muuri": "^0.8.0", "plotly.js-dist-min": "^2.28.0", "survey-core": "latest", - "tabulator-tables": "^6.2.5" + "tabulator-tables": "^6.2.5", + "apexcharts": "^4.7.0" }, "devDependencies": { "@playwright/test": "1.53.1", @@ -58,8 +64,12 @@ "@types/jest": "^26.0.24", "@types/jquery": "3.3.29", "@types/node": "7.0.4", + "@types/minimatch": "5.1.2", "@typescript-eslint/eslint-plugin": "^4.33.0", "@typescript-eslint/parser": "^4.33.0", + "axe-core": "^4.8.2", + "axe-playwright": "^2.1.0", + "axe-testcafe": "^3.0.0", "concurrently": "^5.3.0", "css-loader": "^7.1.2", "eslint": "^7.32.0", @@ -98,6 +108,11 @@ "@types/plotly.js-dist-min": "^2.3.0", "@types/tabulator-tables": "^6.2.3" }, + "overrides": { + "axe-testcafe": { + "axe-core": "^4.8.2" + } + }, "husky": { "hooks": { "pre-push": "npm run pre-push-check" diff --git a/playwright.config.ts b/playwright.config.ts index 537470f37..ac4cda9fe 100644 --- a/playwright.config.ts +++ b/playwright.config.ts @@ -1,4 +1,5 @@ import { defineConfig, devices } from "@playwright/test"; +import { resolve } from "path"; /** * Read environment variables from file. @@ -31,7 +32,7 @@ export default defineConfig({ /* Collect trace when retrying the failed test. See https://playwright.dev/docs/trace-viewer */ trace: "on-first-retry", }, - snapshotPathTemplate: "{testDir}/{testFilePath}-snapshots/{arg}{ext}", + snapshotPathTemplate: `{testDir}/{testFilePath}-snapshots${process.env.SNAPSHOT_SUFFIX || ""}/{arg}{ext}`, /* Configure projects for major browsers */ projects: [ @@ -49,6 +50,10 @@ export default defineConfig({ name: "webkit", use: { ...devices["Desktop Safari"] }, }, + { + name: "a11y", + testDir: resolve(__dirname, "./accessibilityTests") + }, /* Test against mobile viewports. */ // { @@ -73,7 +78,7 @@ export default defineConfig({ /* Run your local dev server before starting the tests */ webServer: { - command: "npm run start", + command: "npm run serve", url: "http://localhost:8080", reuseExistingServer: !process.env.CI, }, diff --git a/rollup.config.js b/rollup.config.js index f7448db3b..a400e51ae 100644 --- a/rollup.config.js +++ b/rollup.config.js @@ -21,6 +21,8 @@ const input = { "survey.analytics.core": path.resolve(__dirname, "./src/entries/summary.core.ts"), "survey.analytics.mongo": path.resolve(__dirname, "./src/entries/mongo.ts"), "survey.analytics.tabulator": path.resolve(__dirname, "./src/entries/tabulator-es.ts"), + "survey.analytics.apexcharts": path.resolve(__dirname, "./src/entries/apexcharts.ts"), + "survey.analytics.plotly": path.resolve(__dirname, "./src/entries/plotly.ts"), }; module.exports = (options) => { options = options ?? {}; @@ -81,6 +83,7 @@ module.exports = (options) => { "survey-core", "plotly.js-dist-min", "tabulator-tables", + "apexcharts", "mongodb" ], output: [ diff --git a/src/_globals.scss b/src/_globals.scss index ca246586c..ae9b31db4 100644 --- a/src/_globals.scss +++ b/src/_globals.scss @@ -25,6 +25,6 @@ $form-element-height: 34px; $svg-color: var(--svg-color, rgba(#9f9f9f, 0.4)); $svg-hover-color: var(--svg-hover-color, #9f9f9f); -$font-family: var(--font-family, "Segoe UI", SegoeUI, Arial, sans-serif); +$font-family: var(--sjs2-typography-font-family-default, var(--font-family, "Open Sans", "Segoe UI", SegoeUI, Arial, sans-serif)); $font-family-secondary: var(--font-family-secondary, Raleway, Arial, sans-serif); $root-font-size: var(--root-font-size, 14px); \ No newline at end of file diff --git a/src/alternativeVizualizersWrapper.ts b/src/alternativeVizualizersWrapper.ts index 24c540fc2..10bf09dca 100644 --- a/src/alternativeVizualizersWrapper.ts +++ b/src/alternativeVizualizersWrapper.ts @@ -1,10 +1,11 @@ import { Question, ItemValue } from "survey-core"; -import { VisualizerBase } from "./visualizerBase"; +import { ICalculationResult, IChartAdapter, VisualizerBase } from "./visualizerBase"; import { localization } from "./localizationManager"; import { DocumentHelper } from "./utils/index"; import { VisualizationManager } from "./visualizationManager"; import { IVisualizerWithSelection } from "./selectBase"; import { Event } from "survey-core"; +import { IDashboardTheme } from "./theme"; export class AlternativeVisualizersWrapper extends VisualizerBase @@ -14,9 +15,7 @@ export class AlternativeVisualizersWrapper private updateVisualizerSelector() { if (!!this.visualizerSelector) { - this.visualizerSelector.getElementsByTagName( - "select" - )[0].value = this.visualizer.type; + (this.visualizerSelector as any).setValue(this.visualizer.type); } } @@ -47,7 +46,7 @@ export class AlternativeVisualizersWrapper if(this.options.allowChangeVisualizerType !== false) { this.registerToolbarItem("changeVisualizer", () => - this.visualizerSelector = DocumentHelper.createSelector( + this.visualizerSelector = DocumentHelper.createDropdown( this.visualizers.map((visualizer) => { return { value: visualizer.type, @@ -55,8 +54,8 @@ export class AlternativeVisualizersWrapper }; }), (option: any) => this.visualizer.type === option.value, - (e: any) => this.setVisualizer(e.target.value) - ), 0 + (e: any) => this.setVisualizer(e) + ), "dropdown", 0 ); } @@ -66,6 +65,10 @@ export class AlternativeVisualizersWrapper } protected visualizerContainer: HTMLElement; + + protected onDataChanged(): void { + } + public get hasFooter(): boolean { return false; } @@ -74,6 +77,10 @@ export class AlternativeVisualizersWrapper return this.visualizers; } + public getChartAdapter(): IChartAdapter { + return this.visualizer.getChartAdapter(); + } + private visualizersWithSelection: Array = []; private selectedItem: ItemValue; private visualizer: VisualizerBase; @@ -156,7 +163,7 @@ export class AlternativeVisualizersWrapper protected renderContent(container: HTMLElement): void { this.visualizerContainer = container; - this.visualizer.render(this.visualizerContainer); + this.visualizer.render(this.visualizerContainer, false); } protected setBackgroundColorCore(color: string) { @@ -215,10 +222,17 @@ export class AlternativeVisualizersWrapper return this.visualizer.getLabels(); } - public getCalculatedValues(): Promise> { + public getCalculatedValues(): Promise { return this.visualizer.getCalculatedValues(); } + protected onThemeChanged(): void { + super.onThemeChanged(); + this.visualizers.forEach(v => { + v.theme = this.theme; + }); + } + destroy() { this.visualizers.forEach((visualizer) => { visualizer.onAfterRender.remove(this.onAfterVisualizerRenderCallback); diff --git a/src/analytics-localization/english.ts b/src/analytics-localization/english.ts index 0e3c3097a..0b2721ca3 100644 --- a/src/analytics-localization/english.ts +++ b/src/analytics-localization/english.ts @@ -5,8 +5,10 @@ export var englishStrings = { groupButton: "Group By Me", ungroupButton: "Ungroup By Me", selectButton: "Select Me", + columnReorder: "Column reorder", hideColumn: "Hide column", showColumn: "Show column", + columns: "Columns", makePrivateColumn: "Make column private", makePublicColumn: "Make column public", moveToDetail: "Move to Detail", @@ -15,6 +17,7 @@ export var englishStrings = { removeRows: "Remove rows", showLabel: "Show", entriesLabel: "entries", + entriesOnPageLabel: "Entries on Page:", visualizer_text: "Texts in table", visualizer_wordcloud: "Wordcloud", visualizer_histogram: "Histogram", @@ -41,18 +44,21 @@ export var englishStrings = { changeLocale: "Change Locale", clearButton: "Clear", addElement: "Choose question to show...", + allQuestions: "All questions", defaultOrder: "Default Order", ascOrder: "Ascending", descOrder: "Descending", showMinorColumns: "Show minor columns", actionsColumn: "Actions", otherCommentTitle: "Other items and comments", - showPercentages: "Show percentages", + showPercentages: "Show %", hidePercentages: "Hide percentages", + exportAs: "Export As...", pdfDownloadCaption: "PDF", xlsxDownloadCaption: "Excel", csvDownloadCaption: "CSV", saveDiagramAsPNG: "Download plot as a PNG file", + answersText: "answer(s)", hideEmptyAnswers: "Hide empty answers", showEmptyAnswers: "Show empty answers", "topNValueText-1": "All answers", diff --git a/src/apexcharts/chart-adapter.ts b/src/apexcharts/chart-adapter.ts new file mode 100644 index 000000000..cfe9e8baf --- /dev/null +++ b/src/apexcharts/chart-adapter.ts @@ -0,0 +1,177 @@ +import ApexCharts from "apexcharts"; +import { ItemValue } from "survey-core"; +import { SelectBase } from "../selectBase"; +import { localization } from "../localizationManager"; +import { ApexChartsOptions, ApexChartsSetup } from "./setup"; +import { VisualizerBase } from "../visualizerBase"; +import { removeUndefinedProperties } from "../utils/utils"; + +export const chartTypes = { + "boolean": ["pie", "doughnut", "bar"], + "number": ["gauge", "bullet"], + "selectBase": ["bar", "vbar", "pie", "doughnut"], + "histogram": ["vbar", "bar"], + "matrix": ["bar", "stackedbar", "pie", "doughnut"], + "matrixDropdownGrouped": ["stackedbar", "bar", "pie", "doughnut"], + "pivot": ["vbar", "bar", "line", "stackedbar", "pie", "doughnut"], // ["vbar", "bar"]; + "ranking": ["bar", "vbar", "pie", "doughnut", "radar"], +}; + +export class ApexChartsAdapter { + private _chart: ApexCharts = undefined; + private _pieCharts: ApexCharts[] = undefined; + + private updatePieCharts(options: any, chartOptions: ApexChartsOptions, chartNode: HTMLElement): void { + if (this._pieCharts) { + this._pieCharts.forEach((chart) => chart.updateOptions(options)); + } else { + chartNode.style.cssText = "display: grid; grid-template-columns: repeat(2, 1fr);"; + this._pieCharts = chartOptions.series.map((s, i) => { + const chartDiv = document.createElement("div"); + chartDiv.id = "sa-chart" + i; + chartNode.appendChild(chartDiv); + + const _options = Object.assign({}, options, { + series: s.series, + labels: s.labels + }); + _options.title.text = s.title; + + removeUndefinedProperties(_options); + const chart = new ApexCharts(chartDiv, _options); + return chart; + }); + this._pieCharts.forEach((chart) => chart.render()); + } + } + + constructor(protected model: SelectBase | VisualizerBase) { } + + protected patchConfigParameters( + chartNode: object, + options: object + ) { } + + public get chart() { + return this._chart; + } + + getChartTypes(): string[] { + const visualizerType = this.model.type; + const chartCtypes = chartTypes[visualizerType]; + return chartCtypes || []; + } + + public async create(chartNode: HTMLElement): Promise { + const chartOptions = await this.update(chartNode); + const currentCharts = this._pieCharts || [this._chart]; + + if(this.model instanceof SelectBase) { + // Handle chart clicks + const _model = this.model as SelectBase; + } + + return currentCharts; + } + + public async update(chartNode: HTMLElement): Promise { + const _chartType = (this.model as any).chartType; + const answersData = await this.model.getAnswersData(); + var chartOptions = ApexChartsSetup.setup(_chartType, this.model, answersData as any); + + if (this.model instanceof SelectBase && this.model.supportSelection) { + const _model = this.model as SelectBase; + chartOptions.chart.events = { + dataPointMouseEnter: function () { chartNode.style.cursor = "pointer"; }, + dataPointMouseLeave: function () { chartNode.style.cursor = ""; }, + dataPointSelection: function(event, chartContext, opts) { + if (opts.dataPointIndex !== undefined && opts.seriesIndex !== undefined) { + let itemText = ""; + if (!chartOptions.hasSeries) { + itemText = config.labels[opts.dataPointIndex]; + const item: ItemValue = _model.getSelectedItemByText(itemText); + _model.setSelection(item); + } else { + itemText = config.series[opts.seriesIndex].name; + const propertyLabel = config.labels[opts.dataPointIndex]; + + const seriesValues = _model.getSeriesValues(); + const seriesLabels = _model.getSeriesLabels(); + const propertyValue = seriesValues[seriesLabels.indexOf(propertyLabel)]; + const selectedItem: ItemValue = _model.getSelectedItemByText(itemText); + const item = new ItemValue({ [propertyValue]: selectedItem.value }, propertyLabel + ": " + selectedItem.text); + _model.setSelection(item); + } + } + + // The last parameter opts contains additional information like `seriesIndex` and `dataPointIndex` for cartesian charts + /*if (data.points.length > 0) { + let itemText = ""; + if (!chartOptions.hasSeries) { + itemText = Array.isArray(data.points[0].customdata) + ? data.points[0].customdata[0] + : data.points[0].customdata; + const item: ItemValue = _model.getSelectedItemByText(itemText); + _model.setSelection(item); + } else { + itemText = data.points[0].data.name; + const propertyLabel = data.points[0].label; + // const seriesValues = this.model.getSeriesValues(); + // const seriesLabels = this.model.getSeriesLabels(); + // const propertyValue = seriesValues[seriesLabels.indexOf(propertyLabel)]; + // const selectedItem: ItemValue = _model.getSelectedItemByText(itemText); + // const item = new ItemValue({ [propertyValue]: selectedItem.value }, propertyLabel + ": " + selectedItem.text); + // _model.setSelection(item); + } + }*/ + } + }; + } + + let config: any = { + chart: { + ...chartOptions.chart, + locales: [{ + name: localization.currentLocale, + }], + defaultLocale: localization.currentLocale + }, + ...chartOptions + }; + + this.patchConfigParameters(chartNode, config); + + let options = { + ...config + }; + ApexChartsSetup.onChartCreating.fire(this.model, options); + + if((_chartType=== "pie" || _chartType === "doughnut") && chartOptions.series.length > 0 && typeof chartOptions.series[0] !== "number") { + this.updatePieCharts(options, chartOptions, chartNode); + } else { + const availableUpdateOptions = this._chart && !!this._chart["el"] && this._chart["el"].getRootNode() === document; + if (availableUpdateOptions) { + await this._chart.updateOptions({ series: options.series }); + } else { + removeUndefinedProperties(options); + this._chart = new ApexCharts(chartNode, options); + await this._chart.render(); + } + } + + return chartOptions; + } + + public destroy(node: HTMLElement): void { + if (this._chart) { + this._chart.destroy(); + this._chart = undefined; + } + if (this._pieCharts) { + this._pieCharts.forEach(ch => ch.destroy()); + this._pieCharts = undefined; + } + } +} + +VisualizerBase.chartAdapterType = ApexChartsAdapter; \ No newline at end of file diff --git a/src/apexcharts/index.ts b/src/apexcharts/index.ts new file mode 100644 index 000000000..705cac8b8 --- /dev/null +++ b/src/apexcharts/index.ts @@ -0,0 +1,2 @@ +export * from "./setup"; +export * from "./chart-adapter"; \ No newline at end of file diff --git a/src/apexcharts/setup.ts b/src/apexcharts/setup.ts new file mode 100644 index 000000000..52dd5ca48 --- /dev/null +++ b/src/apexcharts/setup.ts @@ -0,0 +1,1163 @@ +import { Event } from "survey-core"; +import { SelectBase } from "../selectBase"; +import { IAnswersData, VisualizerBase } from "../visualizerBase"; +import { DataHelper } from "../utils"; +import { NumberModel } from "../number"; +import { DashboardTheme } from "../theme"; +import { reverseAll } from "../utils/utils"; +import { localization } from "../localizationManager"; + +import "./styles.scss"; +export interface ApexChartsOptions { + series: Array; + chart: any; + labels: Array; + colors: Array; + plotOptions: any; + dataLabels?: any; + legend?: any; + tooltip?: any; + hasSeries?: boolean; + xaxis?: any; + yaxis?: any; + grid?: any; + title?: any; + responsive?: Array; +} + +export class ApexChartsSetup { + public static imageExportFormat = "png"; + + static defaultChartHeight = 450; + static defaultBarGap = DashboardTheme.barGap; + + static defaultToolbarConfig = { + show: true, + tools: { + download: true, + selection: true, + zoom: true, + zoomin: true, + zoomout: true, + pan: true, + reset: true + } + }; + + static defaultDataLabelsConfig(theme: DashboardTheme) { + const insideLabelFont = theme.insideLabelFont; + return { + enabled: true, + style: { + colors: [insideLabelFont.color], + fontSize: insideLabelFont.size, + fontFamily: insideLabelFont.family, + fontWeight: insideLabelFont.weight, + } + }; + } + + static defaultTooltipConfig(theme: DashboardTheme) { + const font = theme.tooltipFont; + + return { + enabled: true, + fillSeriesColor: false, + style: { + fontSize: font.size, + fontFamily: font.family, + }, + marker: { + show: false, + }, + x: { + formatter: () => "", + }, + y: { + formatter: function(val: number) { + return val.toString(); + }, + title: { + formatter: () => "", + }, + } + }; + } + + static defaultLegendConfig(theme: DashboardTheme) { + const font = theme.legendLabelFont; + return { + position: "right", + horizontalAlign: "left", + verticalAlign: "top", + fontSize: font.size, + fontFamily: font.family, + fontWeight: font.weight, + labels: { + colors: font.color + }, + markers: { + size: 10, + strokeWidth: 1, + // customHTML: function() { + // return ''; + // } + }, + }; + } + + static defaultAxisZerolineConfig(theme: DashboardTheme) { + return { + show: false, + color: theme.axisGridColor, + }; + } + + static defaultGridConfig(theme: DashboardTheme) { + return { + borderColor: theme.axisGridColor, + strokeDashArray: 4, + position: "back", + xaxis: { + lines: { + show: false, + } + }, + yaxis: { + lines: { + show: false, + } + } + }; + } + + static defaultAxisLabelFont(theme: DashboardTheme) { + const font = theme.axisLabelFont; + return { + colors: font.color, + fontSize: font.size, + fontFamily: font.family, + fontWeight: font.weight, + }; + } + + static defaultAxisLabelConfig(theme: DashboardTheme) { + return { + labels: { + style: { + ...ApexChartsSetup.defaultAxisLabelFont(theme) + }, + } + }; + } + + static defaultGaugeValueFont(theme: DashboardTheme) { + const font = theme.gaugeValueFont; + return { + colors: font.color, + fontSize: font.size, + fontFamily: font.family, + fontWeight: font.weight, + }; + } + + static defaultGaugeTickFont(theme: DashboardTheme) { + const font = theme.gaugeTickFont; + return { + colors: font.color, + fontSize: font.size, + fontFamily: font.family, + fontWeight: font.weight, + }; + } + + static defaultStrokeConfig = { + width: 2, + curve: "smooth" + }; + + static defaultFillConfig = { + type: "solid", + opacity: 0.8 + }; + + static defaultResponsive = { + breakpoint: 600, + options: { + legend: { + position: "bottom" + } + } + }; + + /** + * Fires when end user clicks on the 'save as image' button. + */ + public static onImageSaving = new Event< + (sender: VisualizerBase, options: any) => any, + VisualizerBase, + any + >(); + + /** + * Fires before chart will be created. User can change series, chart options and config of the chart. + * Options is an object with the following fields: series, chart, xaxis, yaxis, labels, colors, plotOptions, dataLabels, legend, tooltip, grid and hasSeries. + */ + public static onChartCreating = new Event< + (sender: VisualizerBase, options: any) => any, + VisualizerBase, + any + >(); + + static dataListFormatter(model: SelectBase, text: string, value: string): string { + if (model.showPercentages) { + if (model.showOnlyPercentages) { + return text + "%"; + } else { + return value + " (" + text + "%)"; + } + } + return value; + } + + static setups: { [type: string]: (model: VisualizerBase, answersData: IAnswersData) => ApexChartsOptions } = { + bar: ApexChartsSetup.setupBar, + vbar: ApexChartsSetup.setupVBar, + line: ApexChartsSetup.setupLine, + stackedbar: ApexChartsSetup.setupStackedBar, + doughnut: ApexChartsSetup.setupPie, + pie: ApexChartsSetup.setupPie, + scatter: ApexChartsSetup.setupScatter, + gauge: ApexChartsSetup.setupGauge, + bullet: ApexChartsSetup.setupBullet, + radar: ApexChartsSetup.setupRadar, + }; + + static setup(charType: string, model: VisualizerBase, answersData: IAnswersData): ApexChartsOptions { + return this.setups[charType](model, answersData); + } + + static setupPie(model: SelectBase, answersData: IAnswersData): ApexChartsOptions { + let { + datasets, + labels, + colors, + texts, + seriesLabels, + } = answersData; + + const hasSeries = seriesLabels.length > 1 || model.dataType === "matrix"; + + // Prepare data series + let series: Array = []; + let chartCount = 1; + + if (hasSeries) { + // For matrix questions or multiple series + datasets.forEach((dataset: Array, index: number) => { + const isNotEmpty = dataset.some((value: number) => value != 0); + if(isNotEmpty) { + chartCount += 1; + series.push({ + series: dataset, + labels: labels, + title: seriesLabels[index] + }); + } + }); + } else { + // For simple questions + series = datasets[0]; + } + + const diameter = labels.length < 10 ? labels.length * 50 + 100 : 550; + + // Chart settings + const chart: any = { + type: model.chartType === "doughnut" ? "donut" : "pie", + height: diameter, + toolbar: { ...ApexChartsSetup.defaultToolbarConfig }, + background: "transparent" + }; + + // Data label settings + const dataLabels: any = { + ...ApexChartsSetup.defaultDataLabelsConfig(model.theme), + formatter: function(val: number, opts: any) { + const name = opts.w.globals.labels[opts.seriesIndex]; + const text = name.length > 15 ? name.substring(0, 15) + "..." : name; + return [text, val.toFixed(model.percentagePrecision) + "%"]; + }, + }; + + // Chart options settings + const plotOptions: any = { + pie: { + donut: { + size: model.chartType === "doughnut" ? "40%" : "0%", + }, + customScale: 1, + offsetX: 0, + offsetY: 0, + startAngle: 0, + endAngle: 360, + expandOnClick: true, + dataLabels: { + offset: model.chartType === "doughnut" ? -10 : -25, + } + } + }; + + // Tooltip settings + const tooltip: any = ApexChartsSetup.defaultTooltipConfig(model.theme); + tooltip.y.title.formatter = (seriesName, opts: any) => { + const val = opts.w.globals.seriesPercent[opts.seriesIndex][0]; + return [seriesName, val.toFixed(model.percentagePrecision) + "%"]; + }; + + const legend= { + show: false, + }; + + const options: ApexChartsOptions = { + series, + chart, + labels: hasSeries ? seriesLabels : labels, + colors, + plotOptions, + dataLabels, + legend, + responsive: [{ ...ApexChartsSetup.defaultResponsive }], + tooltip, + hasSeries + }; + + if (hasSeries) { + options.title = { + align: "center", + style: { + ...ApexChartsSetup.defaultAxisLabelFont(model.theme), + }, + }; + } + + return options; + } + + static setupBar(model: SelectBase, answersData: IAnswersData): ApexChartsOptions { + let { + datasets, + labels, + colors, + texts, + seriesLabels, + } = answersData; + + const hasSeries = seriesLabels.length > 1 || model.dataType === "matrix"; + const isHistogram = model.type === "histogram"; + + const reversedAnswersData = reverseAll(labels, seriesLabels, colors, hasSeries, texts, datasets); + labels = reversedAnswersData.labels; + datasets = reversedAnswersData.datasets; + + // Prepare data series + let series: Array = []; + + if (hasSeries) { + // For matrix questions or multiple series + datasets.forEach((dataset: Array, index: number) => { + series.push({ + name: seriesLabels[index], + data: dataset + }); + }); + } else { + // For simple questions + series.push({ + name: "Values", + data: datasets[0] + }); + } + + let lineHeight = 30; + let margin = 35; + let height = (labels.length) * lineHeight + 2 * margin; + if(hasSeries) { + height = (labels.length * seriesLabels.length) * lineHeight + 2 * margin; + } + + // Chart settings + const chart: any = { + type: "bar", + height: height, + toolbar: { ...ApexChartsSetup.defaultToolbarConfig }, + background: "transparent" + }; + + // Axis settings + const xaxis: any = { + ...ApexChartsSetup.defaultAxisLabelConfig(model.theme), + categories: labels, + axisBorder: { + show: false, + }, + }; + + const yaxis: any = { + ...ApexChartsSetup.defaultAxisLabelConfig(model.theme), + axisBorder: { ...ApexChartsSetup.defaultAxisZerolineConfig(model.theme) }, + }; + + const grid = { + ...ApexChartsSetup.defaultGridConfig(model.theme), + xaxis: { + lines: { + show: true + } + }, + }; + + // Legend settings + const legend: any = { + ...ApexChartsSetup.defaultLegendConfig(model.theme), + show: hasSeries, + }; + + // Data label settings + const dataLabels: any = { + ...ApexChartsSetup.defaultDataLabelsConfig(model.theme), + formatter: function(val, opts) { + return ApexChartsSetup.dataListFormatter(model, texts[opts.seriesIndex][opts.dataPointIndex], val); + }, + }; + + // Chart options settings + const plotOptions: any = { + bar: { + horizontal: true, + distributed: !isHistogram && !hasSeries, + barHeight: isHistogram ? "100%": (1 - ApexChartsSetup.defaultBarGap) * 100 + "%", + } + }; + + // Tooltip settings + const tooltip: any = ApexChartsSetup.defaultTooltipConfig(model.theme); + + // RTL language handling + if (["ar", "fa"].indexOf(localization.currentLocale) !== -1) { + chart.direction = "rtl"; + } + + return { + series, + chart, + labels, + colors, + plotOptions, + dataLabels, + legend, + responsive: [{ ...ApexChartsSetup.defaultResponsive }], + tooltip, + hasSeries, + grid, + xaxis, + yaxis + }; + } + + static setupVBar(model: SelectBase, answersData: IAnswersData): ApexChartsOptions { + let { + datasets, + labels, + colors, + texts, + seriesLabels, + } = answersData; + + const hasSeries = seriesLabels.length > 1 || model.dataType === "matrix"; + const isHistogram = model.type === "histogram"; + + if (!isHistogram && model.type !== "pivot") { + ({ labels, seriesLabels, colors, texts, datasets } = reverseAll(labels, seriesLabels, colors, hasSeries, texts, datasets)); + } + + // Prepare data series + let series: Array = []; + + if (hasSeries) { + // For matrix questions or multiple series + datasets.forEach((dataset: Array, index: number) => { + series.push({ + name: seriesLabels[index], + data: dataset + }); + }); + } else { + // For simple questions + series.push({ + name: "Values", + data: datasets[0] + }); + } + + // Chart settings + const chart: any = { + type: "bar", + height: ApexChartsSetup.defaultChartHeight, + toolbar: { ...ApexChartsSetup.defaultToolbarConfig }, + background: "transparent" + }; + + // Axis settings + const xaxis: any = { + ...ApexChartsSetup.defaultAxisLabelConfig(model.theme), + categories: labels, + axisBorder: { ...ApexChartsSetup.defaultAxisZerolineConfig(model.theme) }, + }; + + const yaxis: any = { + ...ApexChartsSetup.defaultAxisLabelConfig(model.theme) + }; + + const grid = { + ...ApexChartsSetup.defaultGridConfig(model.theme), + yaxis: { + lines: { + show: true + } + } + }; + + // Legend settings + const legend: any = { + ...ApexChartsSetup.defaultLegendConfig(model.theme), + show: hasSeries, + }; + + // Data label settings + const dataLabels: any = { + ...ApexChartsSetup.defaultDataLabelsConfig(model.theme), + formatter: function(val, opts) { + return ApexChartsSetup.dataListFormatter(model, texts[opts.seriesIndex][opts.dataPointIndex], val); + } + }; + + // Chart options settings + const plotOptions: any = { + bar: { + horizontal: false, + distributed: !isHistogram && !hasSeries, + columnWidth: isHistogram ? "100%": (1 - ApexChartsSetup.defaultBarGap) * 100 + "%", + } + }; + + // Tooltip settings + const tooltip: any = ApexChartsSetup.defaultTooltipConfig(model.theme); + + // RTL language handling + if (["ar", "fa"].indexOf(localization.currentLocale) !== -1) { + chart.direction = "rtl"; + } + + return { + series, + chart, + labels, + colors, + plotOptions, + dataLabels, + legend, + responsive: [{ ...ApexChartsSetup.defaultResponsive }], + tooltip, + hasSeries, + grid, + xaxis, + yaxis + }; + } + + static setupLine(model: SelectBase, answersData: IAnswersData): ApexChartsOptions { + let { + datasets, + labels, + colors, + texts, + seriesLabels, + } = answersData; + + const hasSeries = seriesLabels.length > 1 || model.dataType === "matrix"; + + // Prepare data series + let series: Array = []; + + if (hasSeries) { + // For matrix questions or multiple series + datasets.forEach((dataset: Array, index: number) => { + series.push({ + name: seriesLabels[index], + data: dataset + }); + }); + } else { + // For simple questions + series.push({ + name: "Values", + data: datasets[0] + }); + } + + // Chart settings + const chart: any = { + type: "line", + height: ApexChartsSetup.defaultChartHeight, + toolbar: { ...ApexChartsSetup.defaultToolbarConfig }, + background: "transparent" + }; + + // Axis settings + const xaxis: any = { + axisBorder: { ...ApexChartsSetup.defaultAxisZerolineConfig(model.theme) }, + categories: labels, + labels: { + style: { + ...ApexChartsSetup.defaultAxisLabelFont(model.theme) + } + } + }; + + const yaxis: any = { + ...ApexChartsSetup.defaultAxisLabelConfig(model.theme) + }; + + // Legend settings + const legend: any = { + ...ApexChartsSetup.defaultLegendConfig(model.theme), + show: hasSeries, + }; + + // Data label settings + const dataLabels: any = { + ...ApexChartsSetup.defaultDataLabelsConfig(model.theme), + }; + + // Chart options settings + const plotOptions: any = { + line: { + curve: "smooth" + } + }; + + // Tooltip settings + const tooltip: any = ApexChartsSetup.defaultTooltipConfig(model.theme); + + // RTL language handling + if (["ar", "fa"].indexOf(localization.currentLocale) !== -1) { + chart.direction = "rtl"; + } + + return { + series, + chart, + labels, + colors, + plotOptions, + dataLabels, + legend, + responsive: [{ ...ApexChartsSetup.defaultResponsive }], + tooltip, + hasSeries, + xaxis, + yaxis + }; + } + + static setupStackedBar(model: SelectBase, answersData: IAnswersData): ApexChartsOptions { + let { + datasets, + labels, + colors, + texts, + seriesLabels, + } = answersData; + + const hasSeries = seriesLabels.length > 1 || model.dataType === "matrix"; + + const reversedAnswersData = reverseAll(labels, seriesLabels, colors, hasSeries, texts, datasets); + labels = reversedAnswersData.labels; + datasets = reversedAnswersData.datasets; + + // Prepare data series + let series: Array = []; + + if (hasSeries) { + // For matrix questions or multiple series + datasets.forEach((dataset: Array, index: number) => { + series.push({ + name: seriesLabels[index], + data: dataset + }); + }); + } else { + // For simple questions + series.push({ + name: "Values", + data: datasets[0] + }); + } + + let lineHeight = 30; + let margin = 35; + let height = labels.length * lineHeight + 2 * margin; + + // Chart settings + const chart: any = { + type: "bar", + stacked: true, + height: height, + toolbar: { ...ApexChartsSetup.defaultToolbarConfig }, + background: "transparent" + }; + + // Axis settings + const xaxis: any = { + ...ApexChartsSetup.defaultAxisLabelConfig(model.theme), + categories: labels, + axisBorder: { ...ApexChartsSetup.defaultAxisZerolineConfig(model.theme) }, + }; + + const yaxis: any = { + ...ApexChartsSetup.defaultAxisLabelConfig(model.theme) + }; + + const grid = { + ...ApexChartsSetup.defaultGridConfig(model.theme), + xaxis: { + lines: { + show: true + } + }, + }; + + // Legend settings + const legend: any = { + ...ApexChartsSetup.defaultLegendConfig(model.theme), + show: hasSeries, + }; + + // Data label settings + const dataLabels: any = { + ...ApexChartsSetup.defaultDataLabelsConfig(model.theme), + }; + + // Chart options settings + const plotOptions: any = { + bar: { + horizontal: true, + barHeight: (1 - ApexChartsSetup.defaultBarGap) * 100 + "%", + } + }; + + // Tooltip settings + const tooltip: any = ApexChartsSetup.defaultTooltipConfig(model.theme); + + // RTL language handling + if (["ar", "fa"].indexOf(localization.currentLocale) !== -1) { + chart.direction = "rtl"; + } + + return { + series, + chart, + labels, + colors, + plotOptions, + dataLabels, + legend, + responsive: [{ ...ApexChartsSetup.defaultResponsive }], + tooltip, + hasSeries, + grid, + xaxis, + yaxis + }; + } + + static setupScatter(model: SelectBase, answersData: IAnswersData): ApexChartsOptions { + let { + datasets, + labels, + colors, + texts, + seriesLabels, + } = answersData; + + const hasSeries = seriesLabels.length > 1 || model.dataType === "matrix"; + + // Prepare data series + let series: Array = []; + + if (hasSeries) { + // For matrix questions or multiple series + datasets.forEach((dataset: Array, index: number) => { + const scatterData = dataset.map((value: number, valueIndex: number) => ({ + x: valueIndex, + y: value + })); + series.push({ + name: seriesLabels[index], + data: scatterData + }); + }); + } else { + // For simple questions + const scatterData = datasets[0].map((value: number, index: number) => ({ + x: index, + y: value + })); + series.push({ + name: "Values", + data: scatterData + }); + } + + // Chart settings + const chart: any = { + type: "scatter", + height: ApexChartsSetup.defaultChartHeight, + toolbar: { ...ApexChartsSetup.defaultToolbarConfig }, + background: "transparent" + }; + + // Axis settings + const xaxis: any = { + type: "numeric", + axisBorder: { ...ApexChartsSetup.defaultAxisZerolineConfig(model.theme) }, + labels: { + style: { + ...ApexChartsSetup.defaultAxisLabelFont(model.theme) + } + } + }; + + const yaxis: any = { + ...ApexChartsSetup.defaultAxisLabelConfig(model.theme) + }; + + const grid = { + ...ApexChartsSetup.defaultGridConfig(model.theme), + xaxis: { + lines: { + show: true + } + }, + }; + + // Legend settings + const legend: any = { + ...ApexChartsSetup.defaultLegendConfig(model.theme), + show: hasSeries, + }; + + // Data label settings + const dataLabels: any = { + enabled: false + }; + + // Chart options settings + const plotOptions: any = { + scatter: { + size: 6 + } + }; + + // Tooltip settings + const tooltip: any = { + ...ApexChartsSetup.defaultTooltipConfig(model.theme), + custom: function({ series, seriesIndex, dataPointIndex, w }: any) { + const value = series[seriesIndex][dataPointIndex]; + const label = hasSeries ? seriesLabels[dataPointIndex] : labels[dataPointIndex]; + return `
    + ${label}: ${value.y} +
    `; + } + }; + + // RTL language handling + if (["ar", "fa"].indexOf(localization.currentLocale) !== -1) { + chart.direction = "rtl"; + } + + return { + series, + chart, + labels, + colors, + plotOptions, + dataLabels, + legend, + responsive: [{ ...ApexChartsSetup.defaultResponsive }], + tooltip, + hasSeries, + grid, + xaxis, + yaxis + }; + } + + static setupGauge(model: NumberModel, answersData: IAnswersData): ApexChartsOptions { + let value = answersData.datasets[0][answersData.values.indexOf(model.displayValueName || "value")]; + let minValue = answersData.datasets[0][answersData.values.indexOf("min")] || 0; + let maxValue = answersData.datasets[0][answersData.values.indexOf("max")] || value * 1.25; + + if (model.dataType === "rating") { + const rateValues = model.question.visibleRateValues; + maxValue = rateValues[rateValues.length - 1].value; + minValue = rateValues[0].value; + } + + if (NumberModel.showAsPercentage) { + value = DataHelper.toPercentage(value, maxValue); + minValue = DataHelper.toPercentage(minValue, maxValue); + maxValue = DataHelper.toPercentage(maxValue, maxValue); + } + + const chart= { + type: "radialBar", + height: ApexChartsSetup.defaultChartHeight, + background: "transparent", + toolbar: { + show: false + } + }; + + const plotOptions = { + radialBar: { + startAngle: -90, + endAngle: 90, + track: { + background: model.theme.gaugeBackground, + strokeWidth: "97%", + }, + dataLabels: { + name: { + show: false, + }, + value: { + ...ApexChartsSetup.defaultGaugeValueFont(model.theme), + show: true, + offsetY: -10, + formatter: function (val) { + return value.toString(); + } + } + } + } + }; + + const percent = ((value - minValue) / (maxValue - minValue)) * 100; + + const yaxis = { + min: minValue, + max: maxValue, + labels: { + formatter: (val) => { + const realValue = minValue + (val / 100) * (maxValue - minValue); + return realValue.toFixed(1); + } + } + }; + const series = [percent]; + const labels = [model.name]; + const colors = [model.theme.gaugeBarColor]; + + return { + series, + chart, + labels, + colors, + plotOptions, + yaxis, + responsive: [{ ...ApexChartsSetup.defaultResponsive }], + // dataLabels, + }; + } + + static setupBullet(model: NumberModel, answersData: IAnswersData): ApexChartsOptions { + let value = answersData.datasets[0][answersData.values.indexOf(model.displayValueName || "value")]; + let minValue = answersData.datasets[0][answersData.values.indexOf("min")] || 0; + let maxValue = answersData.datasets[0][answersData.values.indexOf("max")] || value * 1.25; + + if (model.dataType === "rating") { + const rateValues = model.question.visibleRateValues; + maxValue = rateValues[rateValues.length - 1].value; + minValue = rateValues[0].value; + } + + if (NumberModel.showAsPercentage) { + value = DataHelper.toPercentage(value, maxValue); + minValue = DataHelper.toPercentage(minValue, maxValue); + maxValue = DataHelper.toPercentage(maxValue, maxValue); + } + + const chart = { + type: "bar", + height: 100, + background: "transparent", + toolbar: { + show: false + } + }; + const plotOptions = { + bar: { + horizontal: true, + } + }; + const dataLabels = { + enabled: false + }; + + const xaxis = { + min: minValue, + max: maxValue, + stepSize: 5, + style: ApexChartsSetup.defaultGaugeTickFont(model.theme), + axisBorder: { + color: model.theme.gaugeBackground, + }, + }; + + const yaxis = { + axisBorder: { + color: model.theme.gaugeBackground, + }, + labels: { + offsetY: 10, + style: ApexChartsSetup.defaultGaugeValueFont(model.theme) + } + }; + + // Tooltip settings + const tooltip: any = ApexChartsSetup.defaultTooltipConfig(model.theme); + + const series = [{ + data: [{ + x: "", + y: value, + goals: [{ + value: maxValue, + strokeWidth: 1, + strokeColor: model.theme.gaugeBackground, + }] + }] + }]; + const labels = [value]; + const colors = [model.theme.gaugeBarColor]; + + return { + series, + chart, + labels, + colors, + plotOptions, + xaxis, + yaxis, + dataLabels, + tooltip, + }; + } + + static setupRadar(model: SelectBase, answersData: IAnswersData): ApexChartsOptions { + let { + datasets, + labels, + colors, + texts, + seriesLabels, + } = answersData; + const hasSeries = seriesLabels.length > 1 || model.dataType === "matrix"; + + const series = datasets.map((dataset: Array, index: number) => { + const seriesName = hasSeries ? seriesLabels[index] : ""; + return { + name: seriesName, + data: dataset + }; + }); + + const chart = { + type: "radar", + height: ApexChartsSetup.defaultChartHeight, + background: "transparent", + toolbar: { ...ApexChartsSetup.defaultToolbarConfig }, + }; + + const plotOptions = { + radar: { + polygons: { + strokeColors: model.theme.axisGridColor, + } + } + }; + + const radarLabelFont = model.theme.radarLabelFont; + const xaxis = { + labels: { + style: { + colors: radarLabelFont.color, + fontSize: radarLabelFont.size, + fontFamily: radarLabelFont.family, + fontWeight: radarLabelFont.weight, + }, + }, + categories: labels, + }; + xaxis.labels.style.colors = Array(labels.length).fill(model.theme.axisLabelFont.color) as any; + + const yaxis= { + show: true, + labels: { + show: true, + style: { + ...ApexChartsSetup.defaultAxisLabelFont(model.theme), + } + }, + tickAmount: 5 + }; + + const legend = { + ...ApexChartsSetup.defaultLegendConfig(model.theme), + show: hasSeries, + markers: { + width: 12, + height: 12, + radius: 6 + } + }; + const tooltip = { + enabled: true, + style: { + ...ApexChartsSetup.defaultTooltipConfig(model.theme), + }, + y: { + formatter: function(val: number, opts: any) { + const seriesName = opts.w.globals.seriesNames[opts.seriesIndex]; + const label = opts.w.globals.labels[opts.dataPointIndex]; + return !!seriesName ? `${seriesName}: ${val} (${label})` : `${label}: ${val}`; + } + } + }; + + return { + series, + chart, + labels, + colors, + plotOptions, + xaxis, + yaxis, + tooltip, + legend, + responsive: [{ ...ApexChartsSetup.defaultResponsive }], + }; + } +} \ No newline at end of file diff --git a/src/apexcharts/styles.scss b/src/apexcharts/styles.scss new file mode 100644 index 000000000..fdfa806bd --- /dev/null +++ b/src/apexcharts/styles.scss @@ -0,0 +1,79 @@ +.sa-visualizer { + .apexcharts-tooltip.apexcharts-tooltip { + padding: var(--sjs2-spacing-x150, 12px) var(--sjs2-spacing-x200, 16px); + border-radius: var(--sjs2-radius-container-tooltip, 8px); + border-color: var(--sjs2-color-bg-neutral-primary, #1C1B20); + background: var(--sjs2-color-bg-neutral-primary, #1C1B20); + color: var(--sjs2-color-fg-neutral-primary, #FFF); + + .apexcharts-tooltip-title { + display: none; + } + + .apexcharts-tooltip-text-goals-value, .apexcharts-tooltip-text-y-value, .apexcharts-tooltip-text-z-value { + margin: 0; + } + } + + .apexcharts-tooltip-y-group.apexcharts-tooltip-y-group { + display: flex; + flex-direction: column; + } + + .apexcharts-menu-icon.apexcharts-menu-icon svg { + fill: var(--sjs2-color-fg-brand-primary, #19B394); + opacity: var(--sjs2-opacity-x035, 0.35); + } + .apexcharts-menu-icon.apexcharts-menu-icon:hover svg { + fill: var(--sjs2-color-fg-brand-primary, #19B394); + opacity: 1; + } + + .apexcharts-menu.apexcharts-menu-open { + border: var(--sjs2-border-width-x100, 1px) solid var(--sjs2-color-border-basic-secondary, #D4D4D4); + border-top: none; + border-radius: var(--sjs2-radius-container-drop, 16px); + background: var(--sjs2-color-utility-sheet, #FFF); + margin-top: 8px; + padding: var(--sjs2-layout-container-drop-vertical, 8px) var(--sjs2-layout-container-drop-horizontal, 8px); + box-shadow: var(--sjs2-shadow-size-large-offset-x, 0) var(--sjs2-shadow-size-large-offset-y, 6px) var(--sjs2-shadow-size-large-blur, 12px) var(--sjs2-shadow-size-large-spread, 4px) var(--sjs2-shadow-color-large, rgba(0, 76, 68, 0.10)); + } + + .apexcharts-menu-item.apexcharts-menu-item { + width: max-content; + min-width: calc(100% - 2 * var(--sjs2-size-x200, 16px)); + max-width: calc(100% - 2 * var(--sjs2-size-x200, 16px)); + padding: var(--sjs2-spacing-x150, 12px) var(--sjs2-size-x200, 16px); + cursor: pointer; + transition: all 0.3s; + display: flex; + align-items: center; + gap: var(--sjs2-spacing-x150, 12px); + border-radius: var(--sjs2-radius-control-drop-item, 8px); + color: var(--sjs2-color-fg-basic-primary, #1C1B20); + background: var(--sjs2-color-bg-brand-tertiary, rgba(25, 179, 148, 0.00)); + + /* sjs2/typography/default */ + font-family: var(--sjs2-typography-font-family-default, "Open Sans", "Segoe UI", SegoeUI, Arial, sans-serif); + font-size: var(--sjs2-typography-font-size-default, 16px); + font-style: normal; + font-weight: 400; + line-height: var(--sjs2-typography-line-height-default, 24px); /* 150% */ + + &:hover { + background-color: var(--sjs2-color-bg-brand-tertiary-dim, rgba(25, 179, 148, 0.10)); + } + } + + .apx-legend-position-bottom.apx-legend-position-bottom { + display: flex; + border-radius: var(--sjs2-radius-x050, 4px); + border: var(--sjs2-border-width-default, 1px) solid var(--sjs2-color-border-basic-secondary, #D4D4D4); + background: var(--sjs2-color-bg-basic-primary, #FFF); + padding: var(--sjs2-spacing-x250, 20px); + flex-direction: column; + align-items: flex-start; + gap: var(--sjs2-spacing-x150, 12px); + align-self: stretch; + } +} \ No newline at end of file diff --git a/src/boolean.ts b/src/boolean.ts index a25e2fc35..5e30ffcd3 100644 --- a/src/boolean.ts +++ b/src/boolean.ts @@ -10,9 +10,9 @@ export class BooleanModel extends SelectBase { question: Question, data: Array<{ [index: string]: any }>, options?: Object, - name?: string + type?: string ) { - super(question, data, options, name || "boolean"); + super(question, data, options, type || "boolean"); } protected getCorrectAnswerText(): string { diff --git a/src/card.scss b/src/card.scss new file mode 100644 index 000000000..a2e82cbe6 --- /dev/null +++ b/src/card.scss @@ -0,0 +1,34 @@ +@use "globals" as *; + +.sa-visualizer-card { + display: flex; + padding-top: var(--sjs2-spacing-x300, 24px); + flex-direction: column; + align-items: flex-start; + align-self: stretch; +} + +.sa-visualizer-card-content { + display: flex; + min-width: var(--dsb-nps-vizualizer-item-min-width, 256px); + padding: var(--sjs2-spacing-x200, 16px) var(--sjs2-spacing-x300, 24px); + flex-direction: column; + align-items: flex-start; + gap: var(--sjs2-spacing-x300, 24px); + + border-radius: var(--dsb-nps-vizualizer-item-corner-radius, 8px); + border: var(--sjs2-border-width-default, 1px) dashed var(--sjs2-color-border-basic-secondary, #D4D4D4); + background: var(--sjs2-color-bg-basic-primary, #FFF); + +} + +.sa-visualizer-card-value { + color: var(--sjs2-color-fg-basic-primary, #1C1B20); + + /* sjs2/typography/large-strong */ + font-family: $font-family; + font-size: var(--sjs2-typography-font-size-large, 32px); + font-style: normal; + font-weight: 600; + line-height: var(--sjs2-typography-line-height-large, 40px); /* 125% */ +} \ No newline at end of file diff --git a/src/card.ts b/src/card.ts new file mode 100644 index 000000000..5c9da737b --- /dev/null +++ b/src/card.ts @@ -0,0 +1,90 @@ +import { Question } from "survey-core"; +import { ICalculationResult } from "./visualizerBase"; +import { DocumentHelper } from "./utils"; +import { NumberModel } from "./number"; +import { VisualizationManager } from "./visualizationManager"; + +import "./card.scss"; + +export class CardVisualizerWidget { + private _renderedTarget: HTMLDivElement = undefined; + + constructor(private _model: NumberModel, private _data: ICalculationResult) { + } + + public render(target: HTMLDivElement): void { + this._renderedTarget = target; + let value = this._data.data[0][this._data.values.indexOf(this._model.displayValueName || "value")]; + const element = DocumentHelper.createElement("div", "sa-visualizer-card"); + const cardContainer = DocumentHelper.createElement("div", "sa-visualizer-card-content"); + const cardValueElement = DocumentHelper.createElement("div", "sa-visualizer-card-value"); + cardValueElement.innerText = "" + value; + cardContainer.appendChild(cardValueElement); + element.appendChild(cardContainer); + target.appendChild(element); + } + + public dispose(): void { + if(!!this._renderedTarget) { + this._renderedTarget.innerHTML = ""; + this._renderedTarget = undefined; + } + } +} + +export class CardAdapter { + private _cardVisualizer: any; + + constructor(private model: CardVisualizer) {} + + public async create(element: HTMLElement) { + const data = await this.model.getCalculatedValues(); + this._cardVisualizer = new CardVisualizerWidget(this.model, data as any); + this._cardVisualizer.render(element); + return this._cardVisualizer; + } + + public destroy(node: HTMLElement): void { + if(this._cardVisualizer && typeof this._cardVisualizer.dispose === "function") { + this._cardVisualizer.dispose(); + } + this._cardVisualizer = undefined; + } +} + +export class CardVisualizer extends NumberModel { + public precision = 2; + private _cardAdapter: CardAdapter; + + constructor( + question: Question, + data: Array<{ [index: string]: any }>, + options?: Object, + type?: string + ) { + super(question, data, options, type || "card"); + this._cardAdapter = new CardAdapter(this); + this._chartAdapter = undefined; + } + + protected destroyContent(container: HTMLElement) { + this._cardAdapter.destroy(container); + super.destroyContent(container); + } + + protected async renderContentAsync(container: HTMLElement) { + const node: HTMLElement = DocumentHelper.createElement("div"); + container.appendChild(node); + await this._cardAdapter.create(node); + container.innerHTML = ""; + container.appendChild(node); + return container; + } + + destroy() { + this._cardAdapter.destroy(this.contentContainer); + super.destroy(); + } +} + +VisualizationManager.registerVisualizer("card", CardVisualizer); diff --git a/src/dataProvider.ts b/src/dataProvider.ts index 10776699b..8baf21329 100644 --- a/src/dataProvider.ts +++ b/src/dataProvider.ts @@ -10,6 +10,7 @@ export class DataProvider { private _filteredData: Array<{ [index: string]: any }>; protected filterValues: { [index: string]: any } = {}; + protected systemFilterValues: { [index: string]: any } = {}; constructor(private _data: Array | GetDataFn = []) { } @@ -37,13 +38,17 @@ export class DataProvider { public get filteredData(): Array { if (this._filteredData === undefined) { - let filterKeys = Object.keys(this.filterValues); + const filterValues = this.getFilterValues(); + let filterKeys = Object.keys(filterValues); if (filterKeys.length > 0) { this._filteredData = this.data.filter((item) => { - return !Object.keys(this.filterValues).some( + return !filterKeys.some( (key) => { - const filterValue = this.filterValues[key]; - const filterValueType = typeof filterValue; + const filterValue = filterValues[key]; + let filterValueType: string = typeof filterValue; + if(filterValueType === "object" && "start" in filterValue && "end" in filterValue) { + filterValueType = "range"; + } const questionValue = item[key]; if (Array.isArray(questionValue)) { if (filterValueType === "object") { @@ -61,7 +66,11 @@ export class DataProvider { if (!!seriesValue && filterValueType === "object") { return questionValue !== filterValue[seriesValue]; } - if (filterValueType === "object" && filterValue.start !== undefined && filterValue.end !== undefined) { + if (filterValueType === "range") { + if(filterValue.start === undefined && filterValue.end === undefined) { + return false; + } + let continioiusValue = typeof questionValue === "number" ? questionValue : Date.parse(questionValue); if (isNaN(continioiusValue)) { continioiusValue = parseFloat(questionValue); @@ -69,9 +78,18 @@ export class DataProvider { return true; } } - return continioiusValue < filterValue.start || continioiusValue >= filterValue.end; + if(filterValue.start !== undefined && filterValue.end !== undefined) { + return continioiusValue < filterValue.start || continioiusValue >= filterValue.end; + } + if(filterValue.start === undefined && filterValue.end !== undefined) { + return continioiusValue >= filterValue.end; + } + if(filterValue.start !== undefined && filterValue.end === undefined) { + return continioiusValue < filterValue.start; + } + return false; } - return item[key] !== this.filterValues[key]; + return item[key] !== filterValues[key]; } ); }); @@ -82,20 +100,17 @@ export class DataProvider { return this._filteredData; } - /** - * Sets filter by question name and value. - */ - public setFilter(questionName: string, selectedValue: any): void { + private setFilterCore(questionName: string, selectedValue: any, filterObject: any): void { var filterChanged = true; if (selectedValue !== undefined) { - filterChanged = this.filterValues[questionName] !== selectedValue; + filterChanged = filterObject[questionName] !== selectedValue; if (filterChanged) { - this.filterValues[questionName] = selectedValue; + filterObject[questionName] = selectedValue; } } else { - filterChanged = this.filterValues[questionName] !== undefined; + filterChanged = filterObject[questionName] !== undefined; if (filterChanged) { - delete this.filterValues[questionName]; + delete filterObject[questionName]; } } if (filterChanged) { @@ -104,18 +119,43 @@ export class DataProvider { } } - /** - * Resets filter. - */ - public resetFilter(): void { - if (Object.keys(this.filterValues).length === 0) { + private resetFilterCore(filterObject: any): void { + if (Object.keys(filterObject).length === 0) { return; } - Object.keys(this.filterValues).forEach(key => delete this.filterValues[key]); + Object.keys(filterObject).forEach(key => delete filterObject[key]); this.raiseFilterChanged(); this.raiseDataChanged(); } + /** + * Sets filter by question name and value. + */ + public setSystemFilter(questionName: string, selectedValue: any): void { + this.setFilterCore(questionName, selectedValue, this.systemFilterValues); + } + + /** + * Resets filter. + */ + public resetSystemFilter(): void { + this.resetFilterCore(this.systemFilterValues); + } + + /** + * Sets filter by question name and value. + */ + public setFilter(questionName: string, selectedValue: any): void { + this.setFilterCore(questionName, selectedValue, this.filterValues); + } + + /** + * Resets filter. + */ + public resetFilter(): void { + this.resetFilterCore(this.filterValues); + } + /** * Fires when data has been changed. */ @@ -148,7 +188,8 @@ export class DataProvider { } public getFilters(): SummaryFilter[] { - return Object.keys(this.filterValues).map(key => ({ field: key, type: "=", value: this.filterValues[key] })); + const filterValues = this.getFilterValues(); + return Object.keys(filterValues).map(key => ({ field: key, type: "=", value: filterValues[key] })); } public fixDropdownData(dataNames: string[]): void { @@ -165,6 +206,15 @@ export class DataProvider { } }); } + + public getCount(): Promise { + return new Promise(resolve => resolve(this.filteredData.length)); + } + + public getFilterValues(): {} { + const combinedFilterValues = Object.assign({}, this.systemFilterValues, this.filterValues); + return combinedFilterValues; + } } function questionArrayValueContainsValue(questionValues: Array, filterValue: any) { diff --git a/src/entries/apexcharts.fontless.ts b/src/entries/apexcharts.fontless.ts new file mode 100644 index 000000000..f46ebdf84 --- /dev/null +++ b/src/entries/apexcharts.fontless.ts @@ -0,0 +1,2 @@ +export * from "../apexcharts/index"; +export * from "./summary.core"; diff --git a/src/entries/apexcharts.ts b/src/entries/apexcharts.ts new file mode 100644 index 000000000..25b25881d --- /dev/null +++ b/src/entries/apexcharts.ts @@ -0,0 +1,2 @@ +export * from "./apexcharts.fontless"; +import "./fonts.scss"; \ No newline at end of file diff --git a/src/entries/fonts.scss b/src/entries/fonts.scss new file mode 100644 index 000000000..86f3bd837 --- /dev/null +++ b/src/entries/fonts.scss @@ -0,0 +1,243 @@ +/* cyrillic-ext */ +@font-face { + font-family: 'Open Sans'; + font-style: normal; + font-weight: 400; + font-stretch: 100%; + src: url(https://fonts.gstatic.com/s/opensans/v34/memvYaGs126MiZpBA-UvWbX2vVnXBbObj2OVTSKmu1aB.woff2) format('woff2'); + unicode-range: U+0460-052F, U+1C80-1C88, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F; +} + +/* cyrillic */ +@font-face { + font-family: 'Open Sans'; + font-style: normal; + font-weight: 400; + font-stretch: 100%; + src: url(https://fonts.gstatic.com/s/opensans/v34/memvYaGs126MiZpBA-UvWbX2vVnXBbObj2OVTSumu1aB.woff2) format('woff2'); + unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116; +} + +/* greek-ext */ +@font-face { + font-family: 'Open Sans'; + font-style: normal; + font-weight: 400; + font-stretch: 100%; + src: url(https://fonts.gstatic.com/s/opensans/v34/memvYaGs126MiZpBA-UvWbX2vVnXBbObj2OVTSOmu1aB.woff2) format('woff2'); + unicode-range: U+1F00-1FFF; +} + +/* greek */ +@font-face { + font-family: 'Open Sans'; + font-style: normal; + font-weight: 400; + font-stretch: 100%; + src: url(https://fonts.gstatic.com/s/opensans/v34/memvYaGs126MiZpBA-UvWbX2vVnXBbObj2OVTSymu1aB.woff2) format('woff2'); + unicode-range: U+0370-03FF; +} + +/* hebrew */ +@font-face { + font-family: 'Open Sans'; + font-style: normal; + font-weight: 400; + font-stretch: 100%; + src: url(https://fonts.gstatic.com/s/opensans/v34/memvYaGs126MiZpBA-UvWbX2vVnXBbObj2OVTS2mu1aB.woff2) format('woff2'); + unicode-range: U+0590-05FF, U+200C-2010, U+20AA, U+25CC, U+FB1D-FB4F; +} + +/* vietnamese */ +@font-face { + font-family: 'Open Sans'; + font-style: normal; + font-weight: 400; + font-stretch: 100%; + src: url(https://fonts.gstatic.com/s/opensans/v34/memvYaGs126MiZpBA-UvWbX2vVnXBbObj2OVTSCmu1aB.woff2) format('woff2'); + unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+1EA0-1EF9, U+20AB; +} + +/* latin-ext */ +@font-face { + font-family: 'Open Sans'; + font-style: normal; + font-weight: 400; + font-stretch: 100%; + src: url(https://fonts.gstatic.com/s/opensans/v34/memvYaGs126MiZpBA-UvWbX2vVnXBbObj2OVTSGmu1aB.woff2) format('woff2'); + unicode-range: U+0100-024F, U+0259, U+1E00-1EFF, U+2020, U+20A0-20AB, U+20AD-20CF, U+2113, U+2C60-2C7F, U+A720-A7FF; +} + +/* latin */ +@font-face { + font-family: 'Open Sans'; + font-style: normal; + font-weight: 400; + font-stretch: 100%; + src: url(https://fonts.gstatic.com/s/opensans/v34/memvYaGs126MiZpBA-UvWbX2vVnXBbObj2OVTS-muw.woff2) format('woff2'); + unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; +} + +/* cyrillic-ext */ +@font-face { + font-family: 'Open Sans'; + font-style: normal; + font-weight: 600; + font-stretch: 100%; + src: url(https://fonts.gstatic.com/s/opensans/v34/memvYaGs126MiZpBA-UvWbX2vVnXBbObj2OVTSKmu1aB.woff2) format('woff2'); + unicode-range: U+0460-052F, U+1C80-1C88, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F; +} + +/* cyrillic */ +@font-face { + font-family: 'Open Sans'; + font-style: normal; + font-weight: 600; + font-stretch: 100%; + src: url(https://fonts.gstatic.com/s/opensans/v34/memvYaGs126MiZpBA-UvWbX2vVnXBbObj2OVTSumu1aB.woff2) format('woff2'); + unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116; +} + +/* greek-ext */ +@font-face { + font-family: 'Open Sans'; + font-style: normal; + font-weight: 600; + font-stretch: 100%; + src: url(https://fonts.gstatic.com/s/opensans/v34/memvYaGs126MiZpBA-UvWbX2vVnXBbObj2OVTSOmu1aB.woff2) format('woff2'); + unicode-range: U+1F00-1FFF; +} + +/* greek */ +@font-face { + font-family: 'Open Sans'; + font-style: normal; + font-weight: 600; + font-stretch: 100%; + src: url(https://fonts.gstatic.com/s/opensans/v34/memvYaGs126MiZpBA-UvWbX2vVnXBbObj2OVTSymu1aB.woff2) format('woff2'); + unicode-range: U+0370-03FF; +} + +/* hebrew */ +@font-face { + font-family: 'Open Sans'; + font-style: normal; + font-weight: 600; + font-stretch: 100%; + src: url(https://fonts.gstatic.com/s/opensans/v34/memvYaGs126MiZpBA-UvWbX2vVnXBbObj2OVTS2mu1aB.woff2) format('woff2'); + unicode-range: U+0590-05FF, U+200C-2010, U+20AA, U+25CC, U+FB1D-FB4F; +} + +/* vietnamese */ +@font-face { + font-family: 'Open Sans'; + font-style: normal; + font-weight: 600; + font-stretch: 100%; + src: url(https://fonts.gstatic.com/s/opensans/v34/memvYaGs126MiZpBA-UvWbX2vVnXBbObj2OVTSCmu1aB.woff2) format('woff2'); + unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+1EA0-1EF9, U+20AB; +} + +/* latin-ext */ +@font-face { + font-family: 'Open Sans'; + font-style: normal; + font-weight: 600; + font-stretch: 100%; + src: url(https://fonts.gstatic.com/s/opensans/v34/memvYaGs126MiZpBA-UvWbX2vVnXBbObj2OVTSGmu1aB.woff2) format('woff2'); + unicode-range: U+0100-024F, U+0259, U+1E00-1EFF, U+2020, U+20A0-20AB, U+20AD-20CF, U+2113, U+2C60-2C7F, U+A720-A7FF; +} + +/* latin */ +@font-face { + font-family: 'Open Sans'; + font-style: normal; + font-weight: 600; + font-stretch: 100%; + src: url(https://fonts.gstatic.com/s/opensans/v34/memvYaGs126MiZpBA-UvWbX2vVnXBbObj2OVTS-muw.woff2) format('woff2'); + unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; +} + +/* cyrillic-ext */ +@font-face { + font-family: 'Open Sans'; + font-style: normal; + font-weight: 700; + font-stretch: 100%; + src: url(https://fonts.gstatic.com/s/opensans/v34/memvYaGs126MiZpBA-UvWbX2vVnXBbObj2OVTSKmu1aB.woff2) format('woff2'); + unicode-range: U+0460-052F, U+1C80-1C88, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F; +} + +/* cyrillic */ +@font-face { + font-family: 'Open Sans'; + font-style: normal; + font-weight: 700; + font-stretch: 100%; + src: url(https://fonts.gstatic.com/s/opensans/v34/memvYaGs126MiZpBA-UvWbX2vVnXBbObj2OVTSumu1aB.woff2) format('woff2'); + unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116; +} + +/* greek-ext */ +@font-face { + font-family: 'Open Sans'; + font-style: normal; + font-weight: 700; + font-stretch: 100%; + src: url(https://fonts.gstatic.com/s/opensans/v34/memvYaGs126MiZpBA-UvWbX2vVnXBbObj2OVTSOmu1aB.woff2) format('woff2'); + unicode-range: U+1F00-1FFF; +} + +/* greek */ +@font-face { + font-family: 'Open Sans'; + font-style: normal; + font-weight: 700; + font-stretch: 100%; + src: url(https://fonts.gstatic.com/s/opensans/v34/memvYaGs126MiZpBA-UvWbX2vVnXBbObj2OVTSymu1aB.woff2) format('woff2'); + unicode-range: U+0370-03FF; +} + +/* hebrew */ +@font-face { + font-family: 'Open Sans'; + font-style: normal; + font-weight: 700; + font-stretch: 100%; + src: url(https://fonts.gstatic.com/s/opensans/v34/memvYaGs126MiZpBA-UvWbX2vVnXBbObj2OVTS2mu1aB.woff2) format('woff2'); + unicode-range: U+0590-05FF, U+200C-2010, U+20AA, U+25CC, U+FB1D-FB4F; +} + +/* vietnamese */ +@font-face { + font-family: 'Open Sans'; + font-style: normal; + font-weight: 700; + font-stretch: 100%; + src: url(https://fonts.gstatic.com/s/opensans/v34/memvYaGs126MiZpBA-UvWbX2vVnXBbObj2OVTSCmu1aB.woff2) format('woff2'); + unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+1EA0-1EF9, U+20AB; +} + +/* latin-ext */ +@font-face { + font-family: 'Open Sans'; + font-style: normal; + font-weight: 700; + font-stretch: 100%; + src: url(https://fonts.gstatic.com/s/opensans/v34/memvYaGs126MiZpBA-UvWbX2vVnXBbObj2OVTSGmu1aB.woff2) format('woff2'); + unicode-range: U+0100-024F, U+0259, U+1E00-1EFF, U+2020, U+20A0-20AB, U+20AD-20CF, U+2113, U+2C60-2C7F, U+A720-A7FF; +} + +/* latin */ +@font-face { + font-family: 'Open Sans'; + font-style: normal; + font-weight: 700; + font-stretch: 100%; + src: url(https://fonts.gstatic.com/s/opensans/v34/memvYaGs126MiZpBA-UvWbX2vVnXBbObj2OVTS-muw.woff2) format('woff2'); + unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; +} + +:root { + --sjs-font-family: "Open Sans", "Helvetica Neue", Helvetica, Arial, sans-serif; +} \ No newline at end of file diff --git a/src/entries/plotly.fontless.ts b/src/entries/plotly.fontless.ts new file mode 100644 index 000000000..f668e0199 --- /dev/null +++ b/src/entries/plotly.fontless.ts @@ -0,0 +1,2 @@ +export * from "../plotly/index"; +export * from "./summary.core"; diff --git a/src/entries/plotly.ts b/src/entries/plotly.ts new file mode 100644 index 000000000..ed3f5e36d --- /dev/null +++ b/src/entries/plotly.ts @@ -0,0 +1,2 @@ +export * from "./plotly.fontless"; +import "./fonts.scss"; \ No newline at end of file diff --git a/src/entries/summary.core.ts b/src/entries/summary.core.ts index c2a635090..3ceed5fe3 100644 --- a/src/entries/summary.core.ts +++ b/src/entries/summary.core.ts @@ -21,6 +21,7 @@ export * from "../visualizerFactory"; export * from "../selectBase"; export * from "../matrix"; +export * from "../matrixDropdownGrouped"; export * from "../boolean"; export * from "../histogram"; export * from "../number"; @@ -38,7 +39,18 @@ export * from "../wordcloud/stopwords/index"; export * from "../text"; export * from "../statistics-table"; export * from "../nps"; +export * from "../card"; export * from "../ranking"; export * from "../pivot"; +export * from "../theme"; +export * from "../sjs-design-tokens/default-light"; +export * from "../sjs-design-tokens/default-dark"; export { DocumentHelper } from "../utils/index"; + +export * from "../layout-engine"; +export * from "../muuri-layout-engine"; + +import { VisualizationPanel } from "../visualizationPanel"; +import { MuuriLayoutEngine } from "../muuri-layout-engine"; +VisualizationPanel.LayoutEngine = VisualizationPanel.LayoutEngine || MuuriLayoutEngine; diff --git a/src/entries/summary.ts b/src/entries/summary.ts index f668e0199..ed3f5e36d 100644 --- a/src/entries/summary.ts +++ b/src/entries/summary.ts @@ -1,2 +1,2 @@ -export * from "../plotly/index"; -export * from "./summary.core"; +export * from "./plotly.fontless"; +import "./fonts.scss"; \ No newline at end of file diff --git a/src/entries/tabulator.ts b/src/entries/tabulator.ts index a72b07088..abf80d3e8 100644 --- a/src/entries/tabulator.ts +++ b/src/entries/tabulator.ts @@ -19,6 +19,7 @@ import "../analytics-localization/swedish"; //extensions import "../tables/extensions/rowextensions"; import "../tables/extensions/headerextensions"; +import "../tables/extensions/footerextensions"; import "../tables/extensions/columnextensions"; import "../tables/extensions/detailsextensions"; @@ -28,3 +29,8 @@ export * from "../tables/columnbuilder"; export * from "../tables/columns"; export { TableExtensions } from "../tables/extensions/tableextensions"; export { DocumentHelper } from "../utils/index"; + +export * from "../sjs-design-tokens/default-light"; +export * from "../sjs-design-tokens/default-dark"; + +import "./fonts.scss"; diff --git a/src/filterInfo.ts b/src/filterInfo.ts index 9b15a0981..063bf5d42 100644 --- a/src/filterInfo.ts +++ b/src/filterInfo.ts @@ -14,11 +14,11 @@ export class FilterInfo { "span", "sa-question__filter-text" ); - this._htmlElement.appendChild(this.text); const filterClear = DocumentHelper.createButton(() => { visualizer.setSelection(undefined); - }, localization.getString("clearButton")); + }, undefined, undefined, "close-16x16"); this._htmlElement.appendChild(filterClear); + this._htmlElement.appendChild(this.text); } public get htmlElement() { diff --git a/src/histogram.ts b/src/histogram.ts index b88643fae..88b3b4050 100644 --- a/src/histogram.ts +++ b/src/histogram.ts @@ -1,7 +1,8 @@ import { ItemValue, Question } from "survey-core"; import { DataProvider } from "./dataProvider"; -import { IAnswersData, SelectBase } from "./selectBase"; +import { SelectBase } from "./selectBase"; import { VisualizationManager } from "./visualizationManager"; +import { IAnswersData, ICalculationResult, VisualizerBase } from "./visualizerBase"; import { getNestedDataRows, histogramStatisticsCalculator } from "./statisticCalculators"; import { DocumentHelper } from "./utils"; import { localization } from "./localizationManager"; @@ -147,11 +148,11 @@ export const intervalCalculators = { }; export class HistogramModel extends SelectBase { - protected valueType: "date" | "number" = "number"; - private _cachedValues: Array<{ original: any, continuous: number, row: any }> = undefined; + protected valueType: "date" | "number" | "enum" = "number"; + protected _cachedValues: Array<{ original: any, continuous: number, row: any }> = undefined; private _continuousData: { [series: string]: Array<{continuous: number, row: any}> } = undefined; - private _cachedIntervals: Array<{ start: number, end: number, label: string }> = undefined; - private _intervalPrecision: number = 2; + protected _cachedIntervals: Array<{ start: number, end: number, label: string }> = undefined; + protected _intervalPrecision: number = 2; private showRunningTotalsBtn: HTMLElement = undefined; private showGroupedBtn: HTMLElement = undefined; private changeIntervalsModeSelector: HTMLDivElement = undefined; @@ -163,24 +164,19 @@ export class HistogramModel extends SelectBase { question: Question, data: Array<{ [index: string]: any }>, options?: Object, - name?: string + type?: string ) { - super(question, data, options, name || "histogram"); + super(question, data, options, type || "histogram"); this._transposeData = false; if (this.options.intervalPrecision !== undefined) { this._intervalPrecision = this.options.intervalPrecision; } - const questionType = question.getType(); - if (questionType === "text" && (question["inputType"] === "date" || question["inputType"] === "datetime")) { - this.valueType = "date"; - } else { - this.valueType = "number"; - } + this.valueType = this.getQuestionValueType(this.question, "number") || this.valueType; this._intervalsMode = this.valueType === "date" ? "auto" : "default" as any; if(this.allowChangeIntervals) { this.registerToolbarItem("changeIntervalsMode", () => { - this.changeIntervalsModeSelector = DocumentHelper.createSelector( + this.changeIntervalsModeSelector = DocumentHelper.createDropdown( this.intervalModes.map((intervalModeValue) => { return { value: intervalModeValue, @@ -188,13 +184,13 @@ export class HistogramModel extends SelectBase { }; }), (option: any) => this.intervalsMode === option.value, - (e: any) => { - this.intervalsMode = e.target.value; + (value: any) => { + this.intervalsMode = value; }, localization.getString("intervalModeTitle") ); return this.changeIntervalsModeSelector; - }); + }, "dropdown"); } if (this.possibleAggregateDataNames.length > 0) { this.registerToolbarItem("aggregateDataName", () => { @@ -203,17 +199,17 @@ export class HistogramModel extends SelectBase { }); choices.unshift({ value: "", text: localization.getString("noneAggregateText") }), - this.aggregateDataNameSelector = DocumentHelper.createSelector( + this.aggregateDataNameSelector = DocumentHelper.createDropdown( choices, (option: any) => this.aggregateDataName === option.value, - (e) => { - this.aggregateDataName = e.target.value; + (value) => { + this.aggregateDataName = value; }, localization.getString("selectAggregateText") ); this.updateAggregateDataNameSelector(); return this.aggregateDataNameSelector; - }); + }, "dropdown"); } if(this.allowChangeIntervals && this.options.allowRunningTotals) { this.registerToolbarItem("showRunningTotals", () => { @@ -222,7 +218,7 @@ export class HistogramModel extends SelectBase { }); this.updateShowRunningTotalsBtn(); return this.showRunningTotalsBtn; - }); + }, "button"); } if(this.allowChangeIntervals && this.options.allowCompareDatePeriods) { this.registerToolbarItem("showGrouped", () => { @@ -231,27 +227,37 @@ export class HistogramModel extends SelectBase { }); this.updateShowGroupedBtn(); return this.showGroupedBtn; - }); + }, "button"); } } private updateIntervalsModeSelector() { if (!!this.changeIntervalsModeSelector) { - this.changeIntervalsModeSelector.getElementsByTagName( - "select" - )[0].value = this.intervalsMode; + (this.changeIntervalsModeSelector as any).setValue(this.intervalsMode); + } } private updateAggregateDataNameSelector() { if (!!this.aggregateDataNameSelector) { - this.aggregateDataNameSelector.getElementsByTagName( - "select" - )[0].value = this.aggregateDataName; + (this.aggregateDataNameSelector as any).setValue(this.aggregateDataName); + } + } + + public getQuestionValueType(question: Question, defaultValue = "enum"): "enum" | "date" | "number" { + if(question) { + const questionType = question.getType(); + if (questionType === "text" && (question["inputType"] === "date" || question["inputType"] === "datetime")) { + return "date"; + } else if(questionType === "text" || questionType === "rating" || questionType === "expression" || questionType === "range") { + return "number"; + } + return defaultValue as any; } + return undefined; } - private reset() { + protected reset() { this._continuousData = undefined; this._cachedValues = undefined; this._cachedIntervals = undefined; @@ -271,7 +277,7 @@ export class HistogramModel extends SelectBase { return "" + value; } - private toPrecision(value: number) { + protected toPrecision(value: number) { const base = Math.pow(10, this._intervalPrecision); return Math.round(base * value) / base; } @@ -321,7 +327,7 @@ export class HistogramModel extends SelectBase { series.forEach(seriesValue => this._continuousData[seriesValue] = []); const hash = {}; this.data.forEach(dataRow => { - const nestedDataRows = getNestedDataRows(dataRow, this); + const nestedDataRows = getNestedDataRows(dataRow, this.dataPath); nestedDataRows.forEach(nestedDataRow => { const answerData = nestedDataRow[this.dataNames[0]]; if (answerData !== undefined) { @@ -347,14 +353,20 @@ export class HistogramModel extends SelectBase { } protected get needUseRateValues() { - return this.question.getType() == "rating" && Array.isArray(this.question["rateValues"]) && this.question["rateValues"].length > 0; + return this.dataType == "rating" && Array.isArray(this.question["rateValues"]) && this.question["rateValues"].length > 0; } public getValues(): Array { + if(this.valueType === "enum") { + return super.getValues().reverse(); + } return this.intervals.map(interval => interval.start); } public getLabels(): Array { + if(this.valueType === "enum") { + return super.getLabels().reverse(); + } return this.intervals.map(interval => interval.label); } @@ -362,12 +374,12 @@ export class HistogramModel extends SelectBase { return !!this.questionOptions && Array.isArray(this.questionOptions.intervals); } - public get intervals() { + public get intervals(): Array<{start: number, end: number, label: string}> { if (this.hasCustomIntervals) { return this.questionOptions.intervals; } - if(this.question.getType() == "rating") { + if(this.dataType == "rating") { if (this.needUseRateValues) { const rateValues = this.question["rateValues"] as ItemValue[]; rateValues.sort((iv1, iv2) => iv1.value - iv2.value); @@ -499,31 +511,35 @@ export class HistogramModel extends SelectBase { return this.questionOptions?.aggregateDataNames ?? []; } - public convertFromExternalData(externalCalculatedData: any): any[] { - return [externalCalculatedData]; + public convertFromExternalData(externalCalculatedData: Array): ICalculationResult { + return { + data: [externalCalculatedData], + values: this.intervals.map(i => i.label) + }; } - protected getCalculatedValuesCore(): Array { + protected getCalculatedValuesCore(): ICalculationResult { const continuousValues = this.getContinuousValues(); return histogramStatisticsCalculator(this._continuousData, this.intervals, this, [this.aggregateDataName].filter(name => !!name)); } - public async getCalculatedValues(): Promise> { - const values = await super.getCalculatedValues(); - const result: Array> = JSON.parse(JSON.stringify(values)); + public async getCalculatedValues(): Promise { + const result = await super.getCalculatedValues(); if(this.showRunningTotals) { - for(let i = 0; i < result.length; i++) { - for(let j = 1; j < result[i].length; j++) { - result[i][j] += result[i][j - 1]; + const resultData: Array> = JSON.parse(JSON.stringify(result.data)); + for(let i = 0; i < resultData.length; i++) { + for(let j = 1; j < resultData[i].length; j++) { + resultData[i][j] += resultData[i][j - 1]; } } + result.data = resultData; } return result; } private async getGroupedDateAnswersData(): Promise { - let datasets = (await this.getCalculatedValues()) as number[][]; - let colors = this.getColors(); + let datasets = ((await this.getCalculatedValues()).data) as number[][]; + let colors = VisualizerBase.getColors(); let labels = this.getLabels(); let seriesLabels = this.getSeriesLabels(); @@ -588,6 +604,7 @@ export class HistogramModel extends SelectBase { let texts = datasets; return { datasets, + values: this.getValues(), labels, colors, texts, @@ -620,7 +637,7 @@ export class HistogramModel extends SelectBase { return answersData; } - public getValueType(): "date" | "number" { + public getValueType(): "date" | "number" | "enum" { return this.valueType; } } diff --git a/src/images/check-24x24.svg b/src/images/check-24x24.svg new file mode 100644 index 000000000..7d18b334c --- /dev/null +++ b/src/images/check-24x24.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/src/images/chevrondown-24x24.svg b/src/images/chevrondown-24x24.svg new file mode 100644 index 000000000..496cb706b --- /dev/null +++ b/src/images/chevrondown-24x24.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/src/images/close-16x16.svg b/src/images/close-16x16.svg new file mode 100644 index 000000000..ed337d7a1 --- /dev/null +++ b/src/images/close-16x16.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/src/images/close-24x24.svg b/src/images/close-24x24.svg new file mode 100644 index 000000000..3a7a691e6 --- /dev/null +++ b/src/images/close-24x24.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/src/images/drag-24x24.svg b/src/images/drag-24x24.svg new file mode 100644 index 000000000..6dce98bfb --- /dev/null +++ b/src/images/drag-24x24.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/images/draghorizontal-24x16.svg b/src/images/draghorizontal-24x16.svg new file mode 100644 index 000000000..e3f50157d --- /dev/null +++ b/src/images/draghorizontal-24x16.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/src/images/invisible-24x24.svg b/src/images/invisible-24x24.svg new file mode 100644 index 000000000..4c215a294 --- /dev/null +++ b/src/images/invisible-24x24.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/src/images/more-24x24.svg b/src/images/more-24x24.svg new file mode 100644 index 000000000..9ce9bd995 --- /dev/null +++ b/src/images/more-24x24.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/src/images/moveToHorizontal-24x24.svg b/src/images/moveToHorizontal-24x24.svg new file mode 100644 index 000000000..98c3de3dd --- /dev/null +++ b/src/images/moveToHorizontal-24x24.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/src/images/moveToVertical-24x24.svg b/src/images/moveToVertical-24x24.svg new file mode 100644 index 000000000..72b022ba2 --- /dev/null +++ b/src/images/moveToVertical-24x24.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/src/images/redo-24x24.svg b/src/images/redo-24x24.svg new file mode 100644 index 000000000..898ef091e --- /dev/null +++ b/src/images/redo-24x24.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/src/images/reorder-24x24.svg b/src/images/reorder-24x24.svg new file mode 100644 index 000000000..a324f5eea --- /dev/null +++ b/src/images/reorder-24x24.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/src/images/search-24x24.svg b/src/images/search-24x24.svg new file mode 100644 index 000000000..ae827dc17 --- /dev/null +++ b/src/images/search-24x24.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/images/warning-24x24.svg b/src/images/warning-24x24.svg new file mode 100644 index 000000000..cb24bd2db --- /dev/null +++ b/src/images/warning-24x24.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/src/layout-engine.ts b/src/layout-engine.ts new file mode 100644 index 000000000..ac74819b9 --- /dev/null +++ b/src/layout-engine.ts @@ -0,0 +1,50 @@ +/** + * A base class used to implement custom layout engines or integrate third-party layout engines with SurveyJS Dashboard. + */ +export class LayoutEngine { + constructor(protected _allowed: boolean) { } + + protected startCore(container: HTMLElement) { } + protected stopCore() { } + protected updateCore() { } + + get allowed() { + return this._allowed; + } + + /** + * Enables the dynamic layout in a given HTML element. + * + * This method should arrange visualization items based on the available screen space and allow users to reorder them via drag and drop. + */ + start(container: HTMLElement) { + if (this._allowed) { + this.startCore(container); + } + } + /** + * Disables the dynamic layout. + */ + stop() { + if (this._allowed) { + this.stopCore(); + } + } + /** + * Updates the dynamic layout. + */ + update() { + if (this._allowed) { + this.updateCore(); + } + } + + add(elements: Array, options?: any) { } + remove(elements: Array, options?: any) { } + + onMoveCallback: (order: Array) => void; + + destroy() { + this.stop(); + } +} diff --git a/src/matrix.ts b/src/matrix.ts index f5bfc3692..176acf4f8 100644 --- a/src/matrix.ts +++ b/src/matrix.ts @@ -1,15 +1,16 @@ import { ItemValue, QuestionMatrixModel, Question } from "survey-core"; -import { IAnswersData, SelectBase } from "./selectBase"; +import { SelectBase } from "./selectBase"; import { VisualizationManager } from "./visualizationManager"; +import { IAnswersData } from "./visualizerBase"; export class Matrix extends SelectBase { constructor( question: Question, data: Array<{ [index: string]: any }>, options?: Object, - name?: string + type?: string ) { - super(question, data, options, name || "matrix"); + super(question, data, options, type || "matrix"); this._transposeData = true; // this.getAnswersData(); } @@ -68,6 +69,7 @@ export class Matrix extends SelectBase { protected hideEmptyAnswersInData(answersData: IAnswersData): IAnswersData { const result: IAnswersData = { datasets: >>[], + values: >[], labels: >[], colors: >[], texts: >>[], diff --git a/src/matrixDropdownGrouped.ts b/src/matrixDropdownGrouped.ts index 1d055caa5..4a6aa923a 100644 --- a/src/matrixDropdownGrouped.ts +++ b/src/matrixDropdownGrouped.ts @@ -1,16 +1,17 @@ import { ItemValue, QuestionMatrixDropdownModel, Question, MatrixDropdownColumn, MatrixDropdownRowModelBase } from "survey-core"; -import { IAnswersData, SelectBase } from "./selectBase"; +import { SelectBase } from "./selectBase"; import { defaultStatisticsCalculator } from "./statisticCalculators"; import { VisualizationManager } from "./visualizationManager"; +import { IAnswersData, ICalculationResult } from "./visualizerBase"; export class MatrixDropdownGrouped extends SelectBase { constructor( question: Question, data: Array<{ [index: string]: any }>, options?: Object, - name?: string + type?: string ) { - super(question, data, options, name || "matrixDropdownGrouped"); + super(question, data, options, type || "matrixDropdownGrouped"); } protected get matrixQuestion(): QuestionMatrixDropdownModel { @@ -43,13 +44,13 @@ export class MatrixDropdownGrouped extends SelectBase { return false; } - protected getCalculatedValuesCore(): Array { + protected getCalculatedValuesCore(): ICalculationResult { const values = this.getValues(); const series = this.getSeriesValues(); const rows = this.matrixQuestion.rows.map(row => row.value); const statistics = defaultStatisticsCalculator(this.surveyData, { - name: this.name, + name: this.dataNames[0], dataNames: series, dataPath: this.dataPath, getValues: () => values, @@ -58,7 +59,8 @@ export class MatrixDropdownGrouped extends SelectBase { getSeriesLabels: () => rows, }); - return statistics.map(s => s[0]); + statistics.data = statistics.data.map(a => a[0] as any); + return statistics; } } diff --git a/src/layoutEngine.ts b/src/muuri-layout-engine.ts similarity index 53% rename from src/layoutEngine.ts rename to src/muuri-layout-engine.ts index a03599fd7..0e864d3fd 100644 --- a/src/layoutEngine.ts +++ b/src/muuri-layout-engine.ts @@ -1,102 +1,52 @@ -import Muuri from "muuri"; - -/** - * A base class used to implement custom layout engines or integrate third-party layout engines with SurveyJS Dashboard. - */ -export class LayoutEngine { - constructor(protected _allowed: boolean) { } - - protected startCore(container: HTMLElement) { } - protected stopCore() { } - protected updateCore() { } - - get allowed() { - return this._allowed; - } - - /** - * Enables the dynamic layout in a given HTML element. - * - * This method should arrange visualization items based on the available screen space and allow users to reorder them via drag and drop. - */ - start(container: HTMLElement) { - if (this._allowed) { - this.startCore(container); - } - } - /** - * Disables the dynamic layout. - */ - stop() { - if (this._allowed) { - this.stopCore(); - } - } - /** - * Updates the dynamic layout. - */ - update() { - if (this._allowed) { - this.updateCore(); - } - } - - add(elements: Array, options?: any) { } - remove(elements: Array, options?: any) { } - - onMoveCallback: (order: Array) => void; - - destroy() { - this.stop(); - } -} - -export class MuuriLayoutEngine extends LayoutEngine { - private _muuri: any = undefined; - private _layoutingTimer: any = undefined; - - constructor(allowed: boolean, private _selector: string, private dragEnabled = true) { - super(allowed); - } - - protected startCore(container: HTMLElement) { - this._muuri = new Muuri(container, { - dragStartPredicate: { - handle: ".sa-question__title--draggable", - }, - items: this._selector, - dragEnabled: this.dragEnabled, - }); - this._muuri.on( - "dragReleaseEnd", - (item: any) => { - const newOrder = item.getGrid().getItems().map(gridItem => gridItem.getElement().dataset.question); - this.onMoveCallback && this.onMoveCallback(newOrder); - } - ); - } - protected stopCore() { - this._muuri.off("dragReleaseEnd"); - this._muuri.destroy(); - this._muuri = undefined; - } - protected updateCore() { - if(!this._muuri) return; - if (this._layoutingTimer !== undefined) { - clearTimeout(this._layoutingTimer); - } - this._layoutingTimer = setTimeout(() => { - this._layoutingTimer = undefined; - if(!this._muuri) return; - this._muuri.refreshItems(); - this._muuri.layout(); - }, 10); - } - - add(elements: Array, options?: any) { - if (this._allowed) this._muuri.add(elements, options); - } - remove(elements: Array, options?: any) { - if (this._allowed) this._muuri.remove(elements, options); - } -} +import Muuri from "muuri"; +import { LayoutEngine } from "./layout-engine"; + +export class MuuriLayoutEngine extends LayoutEngine { + private _muuri: any = undefined; + private _layoutingTimer: any = undefined; + + constructor(allowed: boolean, private _selector: string, private dragEnabled = true) { + super(allowed); + } + + protected startCore(container: HTMLElement) { + this._muuri = new Muuri(container, { + dragStartPredicate: { + handle: ".sa-question__header--draggable", + }, + items: this._selector, + dragEnabled: this.dragEnabled, + }); + this._muuri.on( + "dragReleaseEnd", + (item: any) => { + const newOrder = item.getGrid().getItems().map(gridItem => gridItem.getElement().dataset.question); + this.onMoveCallback && this.onMoveCallback(newOrder); + } + ); + } + protected stopCore() { + this._muuri.off("dragReleaseEnd"); + this._muuri.destroy(); + this._muuri = undefined; + } + protected updateCore() { + if(!this._muuri) return; + if (this._layoutingTimer !== undefined) { + clearTimeout(this._layoutingTimer); + } + this._layoutingTimer = setTimeout(() => { + this._layoutingTimer = undefined; + if(!this._muuri) return; + this._muuri.refreshItems(); + this._muuri.layout(); + }, 10); + } + + add(elements: Array, options?: any) { + if (this._allowed) this._muuri.add(elements, options); + } + remove(elements: Array, options?: any) { + if (this._allowed) this._muuri.remove(elements, options); + } +} diff --git a/src/nps.scss b/src/nps.scss index 0c6344c66..361dacf43 100644 --- a/src/nps.scss +++ b/src/nps.scss @@ -1,34 +1,66 @@ +@use "globals" as *; + .sa-visualizer-nps { display: flex; - flex-direction: row; - gap: 16px; - overflow-x: auto; + align-items: flex-start; + align-content: flex-start; + gap: 16px var(--dsb-nps-vizualizer-gap, 16px); + align-self: stretch; + flex-wrap: wrap; } .sa-visualizer-nps__score-part { display: flex; + min-width: var(--dsb-nps-vizualizer-item-min-width, 256px); + padding: var(--dsb-nps-vizualizer-item-padding-top, 16px) var(--dsb-nps-vizualizer-item-padding-right, 24px) var(--dsb-nps-vizualizer-item-padding-bottom, 16px) var(--dsb-nps-vizualizer-item-padding-left, 24px); flex-direction: column; - padding: 0 16px; + align-items: flex-start; + gap: var(--dsb-nps-vizualizer-item-gap, 24px); + flex: 1 0 0; + + border-radius: var(--dsb-nps-vizualizer-item-corner-radius, 8px); + border: var(--dsb-nps-vizualizer-item-border-width, 1px) dashed var(--dsb-nps-vizualizer-item-border-color, #DCDCDC); + background: var(--dsb-nps-vizualizer-item-background-color, #FFF); } .sa-visualizer-nps__score-part-title { - font-size: 32px; - text-align: center; - color: #909090; + color: var(--dsb-nps-vizualizer-item-title-color, rgba(0, 0, 0, 0.90)); + + /* ctr/Default Bold */ + font-family: $font-family; + font-size: var(--ctr-font-default-size, 16px); + font-style: normal; + font-weight: 600; + line-height: var(--ctr-font-default-line-height, 24px); /* 150% */ } .sa-visualizer-nps__score-part-values { display: flex; - flex-direction: row; - gap: 16px; - align-items: baseline; + align-items: flex-start; + gap: var(--dsb-nps-vizualizer-item-text-gap, 24px); + align-self: stretch; } .sa-visualizer-nps__score-part-value { - font-size: 48px; + flex: 1 0 0; + color: var(--dsb-nps-vizualizer-item-text-color-value, rgba(0, 0, 0, 0.90)); + + /* ctr/Large Bold */ + font-family: $font-family; + font-size: var(--ctr-font-large-size, 32px); + font-style: normal; + font-weight: 700; + line-height: var(--ctr-font-large-line-height, 40px); /* 125% */ } .sa-visualizer-nps__score-part-percent { - font-size: 24px; - color: #606060; + color: var(--dsb-nps-vizualizer-item-text-color-percent, #19B394); + text-align: right; + + /* ctr/Large Bold */ + font-family: $font-family; + font-size: var(--ctr-font-large-size, 32px); + font-style: normal; + font-weight: 700; + line-height: var(--ctr-font-large-line-height, 40px); /* 125% */ } \ No newline at end of file diff --git a/src/nps.ts b/src/nps.ts index cf188bce8..824aa6d7c 100644 --- a/src/nps.ts +++ b/src/nps.ts @@ -1,5 +1,5 @@ import { Question, Event } from "survey-core"; -import { VisualizerBase } from "./visualizerBase"; +import { ICalculationResult, VisualizerBase } from "./visualizerBase"; import { VisualizationManager } from "./visualizationManager"; import { DocumentHelper, toPrecision } from "./utils"; import { localization } from "./localizationManager"; @@ -8,8 +8,12 @@ import "./nps.scss"; export class NpsVisualizerWidget { private _renderedTarget: HTMLDivElement = undefined; + private _data: { detractors: number, passive: number, promoters: number, total: number } = {} as any; - constructor(private _model: NpsVisualizer, private _data: { detractors: number, passive: number, promoters: number, total: number }) { + constructor(private _model: NpsVisualizer, data: ICalculationResult) { + (data.values || []).forEach((name, index) => { + this._data[name] = data.data[0][index]; + }); } private renderScorePart(partId: string, value: number, percent?: number) { @@ -92,13 +96,13 @@ export class NpsVisualizer extends VisualizerBase { question: Question, data: Array<{ [index: string]: any }>, options?: Object, - name?: string + type?: string ) { - super(question, data, options, name || "nps"); + super(question, data, options, type || "nps"); this._npsAdapter = new NpsAdapter(this); } - protected getCalculatedValuesCore(): any { + protected getCalculatedValuesCore(): ICalculationResult { let result = { detractors: 0, passive: 0, @@ -107,7 +111,7 @@ export class NpsVisualizer extends VisualizerBase { }; this.data.forEach((row) => { - const rowValue: any = row[this.question.name]; + const rowValue: any = row[this.dataNames[0]]; const scoreValue = parseInt(rowValue); if (!Number.isNaN(scoreValue)) { if(scoreValue <= NpsVisualizer.DetractorScore) { @@ -121,7 +125,10 @@ export class NpsVisualizer extends VisualizerBase { } }); - return result; + return { + data: [Object.keys(result).map(k => result[k])], + values: Object.keys(result) + }; } protected destroyContent(container: HTMLElement) { @@ -145,3 +152,4 @@ export class NpsVisualizer extends VisualizerBase { } // VisualizationManager.registerVisualizer("rating", NpsVisualizer); +VisualizationManager.registerVisualizer("nps", NpsVisualizer); diff --git a/src/number.ts b/src/number.ts index 12b3825b9..379e60126 100644 --- a/src/number.ts +++ b/src/number.ts @@ -1,14 +1,12 @@ import { Question } from "survey-core"; -import { VisualizerBase } from "./visualizerBase"; +import { ICalculationResult, VisualizerBase } from "./visualizerBase"; import { localization } from "./localizationManager"; import { DocumentHelper } from "./utils/index"; import { VisualizationManager } from "./visualizationManager"; import { mathStatisticsCalculator } from "./statisticCalculators"; export class NumberModel extends VisualizerBase { - private _resultAverage: number; - private _resultMin: number; - private _resultMax: number; + private _statistics: ICalculationResult; public static stepsCount = 5; public static generateTextsCallback: ( @@ -24,24 +22,30 @@ export class NumberModel extends VisualizerBase { public static showAsPercentage = false; + public displayValueName = "average"; + constructor( question: Question, data: Array<{ [index: string]: any }>, options: { [index: string]: any } = {}, - name?: string + type?: string ) { - super(question, data, options, name || "number"); + super(question, data, options, type || "number"); + + if(!!this.question.displayValueName) { + this.displayValueName = this.question.displayValueName; + } if (VisualizerBase.chartAdapterType) { this._chartAdapter = new VisualizerBase.chartAdapterType(this); this.chartTypes = this._chartAdapter.getChartTypes(); - this.chartType = this.chartTypes[0]; + this.chartType = this.questionOptions?.chartType || this.chartTypes[0]; } - if(this.options.allowChangeVisualizerType !== false) { + if(this.options.allowChangeVisualizerType !== false && !(this.questionOptions?.allowChangeVisualizerType === false)) { this.registerToolbarItem("changeChartType", () => { if (this.chartTypes.length > 1) { - return DocumentHelper.createSelector( + return DocumentHelper.createDropdown( this.chartTypes.map((chartType) => { return { value: chartType, @@ -50,19 +54,17 @@ export class NumberModel extends VisualizerBase { }), (option: any) => this.chartType === option.value, (e: any) => { - this.setChartType(e.target.value); + this.setChartType(e); } ); } return null; - }); + }, "dropdown"); } } protected onDataChanged() { - this._resultAverage = undefined; - this._resultMin = undefined; - this._resultMax = undefined; + this._statistics = undefined; super.onDataChanged(); } @@ -84,9 +86,7 @@ export class NumberModel extends VisualizerBase { } destroy(): void { - this._resultAverage = undefined; - this._resultMin = undefined; - this._resultMax = undefined; + this._statistics = undefined; super.destroy(); } @@ -132,7 +132,7 @@ export class NumberModel extends VisualizerBase { } generateColors(maxValue: number, minValue: number, stepsCount: number): string[] { - const palette = this.getColors(); + const palette = VisualizerBase.getColors(); const colors = []; for (let i = 0; i < stepsCount; i++) { colors.push(palette[i]); @@ -141,21 +141,26 @@ export class NumberModel extends VisualizerBase { return colors; } - public convertFromExternalData(externalCalculatedData: any): any[] { - return [externalCalculatedData.value || 0, externalCalculatedData.minValue || 0, externalCalculatedData.maxValue || 0]; + public convertFromExternalData(externalCalculatedData: any): ICalculationResult { + return { + data: [[externalCalculatedData.value || 0, externalCalculatedData.minValue || 0, externalCalculatedData.maxValue || 0, externalCalculatedData.count || 0]], + values: ["average", "min", "max", "count"] + }; } - protected getCalculatedValuesCore(): Array { - if (this._resultAverage === undefined || - this._resultMin === undefined || - this._resultMax === undefined) { - [this._resultAverage, this._resultMin, this._resultMax] = mathStatisticsCalculator(this.surveyData, this); + protected getCalculatedValuesCore(): ICalculationResult { + if (this._statistics === undefined) { + this._statistics = mathStatisticsCalculator(this.surveyData, this); } - return [this._resultAverage, this._resultMin, this._resultMax]; + return this._statistics; } + public getValues(): Array { + return this._statistics ? this._statistics.values : []; + } } VisualizationManager.registerVisualizer("number", NumberModel, 200); VisualizationManager.registerVisualizer("rating", NumberModel, 200); -VisualizationManager.registerVisualizer("expression", NumberModel); \ No newline at end of file +VisualizationManager.registerVisualizer("expression", NumberModel); +VisualizationManager.registerVisualizer("gauge", NumberModel); \ No newline at end of file diff --git a/src/pivot.ts b/src/pivot.ts index 2ed0f05de..80f9d71a3 100644 --- a/src/pivot.ts +++ b/src/pivot.ts @@ -1,16 +1,13 @@ import { ItemValue, Question } from "survey-core"; import { SelectBase } from "./selectBase"; import { createCommercialLicenseLink, DocumentHelper } from "./utils"; -import { VisualizerBase } from "./visualizerBase"; +import { ICalculationResult, VisualizerBase } from "./visualizerBase"; import { localization } from "./localizationManager"; import { VisualizationManager } from "./visualizationManager"; +import { HistogramModel } from "./histogram"; -export class PivotModel extends SelectBase { - protected valueType: "enum" | "date" | "number" = "enum"; - private _cachedValues: Array<{ original: any, continuous: number, row: any }> = undefined; - private _continuousData: Array<{ continuous: number, row: any }> = undefined; - private _cachedIntervals: Array<{ start: number, end: number, label: string }> = undefined; - private _intervalPrecision: number = 2; +export class PivotModel extends HistogramModel { + private _pivotContinuousData: Array<{ continuous: number, row: any }> = undefined; private axisXSelector: HTMLDivElement; public axisXQuestionName: string; @@ -18,25 +15,19 @@ export class PivotModel extends SelectBase { public axisYQuestionNames: Array = []; private questionsY: Array = []; - public static IntervalsCount = 10; - public static UseIntervalsFrom = 10; - constructor( private questions: Array, data: Array<{ [index: string]: any }>, options?: Object, - name?: string, + type?: string, private isRoot = true ) { - super(null, data, options, name || "pivot"); + super(null, data, options, type || "pivot"); this.questions = this.questions.filter((question) => ["matrixdropdown", "matrixdynamic", "matrix", "file", "signature", "multipletext", "comment", "html", "image"].indexOf(question.getType()) === -1); - if (this.options.intervalPrecision !== undefined) { - this._intervalPrecision = this.options.intervalPrecision; - } this.axisXQuestionName = this.questions.length > 0 ? this.questions[0].name : undefined; this.registerToolbarItem("axisXSelector", () => - this.axisXSelector = DocumentHelper.createSelector( + this.axisXSelector = DocumentHelper.createDropdown( this.questions.map((question) => { return { value: question.name, @@ -45,15 +36,16 @@ export class PivotModel extends SelectBase { }), (option: any) => this.axisXQuestionName === option.value, (e: any) => { - this.axisXQuestionName = e.target.value; + this.axisXQuestionName = e; this.updateQuestionsSelection(); this.updateToolbar(); this.setupPivot(); }, + undefined, () => this.isXYChart() ? localization.getString("axisXSelectorTitle") : localization.getString("axisXAlternativeSelectorTitle") - ) + ), "dropdown" ); - this.registerToolbarItem("axisYSelector0", this.createYSelecterGenerator()); + this.registerToolbarItem("axisYSelector0", this.createYSelecterGenerator(), "dropdown"); this.setupPivot(); } @@ -93,7 +85,7 @@ export class PivotModel extends SelectBase { } } else { if(!!value) { - this.registerToolbarItem("axisYSelector" + this.axisYSelectors.length, this.createYSelecterGenerator()); + this.registerToolbarItem("axisYSelector" + this.axisYSelectors.length, this.createYSelecterGenerator(), "dropdown"); } } @@ -116,6 +108,7 @@ export class PivotModel extends SelectBase { } private createAxisYSelector(selectorIndex: number): HTMLDivElement { + const getChoices = () => { const choices = this.questions.filter(q => { if(q.name === this.axisXQuestionName) { @@ -134,10 +127,11 @@ export class PivotModel extends SelectBase { if(getChoices().length == 1) { return undefined; } - const selector = DocumentHelper.createSelector( + const selector = DocumentHelper.createDropdown( getChoices, (option: any) => this.axisYQuestionNames[selectorIndex] === option.value, - (e: any) => { this.onAxisYSelectorChanged(selectorIndex, e.target.value); }, + (e: any) => { this.onAxisYSelectorChanged(selectorIndex, e); }, + undefined, () => selectorIndex ? undefined : (this.isXYChart() ? localization.getString("axisYSelectorTitle") : localization.getString("axisYAlternativeSelectorTitle")) ); return selector; @@ -155,16 +149,6 @@ export class PivotModel extends SelectBase { return ["pie", "doughnut"].indexOf(this.chartType) === -1; } - public getQuestionValueType(question: Question): "enum" | "date" | "number" { - const questionType = question.getType(); - if (questionType === "text" && (question["inputType"] === "date" || question["inputType"] === "datetime")) { - return "date"; - } else if(questionType === "text" || questionType === "rating" || questionType === "expression" || questionType === "range") { - return "number"; - } - return "enum"; - } - private setupPivot() { const questionX = this.questions.filter((q) => q.name === this.axisXQuestionName)[0]; if(!questionX) { @@ -183,57 +167,9 @@ export class PivotModel extends SelectBase { this.onDataChanged(); } - private reset() { - this._continuousData = undefined; - this._cachedValues = undefined; - this._cachedIntervals = undefined; - } - - public getContinuousValue(value: any): number { - if (this.valueType === "date") { - return Date.parse(value); - } - return parseFloat(value); - } - - public getString(value: number): string { - if (this.valueType === "date") { - return new Date(value).toLocaleDateString(); - } - return "" + value; - } - - private toPrecision(value: number) { - const base = Math.pow(10, this._intervalPrecision); - return Math.round(base * value) / base; - } - - public getSelectedItemByText(itemText: string) { - if (this.hasCustomIntervals || this.getContinuousValues().length > PivotModel.UseIntervalsFrom) { - const interval = this.intervals.filter(interval => interval.label === itemText)[0]; - return new ItemValue(interval, interval !== undefined ? interval.label : ""); - } - const labels = this.getLabels(); - const labelIndex = labels.indexOf(itemText); - return new ItemValue(this.getValues()[labelIndex], labels[labelIndex]); - } - - /** - * Updates visualizer data. - */ - public updateData(data: Array<{ [index: string]: any }>) { - this.reset(); - super.updateData(data); - } - - protected onDataChanged() { - this.reset(); - super.onDataChanged(); - } - protected getContinuousValues() { if (this._cachedValues === undefined) { - this._continuousData = []; + this._pivotContinuousData = []; if(this.valueType === "enum") { this._cachedValues = []; return this._cachedValues; @@ -243,7 +179,7 @@ export class PivotModel extends SelectBase { const answerData = dataItem[this.name]; if (answerData !== undefined) { // TODO: _continuousData should be sorted in order to speed-up statistics calculation in the getData function - this._continuousData.push({ continuous: this.getContinuousValue(answerData), row: dataItem }); + this._pivotContinuousData.push({ continuous: this.getContinuousValue(answerData), row: dataItem }); hash[answerData] = { value: answerData, row: dataItem }; } }); @@ -257,14 +193,6 @@ export class PivotModel extends SelectBase { return false; } - protected isSupportMissingAnswers(): boolean { - return false; - } - - protected get needUseRateValues() { - return this.question.getType() == "rating" && Array.isArray(this.question["rateValues"]) && this.question["rateValues"].length > 0; - } - public getSeriesValues(): Array { if(!this.questionsY || this.questionsY.length === 0) { return this.options.seriesValues || []; @@ -295,77 +223,12 @@ export class PivotModel extends SelectBase { return seriesLabels; } - public getValues(): Array { - if(this.valueType === "enum") { - return super.getValues().reverse(); - } - return this.intervals.map(interval => interval.start); - } - - public getLabels(): Array { - if(this.valueType === "enum") { - return super.getLabels().reverse(); - } - return this.intervals.map(interval => interval.label); - } - - public get hasCustomIntervals() { - return !!this.questionOptions && Array.isArray(this.questionOptions.intervals); - } - - public get intervals() { - if (this.hasCustomIntervals) { - return this.questionOptions.intervals; - } - - if(this.question.getType() == "rating") { - if (this.needUseRateValues) { - const rateValues = this.question["rateValues"] as ItemValue[]; - rateValues.sort((iv1, iv2) => iv1.value - iv2.value); - return rateValues.map((rateValue, i) => ({ - start: rateValue.value, - end: i < rateValues.length - 1 ? rateValues[i + 1].value : rateValue.value + 1, - label: rateValue.text - })); - } else { - const rateIntervals = []; - for(let i = (this.question["rateMin"] || 0); i <= (this.question["rateMax"] || (PivotModel.IntervalsCount - 1)); i += (this.question["rateStep"] || 1)) { - rateIntervals.push({ - start: i, - end: i + 1, - label: "" + (!!this.question["rateMin"] && !!this.question["rateMax"] ? i : (i + "-" + (i+1))) - }); - } - return rateIntervals; - } - } - - if (this._cachedIntervals === undefined) { - const continuousValues = this.getContinuousValues(); - this._cachedIntervals = []; - if (continuousValues.length) { - let start = continuousValues[0].continuous; - const end = continuousValues[continuousValues.length - 1].continuous; - const intervalsCount = PivotModel.IntervalsCount; - const delta = (end - start) / intervalsCount; - for (let i = 0; i < intervalsCount; ++i) { - const next = start + delta; - const istart = this.toPrecision(start); - const inext = this.toPrecision(next); - this._cachedIntervals.push({ - start: istart, - end: i < intervalsCount - 1 ? inext : inext + delta / 100, - label: "" + this.getString(istart) + "-" + this.getString(inext) - }); - start = next; - } - } - } - return this._cachedIntervals; - } - - public convertFromExternalData(externalCalculatedData: any): any[] { - return [externalCalculatedData]; + public convertFromExternalData(externalCalculatedData: any): ICalculationResult { + return { + data: [externalCalculatedData], + values: this.getValues(), + series: this.getSeriesValues() + }; } getSeriesValueIndexes(): { [index: string]: number } { @@ -399,7 +262,7 @@ export class PivotModel extends SelectBase { } } - protected getCalculatedValuesCore(): Array { + protected getCalculatedValuesCore(): ICalculationResult { const statistics: Array> = []; const series = this.getSeriesValues(); if (series.length === 0) { @@ -432,7 +295,7 @@ export class PivotModel extends SelectBase { for (var i = 0; i < series.length; ++i) { statistics.push(intervals.map(i => 0)); } - this._continuousData.forEach(dataValue => { + this._pivotContinuousData.forEach(dataValue => { for (let valueIndex = 0; valueIndex < intervals.length; ++valueIndex) { if (intervals[valueIndex].start <= dataValue.continuous && (dataValue.continuous < intervals[valueIndex].end || valueIndex == intervals.length - 1)) { if(this.questionsY.length === 0) { @@ -445,24 +308,23 @@ export class PivotModel extends SelectBase { } }); } - return statistics; - } - - public getValueType(): "enum" | "date" | "number" { - return this.valueType; + return { + data: statistics, + values: this.valueType === "enum" ? this.getValues() : this.intervals.map(i => i.label) + }; } - protected isSupportSoftUpdateContent(): boolean { - return false; + protected renderToolbar(container: HTMLElement) { + container.className += " sa-pivot__header"; + super.renderToolbar(container); } - protected renderToolbar(container: HTMLElement) { + protected renderBanner(container: HTMLElement): void { if (!this.haveCommercialLicense && this.isRoot) { const banner = createCommercialLicenseLink(); container.appendChild(banner); } - container.className += " sa-pivot__header"; - super.renderToolbar(container); + super.renderBanner(container); } } diff --git a/src/plotly/chart-adapter.ts b/src/plotly/chart-adapter.ts index db00b25de..8a965d7b0 100644 --- a/src/plotly/chart-adapter.ts +++ b/src/plotly/chart-adapter.ts @@ -1,6 +1,5 @@ import { Question, ItemValue, Event } from "survey-core"; import { SelectBase } from "../selectBase"; -import { VisualizationManager } from "../visualizationManager"; import { localization } from "../localizationManager"; import Plotly from "plotly.js-dist-min"; import { PlotlySetup } from "./setup"; @@ -30,8 +29,8 @@ export class PlotlyChartAdapter implements IChartAdapter { layout: object, config: any ) { - if(this.model.question.getType() === "boolean") { - const colors = this.model.getColors(); + if(this.model.dataType === "boolean") { + const colors = VisualizerBase.getColors(); const boolColors = [ BooleanModel.trueColor || colors[0], BooleanModel.falseColor || colors[1], @@ -72,58 +71,13 @@ export class PlotlyChartAdapter implements IChartAdapter { public async create(chartNode: HTMLElement): Promise { const [plot, plotlyOptions] = await this.update(chartNode); - - if(this.model instanceof SelectBase && this.model.supportSelection) { - const _model = this.model as SelectBase; - (chartNode)["on"]("plotly_click", (data: any) => { - if (data.points.length > 0) { - let itemText = ""; - if (!plotlyOptions.hasSeries) { - itemText = Array.isArray(data.points[0].customdata) - ? data.points[0].customdata[0] - : data.points[0].customdata; - const item: ItemValue = _model.getSelectedItemByText(itemText); - _model.setSelection(item); - } else { - itemText = data.points[0].data.name; - const propertyLabel = data.points[0].label; - const seriesValues = this.model.getSeriesValues(); - const seriesLabels = this.model.getSeriesLabels(); - const propertyValue = seriesValues[seriesLabels.indexOf(propertyLabel)]; - const selectedItem: ItemValue = _model.getSelectedItemByText(itemText); - const item = new ItemValue({ [propertyValue]: selectedItem.value }, propertyLabel + ": " + selectedItem.text); - _model.setSelection(item); - } - - // const itemText = plotlyOptions.hasSeries - // ? data.points[0].data.name - // : Array.isArray(data.points[0].customdata) - // ? data.points[0].customdata[0] - // : data.points[0].customdata; - // const item: ItemValue = this.model.getSelectedItemByText(itemText); - // this.model.setSelection(item); - } - }); - } - - var getDragLayer = () => - chartNode.getElementsByClassName("nsewdrag")[0]; - (chartNode)["on"]("plotly_hover", () => { - const dragLayer = getDragLayer(); - dragLayer && (dragLayer.style.cursor = "pointer"); - }); - (chartNode)["on"]("plotly_unhover", () => { - const dragLayer = getDragLayer(); - dragLayer && (dragLayer.style.cursor = ""); - }); - - // setTimeout(() => Plotly.Plots.resize(chartNode), 10); this._chart = plot; return plot; } public async update(chartNode: HTMLElement): Promise { - const answersData = (this.model instanceof SelectBase) ? await this.model.getAnswersData() : await this.model.getCalculatedValues(); + chartNode.className = "sa-visualizer--plotly"; + const answersData = await this.model.getAnswersData(); var plotlyOptions = PlotlySetup.setup((this.model as any).chartType, this.model, answersData as any); let config: any = { @@ -175,6 +129,51 @@ export class PlotlyChartAdapter implements IChartAdapter { options.config ); + const plotlyChart = chartNode; + + if(this.model instanceof SelectBase && this.model.supportSelection) { + const _model = this.model as SelectBase; + plotlyChart.removeAllListeners("plotly_click"); + plotlyChart.on("plotly_click", (data: any) => { + if (data.points.length > 0) { + let itemText = ""; + if (!plotlyOptions.hasSeries) { + itemText = Array.isArray(data.points[0].customdata) + ? data.points[0].customdata[0] + : data.points[0].customdata; + const item: ItemValue = _model.getSelectedItemByText(itemText); + _model.setSelection(item); + } else { + itemText = data.points[0].data.name; + const propertyLabel = data.points[0].label; + const seriesValues = this.model.getSeriesValues(); + const seriesLabels = this.model.getSeriesLabels(); + const propertyValue = seriesValues[seriesLabels.indexOf(propertyLabel)]; + const selectedItem: ItemValue = _model.getSelectedItemByText(itemText); + const item = new ItemValue({ [propertyValue]: selectedItem.value }, propertyLabel + ": " + selectedItem.text); + _model.setSelection(item); + } + + // const itemText = plotlyOptions.hasSeries + // ? data.points[0].data.name + // : Array.isArray(data.points[0].customdata) + // ? data.points[0].customdata[0] + // : data.points[0].customdata; + // const item: ItemValue = this.model.getSelectedItemByText(itemText); + // this.model.setSelection(item); + } + }); + } + + var setCursorOnDragLayer = (cursor: string) => { + const dragLayer = chartNode.getElementsByClassName("nsewdrag")[0]; + dragLayer && (dragLayer.style.cursor = cursor); + }; + !!plotlyChart.removeAllListeners && plotlyChart.removeAllListeners("plotly_hover"); + plotlyChart.on("plotly_hover", () => setCursorOnDragLayer("pointer")); + !!plotlyChart.removeAllListeners && plotlyChart.removeAllListeners("plotly_unhover"); + plotlyChart.on("plotly_unhover", () => setCursorOnDragLayer("")); + return [plot, plotlyOptions]; } diff --git a/src/plotly/legacy.ts b/src/plotly/legacy.ts index 69d76bb5a..c38a2c732 100644 --- a/src/plotly/legacy.ts +++ b/src/plotly/legacy.ts @@ -13,7 +13,7 @@ export class SelectBasePlotly extends SelectBase { } export class BooleanPlotly extends BooleanModel { - public static types = ["pie", "bar", "doughnut"]; + public static types = ["pie", "doughnut", "bar"]; } export class HistogramPlotly extends HistogramModel { diff --git a/src/plotly/setup.ts b/src/plotly/setup.ts index 46e92bee2..c001de781 100644 --- a/src/plotly/setup.ts +++ b/src/plotly/setup.ts @@ -1,9 +1,11 @@ import { Event, QuestionRatingModel } from "survey-core"; -import { IAnswersData, SelectBase } from "../selectBase"; -import { VisualizerBase } from "../visualizerBase"; +import { SelectBase } from "../selectBase"; +import { IAnswersData, VisualizerBase } from "../visualizerBase"; import { localization } from "../localizationManager"; import { DataHelper } from "../utils"; import { NumberModel } from "../number"; +import { DashboardTheme } from "../theme"; +import { reverseAll } from "../utils/utils"; export interface PlotlyOptions { traces: Array; @@ -13,6 +15,160 @@ export interface PlotlyOptions { export class PlotlySetup { public static imageExportFormat = "png"; + + static defaultBarGap = DashboardTheme.barGap; + + static getRgbaColor(propertyValue: any): string { + let str = propertyValue; + if (!str) return null; + const canvasElement = document.createElement("canvas") as HTMLCanvasElement; + if (!canvasElement) return null; + const ctx = canvasElement.getContext("2d"); + ctx.fillStyle = str; + + if (ctx.fillStyle == "#000000") { + ctx.fillStyle = propertyValue; + } + const newStr = ctx.fillStyle as string; + const match = newStr.match(/color\(srgb\s+([\d.]+)\s+([\d.]+)\s+([\d.]+)\s*\/\s*([\d.]+)\)/); + + if (!match) { + return newStr; + } + + const r = parseFloat(match[1]); + const g = parseFloat(match[2]); + const b = parseFloat(match[3]); + const alpha = parseFloat(match[4]); + const result = `rgba(${r}, ${g}, ${b}, ${alpha})`; + return result; + } + + static defaultModebarConfig(theme: DashboardTheme) { + return { + bgcolor: "transparent", + activecolor: PlotlySetup.getRgbaColor(theme.modebarActiveColor), + color: PlotlySetup.getRgbaColor(theme.modebarColor), + }; + } + + static defaultTooltipConfig(theme: DashboardTheme) { + const font = { + ...theme.tooltipFont, + size: parseFloat(theme.tooltipFont.size) + }; + + return { + bgcolor: PlotlySetup.getRgbaColor(theme.tooltipBackground), + font: font, + }; + } + + static defaultLegendConfig(theme: DashboardTheme) { + const isMobile = window.innerWidth <= 600; + const legendSetting = theme.legendSetting; + const legendLabelFont = { + ...theme.legendLabelFont, + size: parseFloat(theme.legendLabelFont.size) + }; + + return { + yanchor: isMobile ? "top" : "auto", + orientation: isMobile ? "h" : "v", + bordercolor: legendSetting.borderColor, + borderwidth: legendSetting.borderWidth, + itemwidth: 20, + font: legendLabelFont + }; + } + + static defaultAxisConfig(theme: DashboardTheme) { + const axisLabelFont = { + ...theme.axisLabelFont, + size: parseFloat(theme.axisLabelFont.size) + }; + if(axisLabelFont.size === undefined || isNaN(axisLabelFont.size)) { + delete axisLabelFont.size; + } + if(!theme.isAxisLabelFontLoaded()) { + delete axisLabelFont.family; + } + + return { + zerolinecolor: PlotlySetup.getRgbaColor(theme.axisGridColor), + automargin: true, + tickfont: axisLabelFont + }; + } + + static defaultInsideLabelFont(theme: DashboardTheme) { + const insideLabelFont = { + ...theme.insideLabelFont, + size: parseFloat(theme.insideLabelFont.size) + }; + + return insideLabelFont; + } + + static defaultAxisXConfig(theme: DashboardTheme) { + return { + ...PlotlySetup.defaultAxisConfig(theme), + ticklabelstandoff: 8, + }; + } + + static defaultAxisXWithGridLineConfig (theme: DashboardTheme) { + return { + ...PlotlySetup.defaultAxisXConfig(theme), + gridcolor: PlotlySetup.getRgbaColor(theme.axisGridColor), + griddash: "dot", + }; + } + + static defaultAxisYConfig(theme: DashboardTheme) { + return { + ...PlotlySetup.defaultAxisConfig(theme), + ticklabelstandoff: 16, + }; + } + + static defaultAxisYWithGridLineConfig(theme: DashboardTheme) { + return { + ...PlotlySetup.defaultAxisYConfig(theme), + gridcolor: PlotlySetup.getRgbaColor(theme.axisGridColor), + griddash: "dot", + }; + } + + static defaultGaugeConfig(theme) { + return { + bgcolor: PlotlySetup.getRgbaColor(theme.gaugeBackground), + bordercolor: PlotlySetup.getRgbaColor(theme.gaugeBackground), + bar: { + color: PlotlySetup.getRgbaColor(theme.gaugeBarColor), + thickness: 0.5, + }, + }; + } + + static defaultValueGaugeFont(theme: DashboardTheme) { + const font = { + ...theme.gaugeValueFont, + size: parseFloat(theme.gaugeValueFont.size) + }; + + return font; + } + + static defaultGaugeTickFont(theme: DashboardTheme) { + const font = { + ...theme.gaugeTickFont, + size: parseFloat(theme.gaugeTickFont.size) + }; + + return font; + } + /** * Fires when end user clicks on the 'save as image' button. */ @@ -70,7 +226,7 @@ export class PlotlySetup { seriesLabels, } = answersData; - const hasSeries = seriesLabels.length > 1 || model.question.getType() === "matrix"; + const hasSeries = seriesLabels.length > 1 || model.dataType === "matrix"; const layoutColumns = 2; let traces: any = []; @@ -87,7 +243,9 @@ export class PlotlySetup { }), hoverinfo: "value+text", textposition: "inside", - texttemplate: "%{text}" + texttemplate: "%{text}", + insidetextfont: PlotlySetup.defaultInsideLabelFont(model.theme), + hoverlabel: PlotlySetup.defaultTooltipConfig(model.theme), }; if (model.chartType === "doughnut") { @@ -96,7 +254,7 @@ export class PlotlySetup { } if (!hasSeries) { - traceConfig.mode = "markers", + traceConfig.mode = "markers"; traceConfig.marker = { color: colors }; traceConfig.marker.symbol = "circle"; traceConfig.marker.size = 16; @@ -118,7 +276,11 @@ export class PlotlySetup { column: traces.length % layoutColumns, row: Math.floor(traces.length / layoutColumns), }, - title: { position: "bottom center", text: seriesLabels[index] } + title: { + position: "bottom center", + text: seriesLabels[index], + font: PlotlySetup.defaultTooltipConfig(model.theme), + } }) ); } @@ -128,23 +290,18 @@ export class PlotlySetup { const height = (radius + 25) * Math.ceil(traces.length / layoutColumns); const layout: any = { - font: { - family: "Segoe UI, sans-serif", - size: 14, - weight: "normal", - color: "#404040", - }, height: height, margin: { l: 0, t: 25, b: 0, - r: 10, + r: 0, }, + modebar: { ...PlotlySetup.defaultModebarConfig(model.theme) }, colorway: colors, hovermode: "closest", - plot_bgcolor: model.backgroundColor, - paper_bgcolor: model.backgroundColor, + plot_bgcolor: "transparent", + paper_bgcolor: "transparent", showlegend: false, }; @@ -169,7 +326,8 @@ export class PlotlySetup { valuesTitle } = answersData; - const hasSeries = seriesLabels.length > 1 || model.question.getType() === "matrix"; + const hasSeries = seriesLabels.length > 1 || model.dataType === "matrix"; + const isHistogram = model.type === "histogram"; const traces: any = []; const traceConfig: any = { @@ -178,12 +336,14 @@ export class PlotlySetup { customdata: labels, hoverinfo: "text", orientation: "h", - textposition: "none", + textposition: "inside", + textangle: 0, + insidetextanchor: "middle", + insidetextfont: PlotlySetup.defaultInsideLabelFont(model.theme), + hoverlabel: PlotlySetup.defaultTooltipConfig(model.theme), }; - if (!hasSeries) { - traceConfig.width = 0.5; - traceConfig.bargap = 0.5; - traceConfig.mode = "markers", + if (!hasSeries && !isHistogram) { + traceConfig.mode = "markers"; traceConfig.marker = { color: colors }; } @@ -193,7 +353,6 @@ export class PlotlySetup { const trace = Object.assign({}, traceConfig, { x: dataset, name: traceName, - width: hasSeries && model.chartType !== "stackedbar" ? 0.5 / seriesLabels.length : 0.5, text: texts[index], hovertext: labels.map((label: string, labelIndex: number) => { if(model.showOnlyPercentages) { @@ -205,10 +364,7 @@ export class PlotlySetup { }); if (model.showPercentages) { let texttemplate = model.showOnlyPercentages ? "%{text}%" : "%{value} (%{text}%)"; - trace.textposition = "inside"; trace.texttemplate = texttemplate; - trace.width = hasSeries && model.chartType !== "stackedbar" ? 0.7 / seriesLabels.length : 0.9; - trace.bargap = hasSeries && model.chartType !== "stackedbar" ? 0.3 / seriesLabels.length : 0.1; } traces.push(trace); }); @@ -216,30 +372,24 @@ export class PlotlySetup { const height = (labels.length + 1) * lineHeight + topMargin + bottomMargin; const layout: any = { - font: { - family: "Segoe UI, sans-serif", - size: 14, - weight: "normal", - color: "#404040", - }, + bargap: isHistogram ? 0 : PlotlySetup.defaultBarGap, height: height, margin: { t: topMargin, b: bottomMargin, - r: 10, + r: 0, + l: 0, }, colorway: colors, hovermode: "closest", - plot_bgcolor: model.backgroundColor, - paper_bgcolor: model.backgroundColor, showlegend: hasSeries, barmode: hasSeries && model.chartType == "stackedbar" ? "stack" : "group", xaxis: { + ...PlotlySetup.defaultAxisXWithGridLineConfig(model.theme), rangemode: "nonnegative", - automargin: true, }, yaxis: { - automargin: true, + ...PlotlySetup.defaultAxisYConfig(model.theme), type: "category", orientation: "h", tickmode: "array", @@ -251,8 +401,17 @@ export class PlotlySetup { ) + " "; }), }, + modebar: { ...PlotlySetup.defaultModebarConfig(model.theme) }, + plot_bgcolor: "transparent", + paper_bgcolor: "transparent", }; + if (hasSeries) { + layout.legend = PlotlySetup.defaultLegendConfig(model.theme); + if (model.chartType !== "stackedbar") { + layout.height = (labels.length * seriesLabels.length + 1) * lineHeight + topMargin + bottomMargin; + } + } if(labelsTitle) { layout.yaxis.title = { text: labelsTitle }; } @@ -260,22 +419,16 @@ export class PlotlySetup { layout.xaxis.title = { text: valuesTitle }; } - if (hasSeries && model.chartType !== "stackedbar") { - layout.height = - (labels.length * seriesLabels.length + 1) * lineHeight + - topMargin + - bottomMargin; - } - if(["ar", "fa"].indexOf(localization.currentLocale) !== -1) { layout.xaxis.autorange = "reversed"; layout.yaxis.side = "right"; - layout.legend = { + const legendSettings = Object.assign({}, PlotlySetup.defaultLegendConfig(model.theme), { x: 0, y: 1, xanchor: "left", yanchor: "top" - }; + }); + layout.legend = legendSettings; } return { traces, layout, hasSeries }; @@ -294,22 +447,11 @@ export class PlotlySetup { valuesTitle } = answersData; - const hasSeries = seriesLabels.length > 1 || model.question.getType() === "matrix"; + const hasSeries = seriesLabels.length > 1 || model.dataType === "matrix"; + const isHistogram = model.type === "histogram"; - if (model.type !== "histogram" && model.type !== "pivot") { - labels = [].concat(labels).reverse(); - seriesLabels = [].concat(seriesLabels).reverse(); - colors = [].concat(colors.slice(0, hasSeries ? seriesLabels.length : labels.length)).reverse(); - const ts = []; - texts.forEach(text => { - ts.push([].concat(text).reverse()); - }); - texts = ts; - const ds = []; - datasets.forEach(dataset => { - ds.push([].concat(dataset).reverse()); - }); - datasets = ds; + if (!isHistogram && model.type !== "pivot") { + ({ labels, seriesLabels, colors, texts, datasets } = reverseAll(labels, seriesLabels, colors, hasSeries, texts, datasets)); } const traces: any = []; @@ -319,12 +461,13 @@ export class PlotlySetup { customdata: hasSeries ? seriesLabels : labels, hoverinfo: hasSeries ? undefined : "x+y", orientation: "v", - textposition: "none", + insidetextanchor: "middle", + insidetextfont: PlotlySetup.defaultInsideLabelFont(model.theme), + hoverlabel: PlotlySetup.defaultTooltipConfig(model.theme), }; - if (!hasSeries) { - traceConfig.width = 0.5; - traceConfig.bargap = 0.5; - traceConfig.mode = "markers", + + if (!hasSeries && !isHistogram) { + traceConfig.mode = "markers"; traceConfig.marker = { color: colors }; } @@ -336,12 +479,7 @@ export class PlotlySetup { }); if (model.showPercentages) { let texttemplate = model.showOnlyPercentages ? "%{text}%" : "%{value} (%{text}%)"; - trace.textposition = "inside"; trace.texttemplate = texttemplate; - if (!hasSeries) { - trace.width = 0.9; - trace.bargap = 0.1; - } } traces.push(trace); }); @@ -350,27 +488,25 @@ export class PlotlySetup { const tickStep = Math.ceil(labels.length / maxTicks); const layout: any = { - font: { - family: "Segoe UI, sans-serif", - size: 14, - weight: "normal", - color: "#404040", - }, margin: { t: topMargin, b: bottomMargin, - r: 10, + r: 0, + l: 0, }, colorway: colors, hovermode: "closest", - plot_bgcolor: model.backgroundColor, - paper_bgcolor: model.backgroundColor, + plot_bgcolor: "transparent", + paper_bgcolor: "transparent", showlegend: hasSeries, + bargap: isHistogram ? 0 : PlotlySetup.defaultBarGap, yaxis: { + ...PlotlySetup.defaultAxisYWithGridLineConfig(model.theme), rangemode: "nonnegative", automargin: true, }, xaxis: { + ...PlotlySetup.defaultAxisXConfig(model.theme), automargin: true, type: "category", tickmode: "array", @@ -385,6 +521,7 @@ export class PlotlySetup { ); }), }, + modebar: { ...PlotlySetup.defaultModebarConfig(model.theme) }, }; if(labelsTitle) { @@ -396,7 +533,7 @@ export class PlotlySetup { if (model.showPercentages && model.showOnlyPercentages) { layout.yaxis = { - automargin: true, + ...PlotlySetup.defaultAxisYWithGridLineConfig(model.theme), tickformat: ".0%", range: [0, 1], ticklen: model.showOnlyPercentages ? 25 : 5, @@ -405,7 +542,7 @@ export class PlotlySetup { } if(!(model as any).getValueType || (model as any).getValueType() != "date") { layout.xaxis = { - automargin: true, + ...PlotlySetup.defaultAxisXConfig(model.theme), type: "category", }; } @@ -424,7 +561,7 @@ export class PlotlySetup { texts, seriesLabels, } = answersData; - const hasSeries = seriesLabels.length > 1 || model.question.getType() === "matrix"; + const hasSeries = seriesLabels.length > 1 || model.dataType === "matrix"; const traces: any = []; const traceConfig: any = { @@ -440,7 +577,6 @@ export class PlotlySetup { hoverinfo: "x+y", orientation: "h", mode: "markers", - width: 0.5, marker: {}, }; @@ -461,37 +597,34 @@ export class PlotlySetup { const height = (labels.length + 1) * lineHeight + topMargin + bottomMargin; const layout: any = { - font: { - family: "Segoe UI, sans-serif", - size: 14, - weight: "normal", - color: "#404040", - }, height: height, margin: { t: topMargin, b: bottomMargin, - r: 10, + r: 0, + l: 0, }, colorway: colors, hovermode: "closest", yaxis: { - automargin: true, + ...PlotlySetup.defaultAxisYConfig(model.theme), type: "category", ticklen: 5, tickcolor: "transparent", }, xaxis: { + ...PlotlySetup.defaultAxisXConfig(model.theme), rangemode: "nonnegative", - automargin: true, }, - plot_bgcolor: model.backgroundColor, - paper_bgcolor: model.backgroundColor, + modebar: { ...PlotlySetup.defaultModebarConfig(model.theme) }, + plot_bgcolor: "transparent", + paper_bgcolor: "transparent", showlegend: false, }; if (hasSeries) { layout.showlegend = true; + layout.legend = PlotlySetup.defaultLegendConfig(model.theme); layout.height = undefined; labels.forEach((label, index) => { @@ -504,9 +637,11 @@ export class PlotlySetup { } static setupGauge(model: NumberModel, answersData: IAnswersData): PlotlyOptions { - let [level, minValue, maxValue] = answersData as any; + let value = answersData.datasets[0][answersData.values.indexOf(model.displayValueName || "value")]; + let minValue = answersData.datasets[0][answersData.values.indexOf("min")] || 0; + let maxValue = answersData.datasets[0][answersData.values.indexOf("max")] || value * 1.25; - if (model.question.getType() === "rating") { + if (model.dataType === "rating") { const rateValues = model.question.visibleRateValues; maxValue = rateValues[rateValues.length - 1].value; minValue = rateValues[0].value; @@ -519,7 +654,7 @@ export class PlotlySetup { ); if (NumberModel.showAsPercentage) { - level = DataHelper.toPercentage(level, maxValue); + value = DataHelper.toPercentage(value, maxValue); minValue = DataHelper.toPercentage(minValue, maxValue); maxValue = DataHelper.toPercentage(maxValue, maxValue); } @@ -529,20 +664,25 @@ export class PlotlySetup { type: "indicator", mode: "gauge+number", gauge: { - axis: { range: [minValue, maxValue] }, + ...PlotlySetup.defaultGaugeConfig(model.theme), + axis: { + range: [minValue, maxValue], + tickfont: { ...PlotlySetup.defaultGaugeTickFont(model.theme) } + }, shape: model.chartType, - bgcolor: "white", - bar: { color: colors[0] }, }, - value: level, + value: value, text: model.name, domain: { x: [0, 1], y: [0, 1] }, + number: { + font: { ...PlotlySetup.defaultValueGaugeFont(model.theme) } + }, }, ]; const chartMargin = model.chartType === "bullet" ? 60 : 30; var layout: any = { - height: 250, + height: model.chartType === "bullet" ? 150 : 250, margin: { l: chartMargin, r: chartMargin, @@ -550,8 +690,9 @@ export class PlotlySetup { t: chartMargin, pad: 5 }, - plot_bgcolor: model.backgroundColor, - paper_bgcolor: model.backgroundColor, + plot_bgcolor: "transparent", + paper_bgcolor: "transparent", + modebar: { ...PlotlySetup.defaultModebarConfig(model.theme) }, }; return { traces, layout, hasSeries: false }; @@ -565,7 +706,7 @@ export class PlotlySetup { texts, seriesLabels, } = answersData; - const hasSeries = seriesLabels.length > 1 || model.question.getType() === "matrix"; + const hasSeries = seriesLabels.length > 1 || model.dataType === "matrix"; const traces: any = []; const traceConfig: any = { @@ -604,43 +745,36 @@ export class PlotlySetup { }); const layout: any = { - font: { - family: "Segoe UI, sans-serif", - size: 14, - weight: "normal", - color: "#404040", - }, polar: { radialaxis: { + ...PlotlySetup.defaultAxisConfig(model.theme), visible: true, range: [0, Math.max(...datasets.map(s => Math.max(...s))) * 1.1], - tickfont: { - size: 12 - } + gridcolor: model.theme.axisGridColor, + linecolor: model.theme.axisBorderColor, + tickcolor: model.theme.axisBorderColor, + gridwidth: 1, }, angularaxis: { - tickfont: { - size: 12 - }, - ticktext: labels.map((label: string) => { - return PlotlySetup.getTruncatedLabel( - label, - model.labelTruncateLength - ); - }), - tickvals: labels + ...PlotlySetup.defaultAxisConfig(model.theme), + tickfont: model.theme.radarLabelFont, + linecolor: model.theme.axisGridColor, } }, showlegend: hasSeries, + legend: hasSeries ? PlotlySetup.defaultLegendConfig(model.theme) : undefined, colorway: colors, - plot_bgcolor: model.backgroundColor, - paper_bgcolor: model.backgroundColor, + plot_bgcolor: "transparent", + paper_bgcolor: "transparent", margin: { l: 50, r: 50, t: 50, b: 50 - } + }, + modebar: { ...PlotlySetup.defaultModebarConfig(model.theme) }, + hovermode: "closest", + hoverlabel: PlotlySetup.defaultTooltipConfig(model.theme), }; return { traces, layout, hasSeries }; diff --git a/src/ranking.ts b/src/ranking.ts index 099418744..769b77651 100644 --- a/src/ranking.ts +++ b/src/ranking.ts @@ -1,6 +1,7 @@ import { VisualizationManager } from "./visualizationManager"; import { SelectBase } from "./selectBase"; import { QuestionRankingModel } from "survey-core"; +import { ICalculationResult } from "./visualizerBase"; export class RankingModel extends SelectBase { @@ -8,9 +9,9 @@ export class RankingModel extends SelectBase { question: QuestionRankingModel, data: Array<{ [index: string]: any }>, options?: any, - name?: string + type?: string ) { - super(question, data, options, name || "ranking"); + super(question, data, options, type || "ranking"); } getQuestionResults() { @@ -28,17 +29,19 @@ export class RankingModel extends SelectBase { return data; } - protected getCalculatedValuesCore(): Array { + protected getCalculatedValuesCore(): ICalculationResult { const results = this.getQuestionResults(); - const choices = this.getValues(); - - let plotlyData = this.getEmptyData(); + const values = this.getValues(); + let calculatedData = this.getEmptyData(); results.forEach((result) => { - this.applyResultToPlotlyData(result, plotlyData, choices); + this.applyResultToPlotlyData(result, calculatedData, values); }); - return [plotlyData]; + return { + data: [calculatedData], + values + }; } applyResultToPlotlyData(result: any[], plotlyData: any, choices: any) { diff --git a/src/selectBase.ts b/src/selectBase.ts index d381b0398..86454afdd 100644 --- a/src/selectBase.ts +++ b/src/selectBase.ts @@ -1,8 +1,10 @@ import { Question, QuestionSelectBase, ItemValue, Event, QuestionRatingModel } from "survey-core"; -import { VisualizerBase } from "./visualizerBase"; +import { IAnswersData, ICalculationResult, VisualizerBase } from "./visualizerBase"; import { localization } from "./localizationManager"; import { DataHelper, DocumentHelper } from "./utils/index"; import { VisualizationManager } from "./visualizationManager"; +import { IDashboardTheme } from "./theme"; +import { ToggleWidget } from "./utils/toggle"; export interface IVisualizerWithSelection { selection: ItemValue; @@ -10,19 +12,10 @@ export interface IVisualizerWithSelection { setSelection(item: ItemValue): void; } -export interface IAnswersData { - datasets: Array>; - labels: Array; - colors: Array; - texts: Array>; - seriesLabels: Array; - labelsTitle?: string; - valuesTitle?: string; -} - export function hideEmptyAnswersInData(answersData: IAnswersData): IAnswersData { const result = { datasets: >[], + values: >[], labels: >[], colors: >[], texts: >[], @@ -35,6 +28,7 @@ export function hideEmptyAnswersInData(answersData: IAnswersData): IAnswersData if (answersData.datasets[0][i] != 0) { result.datasets[0].push(answersData.datasets[0][i]); result.labels.push(answersData.labels[i]); + result.values.push(answersData.values[i]); result.colors.push(answersData.colors[i]); result.texts[0].push(answersData.texts[0][i]); } @@ -56,6 +50,7 @@ export function hideEmptyAnswersInData(answersData: IAnswersData): IAnswersData for (var valueIndex = 0; valueIndex < valuesDataExistence.length; valueIndex++) { if (valuesDataExistence[valueIndex]) { result.labels.push(answersData.labels[valueIndex]); + result.values.push(answersData.values[valueIndex]); result.colors.push(answersData.colors[valueIndex]); } } @@ -106,9 +101,9 @@ export class SelectBase question: Question, data: Array<{ [index: string]: any }>, options?: any, - name?: string + type?: string ) { - super(question, data, options, name || "selectBase"); + super(question, data, options, type || "selectBase"); if (!!question) { // TODO: move somewhere else (question).visibleChoicesChangedCallback = () => { this.dataProvider.raiseDataChanged(); @@ -137,16 +132,20 @@ export class SelectBase if (this.getSeriesValues().length > 0 && this.chartTypes.indexOf("stackedbar") === -1) { this.chartTypes.push("stackedbar"); } + this._chartType = this.chartTypes[0]; if (this.chartTypes.indexOf(this.options.defaultChartType) !== -1) { this._chartType = this.options.defaultChartType; } + if (this.chartTypes.indexOf(this.questionOptions?.chartType) !== -1) { + this._chartType = this.questionOptions.chartType; + } } - if(this.options.allowChangeVisualizerType !== false) { + if(this.options.allowChangeVisualizerType !== false && !(this.questionOptions?.allowChangeVisualizerType === false)) { this.registerToolbarItem("changeChartType", () => { if (this.chartTypes.length > 1) { - return DocumentHelper.createSelector( + return DocumentHelper.createDropdown( this.chartTypes.map((chartType) => { return { value: chartType, @@ -155,44 +154,45 @@ export class SelectBase }), (option: any) => this.chartType === option.value, (e: any) => { - this.setChartType(e.target.value); + this.setChartType(e); } ); } return null; - }); + }, "dropdown"); } this.registerToolbarItem("changeAnswersOrder", () => { if (this.isSupportAnswersOrder()) { - this.choicesOrderSelector = DocumentHelper.createSelector( + this.choicesOrderSelector = DocumentHelper.createDropdown( [ { text: localization.getString("defaultOrder"), value: "default" }, { text: localization.getString("ascOrder"), value: "asc" }, { text: localization.getString("descOrder"), value: "desc" }, ], - (option) => false, + (option) => this.answersOrder === option.value, (e) => { - this.answersOrder = e.target.value; + this.answersOrder = e; } ); this.updateOrderSelector(); } return this.choicesOrderSelector; - }); + }, "dropdown"); this.registerToolbarItem("showPercentages", () => { if ( this.options.allowShowPercentages && (this.chartTypes.indexOf("bar") !== -1 || this.chartTypes.indexOf("stackedbar") !== -1) ) { - this.showPercentageBtn = DocumentHelper.createButton(() => { + const toggleWidget = new ToggleWidget(() => { this.showPercentages = !this.showPercentages; - }); + }, localization.getString("showPercentages"), this.showPercentages); + this.showPercentageBtn = toggleWidget.container; this.updateShowPercentageBtn(); return this.showPercentageBtn; } - }); + }, "button"); this.registerToolbarItem("hideEmptyAnswers", () => { if (this.options.allowHideEmptyAnswers) { this.emptyAnswersBtn = DocumentHelper.createButton(() => { @@ -201,28 +201,28 @@ export class SelectBase this.updateEmptyAnswersBtn(); } return this.emptyAnswersBtn; - }, 1000); + }, "button", 1000); this.registerToolbarItem("topNAnswers", () => { if ( this.options.allowTopNAnswers && this.getSeriesValues().length === 0 ) { - this.topNSelector = DocumentHelper.createSelector( + this.topNSelector = DocumentHelper.createDropdown( this.topNValues.map((value) => { return { text: localization.getString("topNValueText" + value), value: value, }; }), - (option) => false, + (option) => this.topN === option.value as any, (e) => { - this.topN = parseInt(e.target.value); + this.topN = parseInt(e); } ); this.updateTopNSelector(); } return this.topNSelector; - }); + }, "dropdown"); this.registerToolbarItem("transposeData", () => { if (this.options.allowTransposeData) { this.transposeDataBtn = DocumentHelper.createButton(() => { @@ -231,7 +231,7 @@ export class SelectBase this.updateTransposeDataBtn(); } return this.transposeDataBtn; - }); + }, "button"); this.registerToolbarItem("showMissingAnswers", () => { if (this.isSupportMissingAnswers() && this.options.allowShowMissingAnswers) { this.missingAnswersBtn = DocumentHelper.createButton(() => { @@ -240,7 +240,7 @@ export class SelectBase this.updateMissingAnswersBtn(); } return this.missingAnswersBtn; - }); + }, "button"); } protected chartTypes: string[] = []; @@ -257,9 +257,7 @@ export class SelectBase private updateEmptyAnswersBtn() { if (!!this.emptyAnswersBtn) { - this.emptyAnswersBtn.innerText = this._hideEmptyAnswers - ? localization.getString("showEmptyAnswers") - : localization.getString("hideEmptyAnswers"); + (this.emptyAnswersBtn as any).setText(localization.getString(this._hideEmptyAnswers ? "showEmptyAnswers" : "hideEmptyAnswers")); if (this.chartType == "bar" || this.chartType == "vbar" || this.chartType == "line" || this.chartType == "scatter") { this.emptyAnswersBtn.style.display = "inline"; } else { @@ -270,9 +268,7 @@ export class SelectBase private updateTransposeDataBtn() { if (!!this.transposeDataBtn) { - this.transposeDataBtn.innerText = this.transposeData - ? localization.getString("showPerColumns") - : localization.getString("showPerValues"); + (this.transposeDataBtn as any).setText(localization.getString(this.transposeData ? "showPerColumns" : "showPerValues")); if (this.getSeriesValues().length > 0) { this.transposeDataBtn.style.display = "inline"; } else { @@ -295,19 +291,15 @@ export class SelectBase } else { this.choicesOrderSelector.style.display = "none"; } - this.choicesOrderSelector.getElementsByTagName( - "select" - )[0].value = this.answersOrder; + (this.choicesOrderSelector as any).setValue(this.answersOrder); } } private updateShowPercentageBtn() { if (!!this.showPercentageBtn) { - this.showPercentageBtn.innerText = this._showPercentages - ? localization.getString("hidePercentages") - : localization.getString("showPercentages"); + // (this.showPercentageBtn as any).setText(localization.getString(this._showPercentages ? "hidePercentages" : "showPercentages")); if (this.chartType == "bar" || this.chartType == "vbar" || this.chartType == "stackedbar") { - this.showPercentageBtn.style.display = "inline"; + this.showPercentageBtn.style.display = undefined; } else { this.showPercentageBtn.style.display = "none"; } @@ -316,17 +308,13 @@ export class SelectBase private updateTopNSelector() { if (!!this.topNSelector) { - this.topNSelector.getElementsByTagName("select")[0].value = ( - this._topN - ); + (this.topNSelector as any).setValue(this._topN); } } private updateMissingAnswersBtn() { if (!!this.missingAnswersBtn) { - this.missingAnswersBtn.innerText = this._showMissingAnswers - ? localization.getString("hideMissingAnswers") - : localization.getString("showMissingAnswers"); + (this.missingAnswersBtn as any).setText(localization.getString(this._showMissingAnswers ? "hideMissingAnswers" : "showMissingAnswers")); } } @@ -422,6 +410,10 @@ export class SelectBase return this.options.showPercentages === true; } + public get percentagePrecision(): number { + return this._percentagePrecision; + } + /** * Gets and sets whether chart should show values and percentages. */ @@ -585,6 +577,8 @@ export class SelectBase } getPercentages(data: Array>): Array> { + if(!data || !Array.isArray(data)) return []; + var percentages: Array> = []; var percentagePrecision = this._percentagePrecision; @@ -626,23 +620,24 @@ export class SelectBase */ public async getAnswersData(): Promise { let seriesLabels = this.getSeriesLabels(); - let datasets = (await this.getCalculatedValues()) as number[][]; + let datasets = (await this.getCalculatedValues()).data; + let values = this.getValues(); let labels = this.getLabels(); - let colors = this.getColors(); - + let colors = VisualizerBase.getColors(); if (this.transposeData) { datasets = this.transpose(datasets); const temp = seriesLabels; seriesLabels = labels; labels = temp; + values = this.getSeriesValues(); } var texts = this.showPercentages ? this.getPercentages(datasets) : datasets; if (this.answersOrder == "asc" || this.answersOrder == "desc") { var zippedArray = this.showPercentages - ? DataHelper.zipArrays(labels, colors, texts[0]) - : DataHelper.zipArrays(labels, colors); + ? DataHelper.zipArrays(labels, colors, values, texts[0]) + : DataHelper.zipArrays(labels, colors, values); let dict = DataHelper.sortDictionary( zippedArray, datasets[0], @@ -651,12 +646,14 @@ export class SelectBase let unzippedArray = DataHelper.unzipArrays(dict.keys); labels = unzippedArray[0]; colors = unzippedArray[1]; - if (this.showPercentages) texts[0] = unzippedArray[2]; + values = unzippedArray[2]; + if (this.showPercentages) texts[0] = unzippedArray[3]; datasets[0] = dict.values; } let answersData = { datasets, + values, labels, colors, texts, @@ -677,7 +674,7 @@ export class SelectBase return answersData; } - public convertFromExternalData(externalCalculatedData: any): any[] { + public convertFromExternalData(externalCalculatedData: any): ICalculationResult { const values = this.getValues(); const series = this.getSeriesValues(); const innerCalculatedData = []; @@ -700,7 +697,11 @@ export class SelectBase } innerCalculatedData.push(seriesData); } - return innerCalculatedData; + return { + data: innerCalculatedData, + values, + series + }; } protected transpose(data: Array>): Array> { @@ -736,6 +737,7 @@ export class SelectBase const selectedItem = ItemValue.getItemByValue((this.question as QuestionSelectBase).visibleChoices, state.filter); this.setSelection(selectedItem ?? undefined); } + public resetState(): void { super.resetState(); // this._showPercentages = this.options.showPercentages === true; @@ -745,9 +747,14 @@ export class SelectBase this._hideEmptyAnswers = this.options.hideEmptyAnswers === true; this._answersOrder = this.options.answersOrder || "default"; this._topN = -1; - this.chartType = this.chartTypes[0]; + this.chartType = this.questionOptions?.chartType || this.chartTypes[0]; this.setSelection(undefined); } + + protected onThemeChanged(): void { + super.onThemeChanged(); + this.refreshContent(); + } } VisualizationManager.registerVisualizer("checkbox", SelectBase); diff --git a/src/sjs-design-tokens/default-dark.ts b/src/sjs-design-tokens/default-dark.ts new file mode 100644 index 000000000..d9554cbc6 --- /dev/null +++ b/src/sjs-design-tokens/default-dark.ts @@ -0,0 +1,726 @@ +// Auto-generated theme: default-dark +export const DefaultDark = { + "themeName": "default-dark", + "iconSet": "v2", + "isLight": false, + "cssVariables": { + "--sjs2-base-unit-size": "8px", + "--sjs2-base-unit-spacing": "8px", + "--sjs2-base-unit-radius": "8px", + "--sjs2-base-unit-border-width": "1px", + "--sjs2-base-unit-font-size": "8px", + "--sjs2-base-unit-line-height": "8px", + "--sjs2-base-unit-opacity": "1%", + "--sjs2-base-unit-scale": "1%", + "--sjs2-scale-x000": "calc(var(--sjs2-base-unit-scale) * 0)", + "--sjs2-scale-x025": "calc(var(--sjs2-base-unit-scale) * 25)", + "--sjs2-scale-x050": "calc(var(--sjs2-base-unit-scale) * 50)", + "--sjs2-scale-x075": "calc(var(--sjs2-base-unit-scale) * 75)", + "--sjs2-scale-x095": "calc(var(--sjs2-base-unit-scale) * 95)", + "--sjs2-scale-x100": "calc(var(--sjs2-base-unit-scale) * 100)", + "--sjs2-scale-x200": "calc(var(--sjs2-base-unit-scale) * 200)", + "--sjs2-size-x000": "calc(var(--sjs2-base-unit-size) * 0)", + "--sjs2-size-x025": "calc(var(--sjs2-base-unit-size) * 0.25)", + "--sjs2-size-x050": "calc(var(--sjs2-base-unit-size) * 0.50)", + "--sjs2-size-x075": "calc(var(--sjs2-base-unit-size) * 0.75)", + "--sjs2-size-x100": "calc(var(--sjs2-base-unit-size) * 1)", + "--sjs2-size-x150": "calc(var(--sjs2-base-unit-size) * 1.50)", + "--sjs2-size-x200": "calc(var(--sjs2-base-unit-size) * 2)", + "--sjs2-size-x250": "calc(var(--sjs2-base-unit-size) * 2.50)", + "--sjs2-size-x300": "calc(var(--sjs2-base-unit-size) * 3)", + "--sjs2-size-x350": "calc(var(--sjs2-base-unit-size) * 3.50)", + "--sjs2-size-x400": "calc(var(--sjs2-base-unit-size) * 4)", + "--sjs2-size-x500": "calc(var(--sjs2-base-unit-size) * 5)", + "--sjs2-size-x600": "calc(var(--sjs2-base-unit-size) * 6)", + "--sjs2-size-x700": "calc(var(--sjs2-base-unit-size) * 7)", + "--sjs2-size-x800": "calc(var(--sjs2-base-unit-size) * 8)", + "--sjs2-size-x900": "calc(var(--sjs2-base-unit-size) * 9)", + "--sjs2-size-x1000": "calc(var(--sjs2-base-unit-size) * 10)", + "--sjs2-size-x1100": "calc(var(--sjs2-base-unit-size) * 11)", + "--sjs2-size-x1200": "calc(var(--sjs2-base-unit-size) * 12)", + "--sjs2-size-x1300": "calc(var(--sjs2-base-unit-size) * 13)", + "--sjs2-size-x1400": "calc(var(--sjs2-base-unit-size) * 14)", + "--sjs2-size-x1500": "calc(var(--sjs2-base-unit-size) * 15)", + "--sjs2-radius-x000": "calc(var(--sjs2-base-unit-radius) * 0)", + "--sjs2-radius-x025": "calc(var(--sjs2-base-unit-radius) * 0.25)", + "--sjs2-radius-x050": "calc(var(--sjs2-base-unit-radius) * 0.50)", + "--sjs2-radius-x075": "calc(var(--sjs2-base-unit-radius) * 0.75)", + "--sjs2-radius-x100": "calc(var(--sjs2-base-unit-radius) * 1)", + "--sjs2-radius-x150": "calc(var(--sjs2-base-unit-radius) * 1.50)", + "--sjs2-radius-x200": "calc(var(--sjs2-base-unit-radius) * 2)", + "--sjs2-radius-x250": "calc(var(--sjs2-base-unit-radius) * 2.50)", + "--sjs2-radius-x300": "calc(var(--sjs2-base-unit-radius) * 3)", + "--sjs2-radius-x400": "calc(var(--sjs2-base-unit-radius) * 4)", + "--sjs2-radius-x500": "calc(var(--sjs2-base-unit-radius) * 5)", + "--sjs2-radius-x600": "calc(var(--sjs2-base-unit-radius) * 6)", + "--sjs2-radius-x700": "calc(var(--sjs2-base-unit-radius) * 7)", + "--sjs2-radius-x800": "calc(var(--sjs2-base-unit-radius) * 8)", + "--sjs2-radius-round": "9999px", + "--sjs2-spacing-x000": "calc(var(--sjs2-base-unit-spacing) * 0)", + "--sjs2-spacing-x025": "calc(var(--sjs2-base-unit-spacing) * 0.25)", + "--sjs2-spacing-x050": "calc(var(--sjs2-base-unit-spacing) * 0.50)", + "--sjs2-spacing-x075": "calc(var(--sjs2-base-unit-spacing) * 0.75)", + "--sjs2-spacing-x100": "calc(var(--sjs2-base-unit-spacing) * 1)", + "--sjs2-spacing-x150": "calc(var(--sjs2-base-unit-spacing) * 1.5)", + "--sjs2-spacing-x200": "calc(var(--sjs2-base-unit-spacing) * 2)", + "--sjs2-spacing-x250": "calc(var(--sjs2-base-unit-spacing) * 2.50)", + "--sjs2-spacing-x300": "calc(var(--sjs2-base-unit-spacing) * 3)", + "--sjs2-spacing-x400": "calc(var(--sjs2-base-unit-spacing) * 4)", + "--sjs2-spacing-x500": "calc(var(--sjs2-base-unit-spacing) * 5)", + "--sjs2-spacing-x600": "calc(var(--sjs2-base-unit-spacing) * 6)", + "--sjs2-spacing-x700": "calc(var(--sjs2-base-unit-spacing) * 7)", + "--sjs2-spacing-x800": "calc(var(--sjs2-base-unit-spacing) * 8)", + "--sjs2-spacing-negative-x025": "calc(var(--sjs2-base-unit-spacing) * -0.25)", + "--sjs2-spacing-negative-x050": "calc(var(--sjs2-base-unit-spacing) * -0.50)", + "--sjs2-spacing-negative-x075": "calc(var(--sjs2-base-unit-spacing) * -0.75)", + "--sjs2-spacing-negative-x100": "calc(var(--sjs2-base-unit-spacing) * -1)", + "--sjs2-spacing-negative-x150": "calc(var(--sjs2-base-unit-spacing) * -1.5)", + "--sjs2-spacing-negative-x200": "calc(var(--sjs2-base-unit-spacing) * -2)", + "--sjs2-spacing-negative-x250": "calc(var(--sjs2-base-unit-spacing) * -2.50)", + "--sjs2-spacing-negative-x300": "calc(var(--sjs2-base-unit-spacing) * -3)", + "--sjs2-spacing-negative-x400": "calc(var(--sjs2-base-unit-spacing) * -4)", + "--sjs2-spacing-negative-x500": "calc(var(--sjs2-base-unit-spacing) * -5)", + "--sjs2-spacing-negative-x600": "calc(var(--sjs2-base-unit-spacing) * -6)", + "--sjs2-spacing-negative-x700": "calc(var(--sjs2-base-unit-spacing) * -7)", + "--sjs2-spacing-negative-x800": "calc(var(--sjs2-base-unit-spacing) * -8)", + "--sjs2-opacity-x000": "calc(var(--sjs2-base-unit-opacity) * 0)", + "--sjs2-opacity-x005": "calc(var(--sjs2-base-unit-opacity) * 5)", + "--sjs2-opacity-x010": "calc(var(--sjs2-base-unit-opacity) * 10)", + "--sjs2-opacity-x015": "calc(var(--sjs2-base-unit-opacity) * 15)", + "--sjs2-opacity-x020": "calc(var(--sjs2-base-unit-opacity) * 20)", + "--sjs2-opacity-x025": "calc(var(--sjs2-base-unit-opacity) * 25)", + "--sjs2-opacity-x030": "calc(var(--sjs2-base-unit-opacity) * 30)", + "--sjs2-opacity-x035": "calc(var(--sjs2-base-unit-opacity) * 35)", + "--sjs2-opacity-x040": "calc(var(--sjs2-base-unit-opacity) * 40)", + "--sjs2-opacity-x045": "calc(var(--sjs2-base-unit-opacity) * 45)", + "--sjs2-opacity-x050": "calc(var(--sjs2-base-unit-opacity) * 50)", + "--sjs2-opacity-x055": "calc(var(--sjs2-base-unit-opacity) * 55)", + "--sjs2-opacity-x060": "calc(var(--sjs2-base-unit-opacity) * 60)", + "--sjs2-opacity-x065": "calc(var(--sjs2-base-unit-opacity) * 65)", + "--sjs2-opacity-x070": "calc(var(--sjs2-base-unit-opacity) * 70)", + "--sjs2-opacity-x075": "calc(var(--sjs2-base-unit-opacity) * 75)", + "--sjs2-opacity-x080": "calc(var(--sjs2-base-unit-opacity) * 80)", + "--sjs2-opacity-x085": "calc(var(--sjs2-base-unit-opacity) * 85)", + "--sjs2-opacity-x090": "calc(var(--sjs2-base-unit-opacity) * 90)", + "--sjs2-opacity-x095": "calc(var(--sjs2-base-unit-opacity) * 95)", + "--sjs2-opacity-x100": "calc(var(--sjs2-base-unit-opacity) * 100)", + "--sjs2-border-width-x000": "calc(var(--sjs2-base-unit-border-width) * 0)", + "--sjs2-border-width-x100": "calc(var(--sjs2-base-unit-border-width) * 1)", + "--sjs2-border-width-x200": "calc(var(--sjs2-base-unit-border-width) * 2)", + "--sjs2-border-width-x400": "calc(var(--sjs2-base-unit-border-width) * 4)", + "--sjs2-font-weight-regular": "Regular", + "--sjs2-font-weight-medium": "Medium", + "--sjs2-font-weight-semibold": "SemiBold", + "--sjs2-font-weight-bold": "Bold", + "--sjs2-font-size-x000": "calc(var(--sjs2-base-unit-font-size) * 0)", + "--sjs2-font-size-x100": "calc(var(--sjs2-base-unit-font-size) * 1)", + "--sjs2-font-size-x150": "calc(var(--sjs2-base-unit-font-size) * 1.5)", + "--sjs2-font-size-x200": "calc(var(--sjs2-base-unit-font-size) * 2)", + "--sjs2-font-size-x250": "calc(var(--sjs2-base-unit-font-size) * 2.5)", + "--sjs2-font-size-x300": "calc(var(--sjs2-base-unit-font-size) * 3)", + "--sjs2-font-size-x350": "calc(var(--sjs2-base-unit-font-size) * 3.5)", + "--sjs2-font-size-x400": "calc(var(--sjs2-base-unit-font-size) * 4)", + "--sjs2-font-size-x500": "calc(var(--sjs2-base-unit-font-size) * 5)", + "--sjs2-font-size-x600": "calc(var(--sjs2-base-unit-font-size) * 6)", + "--sjs2-line-height-x000": "calc(var(--sjs2-base-unit-line-height) * 0)", + "--sjs2-line-height-x100": "calc(var(--sjs2-base-unit-line-height) * 1)", + "--sjs2-line-height-x200": "calc(var(--sjs2-base-unit-line-height) * 2)", + "--sjs2-line-height-x300": "calc(var(--sjs2-base-unit-line-height) * 3)", + "--sjs2-line-height-x400": "calc(var(--sjs2-base-unit-line-height) * 4)", + "--sjs2-line-height-x500": "calc(var(--sjs2-base-unit-line-height) * 5)", + "--sjs2-line-height-x600": "calc(var(--sjs2-base-unit-line-height) * 6)", + "--sjs2-text-case-default": "none", + "--sjs2-text-case-uppercase": "uppercase", + "--sjs2-palette-gray-100": "#F5F5F5", + "--sjs2-palette-gray-150": "#EDEDED", + "--sjs2-palette-gray-200": "#E5E5E5", + "--sjs2-palette-gray-250": "#D4D4D4", + "--sjs2-palette-gray-300": "#CDCDCD", + "--sjs2-palette-gray-400": "#B3B2B2", + "--sjs2-palette-gray-500": "#8E8E8E", + "--sjs2-palette-gray-600": "#5F5E61", + "--sjs2-palette-gray-700": "#424146", + "--sjs2-palette-gray-750": "#36353C", + "--sjs2-palette-gray-800": "#2D2C33", + "--sjs2-palette-gray-900": "#1C1B20", + "--sjs2-palette-gray-950": "#161519", + "--sjs2-palette-gray-999": "#111014", + "--sjs2-palette-gray-000": "#fff", + "--sjs2-palette-red-400": "#ff6e84", + "--sjs2-palette-red-600": "#E50A3E", + "--sjs2-palette-red-700": "#C30935", + "--sjs2-palette-green-400": "#15CDAB", + "--sjs2-palette-green-600": "#19B394", + "--sjs2-palette-green-700": "#15947A", + "--sjs2-palette-blue-400": "#66B4FC", + "--sjs2-palette-blue-600": "#437FD9", + "--sjs2-palette-blue-700": "#2A6CD0", + "--sjs2-palette-yellow-400": "#FEC64A", + "--sjs2-palette-yellow-600": "#FF9814", + "--sjs2-palette-yellow-700": "#F08700", + "--sjs2-palette-violet-400": "#C36FF4", + "--sjs2-palette-violet-600": "#A62CEC", + "--sjs2-palette-violet-700": "#9614E1", + "--sjs2-palette-olive-400": "#6FC648", + "--sjs2-palette-olive-600": "#4FAF24", + "--sjs2-palette-olive-700": "#41901E", + "--sjs2-palette-purple-400": "#A190FA", + "--sjs2-palette-purple-600": "#6E5BD1", + "--sjs2-palette-purple-700": "#5640C9", + "--sjs2-palette-indianred-400": "#F9786A", + "--sjs2-palette-indianred-600": "#AF496B", + "--sjs2-palette-indianred-700": "#973F5C", + "--sjs2-radius-semantic-form": "var(--sjs2-radius-x100)", + "--sjs2-radius-semantic-form-item": "var(--sjs2-radius-x050)", + "--sjs2-radius-control-action": "var(--sjs2-radius-semantic-form)", + "--sjs2-radius-control-action-icon": "var(--sjs2-radius-semantic-form)", + "--sjs2-radius-control-button": "var(--sjs2-radius-semantic-form)", + "--sjs2-radius-control-menu-item": "var(--sjs2-radius-semantic-form)", + "--sjs2-radius-control-drop-item": "var(--sjs2-radius-x100)", + "--sjs2-radius-control-checkbox": "var(--sjs2-radius-semantic-form-item)", + "--sjs2-radius-control-rating": "var(--sjs2-radius-round)", + "--sjs2-radius-control-ranking": "var(--sjs2-radius-round)", + "--sjs2-radius-control-boolean": "var(--sjs2-radius-round)", + "--sjs2-radius-control-boolean-item": "var(--sjs2-radius-round)", + "--sjs2-radius-control-toggle": "var(--sjs2-radius-round)", + "--sjs2-radius-control-toggle-thumb": "var(--sjs2-radius-round)", + "--sjs2-radius-control-track": "var(--sjs2-radius-round)", + "--sjs2-radius-control-track-item": "var(--sjs2-radius-round)", + "--sjs2-radius-control-track-thumb": "var(--sjs2-radius-round)", + "--sjs2-radius-container-panel": "var(--sjs2-radius-x150)", + "--sjs2-radius-container-panel-nested": "var(--sjs2-radius-x100)", + "--sjs2-radius-container-menu": "var(--sjs2-radius-x250)", + "--sjs2-radius-container-drop": "var(--sjs2-radius-x200)", + "--sjs2-radius-container-modal": "var(--sjs2-radius-x300)", + "--sjs2-radius-container-notifier": "var(--sjs2-radius-x200)", + "--sjs2-radius-container-tooltip": "var(--sjs2-radius-x050)", + "--sjs2-radius-container-drag": "var(--sjs2-radius-semantic-form)", + "--sjs2-layout-control-formbox-small-horizontal": "var(--sjs2-spacing-x050)", + "--sjs2-layout-control-formbox-small-vertical": "var(--sjs2-spacing-x050)", + "--sjs2-layout-control-formbox-small-gap": "var(--sjs2-spacing-x050)", + "--sjs2-layout-control-formbox-medium-horizontal": "var(--sjs2-spacing-x050)", + "--sjs2-layout-control-formbox-medium-vertical": "var(--sjs2-spacing-x050)", + "--sjs2-layout-control-formbox-medium-gap": "var(--sjs2-spacing-x050)", + "--sjs2-layout-control-message-small-spacer": "var(--sjs2-spacing-x100)", + "--sjs2-layout-control-message-small-horizontal": "var(--sjs2-spacing-x150)", + "--sjs2-layout-control-message-small-vertical": "var(--sjs2-spacing-x100)", + "--sjs2-layout-control-message-small-gap": "var(--sjs2-spacing-x100)", + "--sjs2-layout-control-message-medium-spacer": "var(--sjs2-spacing-x100)", + "--sjs2-layout-control-message-medium-horizontal": "var(--sjs2-spacing-x150)", + "--sjs2-layout-control-message-medium-vertical": "var(--sjs2-spacing-x100)", + "--sjs2-layout-control-message-medium-gap": "var(--sjs2-spacing-x100)", + "--sjs2-layout-control-input-small-content-vertical": "var(--sjs2-spacing-x050)", + "--sjs2-layout-control-input-small-content-horizontal": "var(--sjs2-spacing-x100)", + "--sjs2-layout-control-input-small-swatch-vertical": "var(--sjs2-spacing-x050)", + "--sjs2-layout-control-input-small-swatch-left": "var(--sjs2-spacing-x100)", + "--sjs2-layout-control-input-small-swatch-right": "var(--sjs2-spacing-x000)", + "--sjs2-layout-control-input-small-icon-vertical": "var(--sjs2-spacing-x050)", + "--sjs2-layout-control-input-small-icon-left": "var(--sjs2-spacing-x050)", + "--sjs2-layout-control-input-small-icon-right": "var(--sjs2-spacing-x000)", + "--sjs2-layout-control-input-small-label-vertical": "var(--sjs2-spacing-x050)", + "--sjs2-layout-control-input-small-label-horizontal": "var(--sjs2-spacing-x100)", + "--sjs2-layout-control-input-small-group-gap": "var(--sjs2-spacing-x050)", + "--sjs2-layout-control-input-small-limit-vertical": "var(--sjs2-spacing-x100)", + "--sjs2-layout-control-input-small-limit-left": "var(--sjs2-spacing-x100)", + "--sjs2-layout-control-input-small-limit-right": "var(--sjs2-spacing-x100)", + "--sjs2-layout-control-input-medium-content-vertical": "var(--sjs2-spacing-x100)", + "--sjs2-layout-control-input-medium-content-horizontal": "var(--sjs2-spacing-x150)", + "--sjs2-layout-control-input-medium-swatch-vertical": "var(--sjs2-spacing-x100)", + "--sjs2-layout-control-input-medium-swatch-left": "var(--sjs2-spacing-x150)", + "--sjs2-layout-control-input-medium-swatch-right": "var(--sjs2-spacing-x000)", + "--sjs2-layout-control-input-medium-icon-vertical": "var(--sjs2-spacing-x100)", + "--sjs2-layout-control-input-medium-icon-left": "var(--sjs2-spacing-x100)", + "--sjs2-layout-control-input-medium-icon-right": "var(--sjs2-spacing-x000)", + "--sjs2-layout-control-input-medium-label-vertical": "var(--sjs2-spacing-x100)", + "--sjs2-layout-control-input-medium-label-horizontal": "var(--sjs2-spacing-x150)", + "--sjs2-layout-control-input-medium-group-gap": "var(--sjs2-spacing-x050)", + "--sjs2-layout-control-input-medium-limit-vertical": "var(--sjs2-spacing-x150)", + "--sjs2-layout-control-input-medium-limit-left": "var(--sjs2-spacing-x100)", + "--sjs2-layout-control-input-medium-limit-right": "var(--sjs2-spacing-x100)", + "--sjs2-layout-control-action-xx-small-label-vertical": "var(--sjs2-spacing-x000)", + "--sjs2-layout-control-action-xx-small-label-horizontal": "var(--sjs2-spacing-x050)", + "--sjs2-layout-control-action-xx-small-icon-vertical": "var(--sjs2-spacing-x000)", + "--sjs2-layout-control-action-xx-small-icon-horizontal": "var(--sjs2-spacing-x000)", + "--sjs2-layout-control-action-xx-small-box-vertical": "var(--sjs2-spacing-x050)", + "--sjs2-layout-control-action-xx-small-box-horizontal": "var(--sjs2-spacing-x050)", + "--sjs2-layout-control-action-xx-small-box-gap": "var(--sjs2-spacing-x000)", + "--sjs2-layout-control-action-xx-small-addon-vertical": "var(--sjs2-spacing-x000)", + "--sjs2-layout-control-action-xx-small-addon-horizontal": "var(--sjs2-spacing-x000)", + "--sjs2-layout-control-action-x-small-label-horizontal": "var(--sjs2-spacing-x050)", + "--sjs2-layout-control-action-x-small-label-vertical": "var(--sjs2-spacing-x050)", + "--sjs2-layout-control-action-x-small-icon-vertical": "var(--sjs2-spacing-x050)", + "--sjs2-layout-control-action-x-small-icon-horizontal": "var(--sjs2-spacing-x050)", + "--sjs2-layout-control-action-x-small-box-vertical": "var(--sjs2-spacing-x050)", + "--sjs2-layout-control-action-x-small-box-horizontal": "var(--sjs2-spacing-x050)", + "--sjs2-layout-control-action-x-small-box-gap": "var(--sjs2-spacing-x000)", + "--sjs2-layout-control-action-x-small-addon-vertical": "var(--sjs2-spacing-x050)", + "--sjs2-layout-control-action-x-small-addon-horizontal": "var(--sjs2-spacing-x050)", + "--sjs2-layout-control-action-small-label-horizontal": "var(--sjs2-spacing-x075)", + "--sjs2-layout-control-action-small-label-vertical": "var(--sjs2-spacing-x000)", + "--sjs2-layout-control-action-small-icon-vertical": "var(--sjs2-spacing-x000)", + "--sjs2-layout-control-action-small-icon-horizontal": "var(--sjs2-spacing-x000)", + "--sjs2-layout-control-action-small-box-vertical": "var(--sjs2-spacing-x100)", + "--sjs2-layout-control-action-small-box-horizontal": "var(--sjs2-spacing-x100)", + "--sjs2-layout-control-action-small-box-gap": "var(--sjs2-spacing-x000)", + "--sjs2-layout-control-action-small-addon-vertical": "var(--sjs2-spacing-x050)", + "--sjs2-layout-control-action-small-addon-horizontal": "var(--sjs2-spacing-x050)", + "--sjs2-layout-control-action-medium-label-horizontal": "var(--sjs2-spacing-x100)", + "--sjs2-layout-control-action-medium-label-vertical": "var(--sjs2-spacing-x000)", + "--sjs2-layout-control-action-medium-icon-vertical": "var(--sjs2-spacing-x000)", + "--sjs2-layout-control-action-medium-icon-horizontal": "var(--sjs2-spacing-x000)", + "--sjs2-layout-control-action-medium-box-vertical": "var(--sjs2-spacing-x150)", + "--sjs2-layout-control-action-medium-box-horizontal": "var(--sjs2-spacing-x150)", + "--sjs2-layout-control-action-medium-box-gap": "var(--sjs2-spacing-x000)", + "--sjs2-layout-control-action-medium-addon-vertical": "var(--sjs2-spacing-x050)", + "--sjs2-layout-control-action-medium-addon-horizontal": "var(--sjs2-spacing-x050)", + "--sjs2-layout-control-action-large-label-horizontal": "var(--sjs2-spacing-x150)", + "--sjs2-layout-control-action-large-label-vertical": "var(--sjs2-spacing-x000)", + "--sjs2-layout-control-action-large-icon-vertical": "var(--sjs2-spacing-x000)", + "--sjs2-layout-control-action-large-icon-horizontal": "var(--sjs2-spacing-x000)", + "--sjs2-layout-control-action-large-box-vertical": "var(--sjs2-spacing-x200)", + "--sjs2-layout-control-action-large-box-horizontal": "var(--sjs2-spacing-x200)", + "--sjs2-layout-control-action-large-box-gap": "var(--sjs2-spacing-x000)", + "--sjs2-layout-control-action-large-addon-vertical": "var(--sjs2-spacing-x050)", + "--sjs2-layout-control-action-large-addon-horizontal": "var(--sjs2-spacing-x050)", + "--sjs2-layout-control-caption-small-box-left": "var(--sjs2-spacing-x000)", + "--sjs2-layout-control-caption-small-box-right": "var(--sjs2-spacing-x050)", + "--sjs2-layout-control-caption-small-box-vertical": "var(--sjs2-spacing-x000)", + "--sjs2-layout-control-caption-small-box-gap": "var(--sjs2-spacing-x050)", + "--sjs2-layout-control-caption-small-group-gap": "var(--sjs2-spacing-x000)", + "--sjs2-layout-control-caption-small-description-horizontal": "var(--sjs2-spacing-x000)", + "--sjs2-layout-control-caption-small-description-top": "var(--sjs2-spacing-x000)", + "--sjs2-layout-control-caption-small-description-bottom": "var(--sjs2-spacing-x200)", + "--sjs2-layout-control-caption-small-caption-horizontal": "var(--sjs2-spacing-x000)", + "--sjs2-layout-control-caption-small-caption-vertical": "var(--sjs2-spacing-x100)", + "--sjs2-layout-control-caption-medium-box-left": "var(--sjs2-spacing-x000)", + "--sjs2-layout-control-caption-medium-box-right": "var(--sjs2-spacing-x050)", + "--sjs2-layout-control-caption-medium-box-vertical": "var(--sjs2-spacing-x000)", + "--sjs2-layout-control-caption-medium-box-gap": "var(--sjs2-spacing-x050)", + "--sjs2-layout-control-caption-medium-group-gap": "var(--sjs2-spacing-x000)", + "--sjs2-layout-control-caption-medium-description-horizontal": "var(--sjs2-spacing-x000)", + "--sjs2-layout-control-caption-medium-description-top": "var(--sjs2-spacing-x000)", + "--sjs2-layout-control-caption-medium-description-bottom": "var(--sjs2-spacing-x200)", + "--sjs2-layout-control-caption-medium-caption-horizontal": "var(--sjs2-spacing-x000)", + "--sjs2-layout-control-caption-medium-caption-vertical": "var(--sjs2-spacing-x100)", + "--sjs2-layout-container-drop-horizontal": "var(--sjs2-spacing-x100)", + "--sjs2-layout-container-drop-vertical": "var(--sjs2-spacing-x100)", + "--sjs2-size-semantic-xx-small": "var(--sjs2-size-x300)", + "--sjs2-size-semantic-x-small": "var(--sjs2-size-x400)", + "--sjs2-size-semantic-small": "var(--sjs2-size-x500)", + "--sjs2-size-semantic-medium": "var(--sjs2-size-x600)", + "--sjs2-size-semantic-large": "var(--sjs2-size-x700)", + "--sjs2-size-icon-small": "var(--sjs2-size-x200)", + "--sjs2-size-icon-medium": "var(--sjs2-size-x300)", + "--sjs2-size-icon-large": "var(--sjs2-size-x400)", + "--sjs2-is-panelless": "false", + "--sjs2-typography-font-family-default": "Open Sans", + "--sjs2-typography-font-family-code": "DM Mono", + "--sjs2-typography-font-size-small": "var(--sjs2-font-size-x150)", + "--sjs2-typography-font-size-default": "var(--sjs2-font-size-x200)", + "--sjs2-typography-font-size-medium": "var(--sjs2-font-size-x300)", + "--sjs2-typography-font-size-large": "var(--sjs2-font-size-x400)", + "--sjs2-typography-line-height-small": "var(--sjs2-line-height-x200)", + "--sjs2-typography-line-height-default": "var(--sjs2-line-height-x300)", + "--sjs2-typography-line-height-medium": "var(--sjs2-line-height-x400)", + "--sjs2-typography-line-height-large": "var(--sjs2-line-height-x500)", + "--sjs2-typography-font-weight-default": "var(--sjs2-font-weight-regular)", + "--sjs2-typography-font-weight-strong": "var(--sjs2-font-weight-semibold)", + "--sjs2-color-project-brand-400": "hsl(from var(--sjs2-color-project-brand-600) h s calc(l * 1.1))", + "--sjs2-color-project-brand-600": "#19B394", + "--sjs2-color-project-brand-700": "lch(from var(--sjs2-color-project-brand-600) calc(l * 0.85) c h)", + "--sjs2-color-project-accent-400": "hsl(from var(--sjs2-color-project-accent-600) h s calc(l * 1.1))", + "--sjs2-color-project-accent-600": "#19B394", + "--sjs2-color-project-accent-700": "lch(from var(--sjs2-color-project-accent-600) calc(l * 0.85) c h)", + "--sjs2-color-utility-body": "var(--sjs2-palette-gray-999)", + "--sjs2-color-utility-surface": "#161519", + "--sjs2-color-utility-surface-muted": "#161519", + "--sjs2-color-utility-sheet": "var(--sjs2-palette-gray-900)", + "--sjs2-color-utility-scrollbar": "rgba(from var(--sjs2-palette-gray-000) r g b / var(--sjs2-opacity-x015))", + "--sjs2-color-utility-a11y": "rgba(from var(--sjs2-palette-blue-400) r g b / var(--sjs2-opacity-x040))", + "--sjs2-color-utility-overlay-screen": "rgba(from var(--sjs2-palette-gray-700) r g b / var(--sjs2-opacity-x060))", + "--sjs2-color-utility-overlay-border": "rgba(from var(--sjs2-palette-gray-900) r g b / var(--sjs2-opacity-x020))", + "--sjs2-color-utility-shadow-surface-default": "rgba(from var(--sjs2-palette-gray-999) r g b / var(--sjs2-opacity-x010))", + "--sjs2-color-utility-shadow-surface-hovered": "rgba(from var(--sjs2-palette-gray-999) r g b / var(--sjs2-opacity-x010))", + "--sjs2-color-utility-shadow-surface-pressed": "rgba(from var(--sjs2-palette-gray-999) r g b / var(--sjs2-opacity-x010))", + "--sjs2-color-utility-shadow-surface-focused": "rgba(from var(--sjs2-palette-gray-999) r g b / var(--sjs2-opacity-x010))", + "--sjs2-color-utility-shadow-surface-disabled": "rgba(from var(--sjs2-palette-gray-999) r g b / var(--sjs2-opacity-x010))", + "--sjs2-color-utility-shadow-surface-dragging": "rgba(from #004C44 r g b / var(--sjs2-opacity-x025))", + "--sjs2-color-utility-shadow-elevated-default": "rgba(from #004C44 r g b / var(--sjs2-opacity-x015))", + "--sjs2-color-utility-shadow-floating-default": "rgba(from #004C44 r g b / var(--sjs2-opacity-x020))", + "--sjs2-color-bg-basic-primary": "var(--sjs2-palette-gray-900)", + "--sjs2-color-bg-basic-secondary": "rgba(from var(--sjs2-palette-gray-000) r g b / var(--sjs2-opacity-x005))", + "--sjs2-color-bg-basic-tertiary": "rgba(from var(--sjs2-palette-gray-000) r g b / var(--sjs2-opacity-x010))", + "--sjs2-color-bg-basic-primary-dim": "rgba(from var(--sjs2-palette-gray-000) r g b / var(--sjs2-opacity-x005))", + "--sjs2-color-bg-basic-secondary-dim": "rgba(from var(--sjs2-palette-gray-000) r g b / var(--sjs2-opacity-x010))", + "--sjs2-color-bg-basic-tertiary-dim": "rgba(from var(--sjs2-palette-gray-000) r g b / var(--sjs2-opacity-x015))", + "--sjs2-color-bg-brand-primary": "var(--sjs2-color-project-brand-600)", + "--sjs2-color-bg-brand-secondary": "rgba(from var(--sjs2-color-project-brand-600) r g b / var(--sjs2-opacity-x010))", + "--sjs2-color-bg-brand-tertiary": "rgba(from var(--sjs2-color-project-brand-600) r g b / var(--sjs2-opacity-x000))", + "--sjs2-color-bg-brand-primary-dim": "var(--sjs2-color-project-brand-700)", + "--sjs2-color-bg-brand-secondary-dim": "rgba(from var(--sjs2-color-project-brand-600) r g b / var(--sjs2-opacity-x015))", + "--sjs2-color-bg-brand-tertiary-dim": "rgba(from var(--sjs2-color-project-brand-600) r g b / var(--sjs2-opacity-x010))", + "--sjs2-color-bg-accent-primary": "var(--sjs2-color-project-accent-600)", + "--sjs2-color-bg-accent-secondary": "rgba(from var(--sjs2-color-project-accent-600) r g b / var(--sjs2-opacity-x010))", + "--sjs2-color-bg-accent-tertiary": "rgba(from var(--sjs2-color-project-accent-600) r g b / var(--sjs2-opacity-x000))", + "--sjs2-color-bg-accent-primary-dim": "var(--sjs2-color-project-accent-700)", + "--sjs2-color-bg-accent-secondary-dim": "rgba(from var(--sjs2-color-project-accent-600) r g b / var(--sjs2-opacity-x015))", + "--sjs2-color-bg-accent-tertiary-dim": "rgba(from var(--sjs2-color-project-accent-600) r g b / var(--sjs2-opacity-x010))", + "--sjs2-color-bg-note-primary": "var(--sjs2-palette-blue-600)", + "--sjs2-color-bg-note-secondary": "rgba(from var(--sjs2-palette-blue-600) r g b / var(--sjs2-opacity-x010))", + "--sjs2-color-bg-note-tertiary": "rgba(from var(--sjs2-palette-blue-600) r g b / var(--sjs2-opacity-x000))", + "--sjs2-color-bg-note-primary-dim": "var(--sjs2-palette-blue-700)", + "--sjs2-color-bg-note-secondary-dim": "rgba(from var(--sjs2-palette-blue-600) r g b / var(--sjs2-opacity-x015))", + "--sjs2-color-bg-note-tertiary-dim": "rgba(from var(--sjs2-palette-blue-600) r g b / var(--sjs2-opacity-x010))", + "--sjs2-color-bg-neutral-primary": "var(--sjs2-palette-gray-000)", + "--sjs2-color-bg-neutral-secondary": "rgba(from var(--sjs2-palette-gray-000) r g b / var(--sjs2-opacity-x015))", + "--sjs2-color-bg-neutral-tertiary": "rgba(from var(--sjs2-palette-gray-000) r g b / var(--sjs2-opacity-x000))", + "--sjs2-color-bg-neutral-primary-dim": "var(--sjs2-palette-gray-100)", + "--sjs2-color-bg-neutral-secondary-dim": "rgba(from var(--sjs2-palette-gray-000) r g b / var(--sjs2-opacity-x020))", + "--sjs2-color-bg-neutral-tertiary-dim": "rgba(from var(--sjs2-palette-gray-000) r g b / var(--sjs2-opacity-x010))", + "--sjs2-color-bg-positive-primary": "var(--sjs2-palette-green-600)", + "--sjs2-color-bg-positive-secondary": "rgba(from var(--sjs2-palette-green-600) r g b / var(--sjs2-opacity-x010))", + "--sjs2-color-bg-positive-tertiary": "rgba(from var(--sjs2-palette-green-600) r g b / var(--sjs2-opacity-x000))", + "--sjs2-color-bg-positive-primary-dim": "var(--sjs2-palette-green-700)", + "--sjs2-color-bg-positive-secondary-dim": "rgba(from var(--sjs2-palette-green-600) r g b / var(--sjs2-opacity-x015))", + "--sjs2-color-bg-positive-tertiary-dim": "rgba(from var(--sjs2-palette-green-600) r g b / var(--sjs2-opacity-x010))", + "--sjs2-color-bg-warning-primary": "var(--sjs2-palette-yellow-600)", + "--sjs2-color-bg-warning-secondary": "rgba(from var(--sjs2-palette-yellow-600) r g b / var(--sjs2-opacity-x010))", + "--sjs2-color-bg-warning-tertiary": "rgba(from var(--sjs2-palette-yellow-600) r g b / var(--sjs2-opacity-x000))", + "--sjs2-color-bg-warning-primary-dim": "var(--sjs2-palette-yellow-700)", + "--sjs2-color-bg-warning-secondary-dim": "rgba(from var(--sjs2-palette-yellow-600) r g b / var(--sjs2-opacity-x015))", + "--sjs2-color-bg-warning-tertiary-dim": "rgba(from var(--sjs2-palette-yellow-600) r g b / var(--sjs2-opacity-x010))", + "--sjs2-color-bg-alert-primary": "var(--sjs2-palette-red-600)", + "--sjs2-color-bg-alert-secondary": "rgba(from var(--sjs2-palette-red-600) r g b / var(--sjs2-opacity-x010))", + "--sjs2-color-bg-alert-tertiary": "rgba(from var(--sjs2-palette-red-600) r g b / var(--sjs2-opacity-x000))", + "--sjs2-color-bg-alert-primary-dim": "var(--sjs2-palette-red-700)", + "--sjs2-color-bg-alert-secondary-dim": "rgba(from var(--sjs2-palette-red-600) r g b / var(--sjs2-opacity-x015))", + "--sjs2-color-bg-alert-tertiary-dim": "rgba(from var(--sjs2-palette-red-600) r g b / var(--sjs2-opacity-x010))", + "--sjs2-color-bg-static-main-primary": "var(--sjs2-palette-gray-900)", + "--sjs2-color-bg-static-main-secondary": "rgba(from var(--sjs2-palette-gray-900) r g b / var(--sjs2-opacity-x010))", + "--sjs2-color-bg-static-main-primary-dim": "var(--sjs2-palette-gray-700)", + "--sjs2-color-bg-static-main-secondary-dim": "rgba(from var(--sjs2-palette-gray-900) r g b / var(--sjs2-opacity-x015))", + "--sjs2-color-bg-static-sub-primary": "var(--sjs2-palette-gray-000)", + "--sjs2-color-bg-static-sub-secondary": "rgba(from var(--sjs2-palette-gray-000) r g b / var(--sjs2-opacity-x010))", + "--sjs2-color-bg-static-sub-primary-dim": "hsl(from var(--sjs2-palette-gray-100) h s calc(l * 1.1))", + "--sjs2-color-bg-static-sub-secondary-dim": "rgba(from var(--sjs2-palette-gray-000) r g b / var(--sjs2-opacity-x015))", + "--sjs2-color-bg-state-common-disabled": "var(--sjs2-palette-gray-750)", + "--sjs2-color-fg-basic-primary": "rgba(from var(--sjs2-palette-gray-000) r g b / var(--sjs2-opacity-x085))", + "--sjs2-color-fg-basic-primary-muted": "rgba(from var(--sjs2-palette-gray-000) r g b / var(--sjs2-opacity-x085))", + "--sjs2-color-fg-basic-secondary": "rgba(from var(--sjs2-palette-gray-000) r g b / var(--sjs2-opacity-x060))", + "--sjs2-color-fg-basic-tertiary": "rgba(from var(--sjs2-palette-gray-000) r g b / var(--sjs2-opacity-x040))", + "--sjs2-color-fg-neutral-primary": "var(--sjs2-palette-gray-900)", + "--sjs2-color-fg-brand-primary": "var(--sjs2-color-project-brand-400)", + "--sjs2-color-fg-accent-primary": "var(--sjs2-color-project-accent-400)", + "--sjs2-color-fg-note-primary": "var(--sjs2-palette-blue-400)", + "--sjs2-color-fg-positive-primary": "var(--sjs2-palette-green-400)", + "--sjs2-color-fg-warning-primary": "var(--sjs2-palette-yellow-400)", + "--sjs2-color-fg-alert-primary": "var(--sjs2-palette-red-400)", + "--sjs2-color-fg-static-main-primary": "var(--sjs2-palette-gray-000)", + "--sjs2-color-fg-static-sub-primary": "var(--sjs2-palette-gray-900)", + "--sjs2-color-fg-state-common-disabled": "var(--sjs2-palette-gray-300)", + "--sjs2-color-border-basic-primary": "var(--sjs2-palette-gray-000)", + "--sjs2-color-border-basic-secondary": "var(--sjs2-palette-gray-750)", + "--sjs2-color-border-brand-primary": "var(--sjs2-color-project-brand-600)", + "--sjs2-color-border-accent-primary": "var(--sjs2-color-project-accent-600)", + "--sjs2-color-border-note-primary": "var(--sjs2-palette-blue-600)", + "--sjs2-color-border-positive-primary": "var(--sjs2-palette-green-600)", + "--sjs2-color-border-warning-primary": "var(--sjs2-palette-yellow-600)", + "--sjs2-color-border-alert-primary": "var(--sjs2-palette-red-600)", + "--sjs2-color-border-neutral-primary": "var(--sjs2-palette-gray-900)", + "--sjs2-color-border-static-main-primary": "var(--sjs2-palette-gray-000)", + "--sjs2-color-border-static-sub-primary": "var(--sjs2-palette-gray-900)", + "--sjs2-color-control-formbox-default-bg": "var(--sjs2-palette-gray-800)", + "--sjs2-color-control-formbox-default-border": "var(--sjs2-color-border-basic-secondary)", + "--sjs2-color-control-formbox-disabled-bg": "var(--sjs2-color-bg-basic-primary)", + "--sjs2-color-control-formbox-disabled-border": "var(--sjs2-palette-gray-800)", + "--sjs2-color-control-formbox-readonly-bg": "var(--sjs2-color-bg-basic-primary)", + "--sjs2-color-control-formbox-readonly-border": "var(--sjs2-color-border-basic-secondary)", + "--sjs2-color-control-formbox-focused-bg": "var(--sjs2-palette-gray-800)", + "--sjs2-color-control-formbox-focused-border": "var(--sjs2-color-border-brand-primary)", + "--sjs2-color-control-formbox-invalid-bg": "var(--sjs2-palette-gray-800)", + "--sjs2-color-control-formbox-invalid-border": "var(--sjs2-color-border-alert-primary)", + "--sjs2-color-control-formbox-highlighted-bg": "var(--sjs2-palette-gray-800)", + "--sjs2-color-control-formbox-highlighted-border": "var(--sjs2-color-border-basic-primary)", + "--sjs2-color-control-formbox-design-bg": "var(--sjs2-palette-gray-800)", + "--sjs2-color-control-formbox-design-border": "var(--sjs2-color-border-basic-secondary)", + "--sjs2-color-control-input-default-line": "var(--sjs2-color-border-basic-secondary)", + "--sjs2-color-control-input-default-value": "var(--sjs2-color-fg-basic-primary)", + "--sjs2-color-control-input-default-placeholder": "var(--sjs2-color-fg-basic-secondary)", + "--sjs2-color-control-input-default-label": "var(--sjs2-color-fg-basic-secondary)", + "--sjs2-color-control-input-default-limit": "var(--sjs2-color-fg-basic-secondary)", + "--sjs2-color-control-input-default-icon": "var(--sjs2-color-fg-basic-tertiary)", + "--sjs2-color-control-input-disabled-line": "var(--sjs2-palette-gray-800)", + "--sjs2-color-control-input-disabled-value": "var(--sjs2-palette-gray-250)", + "--sjs2-color-control-input-disabled-placeholder": "var(--sjs2-palette-gray-600)", + "--sjs2-color-control-input-disabled-label": "var(--sjs2-palette-gray-600)", + "--sjs2-color-control-input-disabled-limit": "var(--sjs2-palette-gray-600)", + "--sjs2-color-control-input-disabled-icon": "var(--sjs2-palette-gray-250)", + "--sjs2-color-control-input-readonly-line": "var(--sjs2-color-border-basic-secondary)", + "--sjs2-color-control-input-readonly-value": "var(--sjs2-color-fg-basic-primary)", + "--sjs2-color-control-input-readonly-placeholder": "var(--sjs2-color-fg-basic-secondary)", + "--sjs2-color-control-input-readonly-label": "var(--sjs2-color-fg-basic-secondary)", + "--sjs2-color-control-input-readonly-limit": "var(--sjs2-color-fg-basic-secondary)", + "--sjs2-color-control-input-readonly-icon": "var(--sjs2-color-fg-basic-tertiary)", + "--sjs2-color-control-check-false-default-bg": "var(--sjs2-palette-gray-800)", + "--sjs2-color-control-check-false-default-border": "var(--sjs2-color-border-basic-secondary)", + "--sjs2-color-control-check-false-disabled-bg": "var(--sjs2-color-bg-basic-primary)", + "--sjs2-color-control-check-false-disabled-border": "var(--sjs2-color-border-basic-secondary)", + "--sjs2-color-control-check-false-readonly-bg": "var(--sjs2-color-bg-basic-primary)", + "--sjs2-color-control-check-false-readonly-border": "var(--sjs2-color-border-basic-secondary)", + "--sjs2-color-control-check-false-focused-bg": "var(--sjs2-palette-gray-800)", + "--sjs2-color-control-check-false-focused-border": "var(--sjs2-color-border-brand-primary)", + "--sjs2-color-control-check-false-hovered-bg": "var(--sjs2-color-bg-basic-secondary-dim)", + "--sjs2-color-control-check-false-hovered-border": "var(--sjs2-color-border-basic-secondary)", + "--sjs2-color-control-check-false-design-bg": "var(--sjs2-palette-gray-800)", + "--sjs2-color-control-check-false-design-border": "var(--sjs2-color-border-basic-secondary)", + "--sjs2-color-control-check-true-default-bg": "var(--sjs2-color-bg-brand-primary)", + "--sjs2-color-control-check-true-default-border": "var(--sjs2-color-border-brand-primary)", + "--sjs2-color-control-check-true-default-icon": "var(--sjs2-color-fg-static-main-primary)", + "--sjs2-color-control-check-true-disabled-bg": "var(--sjs2-color-bg-basic-primary)", + "--sjs2-color-control-check-true-disabled-border": "var(--sjs2-color-border-basic-secondary)", + "--sjs2-color-control-check-true-disabled-icon": "var(--sjs2-palette-gray-400)", + "--sjs2-color-control-check-true-readonly-bg": "var(--sjs2-color-bg-basic-primary)", + "--sjs2-color-control-check-true-readonly-border": "var(--sjs2-color-border-basic-secondary)", + "--sjs2-color-control-check-true-readonly-icon": "var(--sjs2-palette-gray-400)", + "--sjs2-color-control-check-true-focused-bg": "var(--sjs2-color-bg-basic-primary)", + "--sjs2-color-control-check-true-focused-border": "var(--sjs2-color-border-brand-primary)", + "--sjs2-color-control-check-true-focused-icon": "var(--sjs2-color-fg-brand-primary)", + "--sjs2-color-control-check-true-hovered-bg": "var(--sjs2-color-bg-brand-primary-dim)", + "--sjs2-color-control-check-true-hovered-border": "var(--sjs2-color-bg-brand-primary-dim)", + "--sjs2-color-control-check-true-hovered-icon": "var(--sjs2-color-fg-static-main-primary)", + "--sjs2-color-control-segmented-false-default-bg": "rgba(from var(--sjs2-color-bg-basic-primary) r g b / var(--sjs2-opacity-hidden))", + "--sjs2-color-control-segmented-false-default-border": "rgba(from var(--sjs2-color-border-basic-secondary) r g b / var(--sjs2-opacity-hidden))", + "--sjs2-color-control-segmented-false-default-value": "var(--sjs2-color-fg-basic-secondary)", + "--sjs2-color-control-segmented-false-disabled-bg": "rgba(from var(--sjs2-color-bg-basic-primary) r g b / var(--sjs2-opacity-hidden))", + "--sjs2-color-control-segmented-false-disabled-border": "rgba(from var(--sjs2-color-border-basic-secondary) r g b / var(--sjs2-opacity-hidden))", + "--sjs2-color-control-segmented-false-disabled-value": "var(--sjs2-palette-gray-250)", + "--sjs2-color-control-segmented-false-readonly-bg": "rgba(from var(--sjs2-color-bg-basic-primary) r g b / var(--sjs2-opacity-hidden))", + "--sjs2-color-control-segmented-false-readonly-border": "rgba(from var(--sjs2-color-border-basic-secondary) r g b / var(--sjs2-opacity-hidden))", + "--sjs2-color-control-segmented-false-readonly-value": "var(--sjs2-palette-gray-400)", + "--sjs2-color-control-segmented-false-focused-bg": "var(--sjs2-color-bg-basic-secondary)", + "--sjs2-color-control-segmented-false-focused-border": "var(--sjs2-color-border-brand-primary)", + "--sjs2-color-control-segmented-false-focused-value": "var(--sjs2-color-fg-basic-primary)", + "--sjs2-color-control-segmented-false-hovered-bg": "var(--sjs2-color-bg-basic-secondary-dim)", + "--sjs2-color-control-segmented-false-hovered-border": "var(--sjs2-color-border-basic-secondary)", + "--sjs2-color-control-segmented-false-hovered-value": "var(--sjs2-color-fg-basic-primary)", + "--sjs2-color-control-segmented-true-default-bg": "var(--sjs2-color-bg-basic-primary)", + "--sjs2-color-control-segmented-true-default-border": "var(--sjs2-color-border-basic-secondary)", + "--sjs2-color-control-segmented-true-default-value": "var(--sjs2-color-fg-brand-primary)", + "--sjs2-color-control-segmented-true-disabled-bg": "var(--sjs2-color-bg-basic-primary-dim)", + "--sjs2-color-control-segmented-true-disabled-border": "rgba(from var(--sjs2-color-border-basic-secondary) r g b / var(--sjs2-opacity-hidden))", + "--sjs2-color-control-segmented-true-disabled-value": "var(--sjs2-palette-gray-400)", + "--sjs2-color-control-segmented-true-readonly-bg": "var(--sjs2-color-bg-basic-primary)", + "--sjs2-color-control-segmented-true-readonly-border": "var(--sjs2-color-border-basic-secondary)", + "--sjs2-color-control-segmented-true-readonly-value": "var(--sjs2-color-fg-basic-primary)", + "--sjs2-color-control-segmented-true-focused-bg": "var(--sjs2-color-bg-basic-primary)", + "--sjs2-color-control-segmented-true-focused-border": "var(--sjs2-color-border-brand-primary)", + "--sjs2-color-control-segmented-true-focused-value": "var(--sjs2-color-fg-brand-primary)", + "--sjs2-color-control-toggle-false-default-bg": "var(--sjs2-palette-gray-800)", + "--sjs2-color-control-toggle-false-default-border": "var(--sjs2-color-border-basic-secondary)", + "--sjs2-color-control-toggle-false-default-thumb": "var(--sjs2-color-fg-basic-secondary)", + "--sjs2-color-control-toggle-false-disabled-bg": "var(--sjs2-palette-gray-800)", + "--sjs2-color-control-toggle-false-disabled-border": "var(--sjs2-color-border-basic-secondary)", + "--sjs2-color-control-toggle-false-disabled-thumb": "var(--sjs2-color-fg-basic-tertiary)", + "--sjs2-color-control-toggle-false-readonly-bg": "var(--sjs2-palette-gray-800)", + "--sjs2-color-control-toggle-false-readonly-border": "var(--sjs2-color-border-basic-secondary)", + "--sjs2-color-control-toggle-false-readonly-thumb": "var(--sjs2-color-fg-basic-tertiary)", + "--sjs2-color-control-toggle-false-focused-bg": "var(--sjs2-palette-gray-800)", + "--sjs2-color-control-toggle-false-focused-border": "var(--sjs2-color-border-brand-primary)", + "--sjs2-color-control-toggle-false-focused-thumb": "var(--sjs2-color-fg-basic-secondary)", + "--sjs2-color-control-toggle-false-hovered-bg": "var(--sjs2-palette-gray-800)", + "--sjs2-color-control-toggle-false-hovered-border": "var(--sjs2-color-border-basic-secondary)", + "--sjs2-color-control-toggle-false-hovered-thumb": "var(--sjs2-color-fg-basic-secondary)", + "--sjs2-color-control-toggle-true-default-bg": "var(--sjs2-color-bg-brand-primary)", + "--sjs2-color-control-toggle-true-default-border": "var(--sjs2-color-border-brand-primary)", + "--sjs2-color-control-toggle-true-default-thumb": "var(--sjs2-color-fg-static-main-primary)", + "--sjs2-color-control-toggle-true-disabled-bg": "var(--sjs2-color-bg-basic-secondary)", + "--sjs2-color-control-toggle-true-disabled-border": "var(--sjs2-color-border-basic-secondary)", + "--sjs2-color-control-toggle-true-disabled-thumb": "var(--sjs2-color-fg-static-main-primary)", + "--sjs2-color-control-toggle-true-readonly-bg": "var(--sjs2-color-bg-basic-secondary)", + "--sjs2-color-control-toggle-true-readonly-border": "var(--sjs2-color-border-basic-secondary)", + "--sjs2-color-control-toggle-true-readonly-thumb": "var(--sjs2-color-fg-static-main-primary)", + "--sjs2-color-control-toggle-true-focused-bg": "var(--sjs2-color-bg-basic-primary)", + "--sjs2-color-control-toggle-true-focused-border": "var(--sjs2-color-border-brand-primary)", + "--sjs2-color-control-toggle-true-focused-thumb": "var(--sjs2-color-fg-brand-primary)", + "--sjs2-color-control-toggle-true-hovered-bg": "var(--sjs2-color-bg-brand-primary-dim)", + "--sjs2-color-control-toggle-true-hovered-border": "var(--sjs2-color-border-brand-primary)", + "--sjs2-color-control-toggle-true-hovered-thumb": "var(--sjs2-color-fg-static-main-primary)", + "--sjs2-color-control-message-bg": "var(--sjs2-color-bg-alert-secondary)", + "--sjs2-color-control-message-icon": "var(--sjs2-color-fg-alert-primary)", + "--sjs2-color-control-message-text": "var(--sjs2-color-fg-basic-primary)", + "--sjs2-color-control-track-default-bg": "var(--sjs2-color-bg-basic-secondary)", + "--sjs2-color-control-track-default-fg": "var(--sjs2-color-fg-brand-primary)", + "--sjs2-color-control-track-default-thumb": "var(--sjs2-color-bg-basic-primary)", + "--sjs2-color-control-track-default-dot": "var(--sjs2-color-fg-brand-primary)", + "--sjs2-color-control-track-default-thumb-border": "var(--sjs2-color-border-basic-secondary)", + "--sjs2-color-control-track-disabled-bg": "var(--sjs2-color-bg-basic-secondary)", + "--sjs2-color-control-track-disabled-fg": "var(--sjs2-color-fg-basic-tertiary)", + "--sjs2-color-control-track-disabled-thumb": "var(--sjs2-color-bg-basic-primary)", + "--sjs2-color-control-track-disabled-dot": "var(--sjs2-color-fg-state-common-disabled)", + "--sjs2-color-control-track-disabled-thumb-border": "var(--sjs2-color-border-basic-secondary)", + "--sjs2-color-control-track-readonly-bg": "var(--sjs2-color-bg-basic-secondary)", + "--sjs2-color-control-track-readonly-fg": "var(--sjs2-color-fg-brand-primary)", + "--sjs2-color-control-track-readonly-thumb": "var(--sjs2-color-bg-basic-primary)", + "--sjs2-color-control-track-readonly-dot": "var(--sjs2-color-bg-basic-primary)", + "--sjs2-color-control-track-readonly-thumb-border": "var(--sjs2-color-border-basic-secondary)", + "--sjs2-color-control-track-focused-bg": "var(--sjs2-color-bg-basic-secondary)", + "--sjs2-color-control-track-focused-fg": "var(--sjs2-color-fg-brand-primary)", + "--sjs2-color-control-track-focused-thumb": "var(--sjs2-color-bg-basic-primary)", + "--sjs2-color-control-track-focused-dot": "var(--sjs2-color-fg-brand-primary)", + "--sjs2-color-control-track-focused-thumb-border": "var(--sjs2-color-border-basic-secondary)", + "--sjs2-color-control-track-invalid-bg": "var(--sjs2-color-bg-alert-secondary)", + "--sjs2-color-control-track-invalid-fg": "var(--sjs2-color-fg-alert-primary)", + "--sjs2-color-control-track-invalid-thumb": "var(--sjs2-color-bg-basic-primary)", + "--sjs2-color-control-track-invalid-dot": "var(--sjs2-color-fg-alert-primary)", + "--sjs2-color-control-track-invalid-thumb-border": "var(--sjs2-color-border-basic-secondary)", + "--sjs2-color-control-track-design-bg": "var(--sjs2-color-bg-basic-secondary)", + "--sjs2-color-control-track-design-fg": "var(--sjs2-color-fg-basic-tertiary)", + "--sjs2-color-control-track-design-thumb": "var(--sjs2-color-bg-basic-primary)", + "--sjs2-color-control-track-design-dot": "var(--sjs2-color-bg-basic-primary)", + "--sjs2-color-control-track-design-thumb-border": "var(--sjs2-color-border-basic-secondary)", + "--sjs2-color-data-chart-bg-color-1": "#84CAD4", + "--sjs2-color-data-chart-bg-color-2": "#3A99FB", + "--sjs2-color-data-chart-bg-color-3": "#FF6771", + "--sjs2-color-data-chart-bg-color-4": "#1DB496", + "--sjs2-color-data-chart-bg-color-5": "#FFC152", + "--sjs2-color-data-chart-bg-color-6": "#ABA1FF", + "--sjs2-color-data-chart-bg-color-7": "#7D8CA5", + "--sjs2-color-data-chart-bg-color-8": "#4FC46C", + "--sjs2-color-data-chart-bg-color-9": "#E87BCB", + "--sjs2-color-data-chart-bg-color-10": "#4E6198", + "--sjs2-color-data-chart-bg-color-1-tinted": "rgba(from #84CAD4 r g b / var(--sjs2-opacity-x060))", + "--sjs2-color-data-chart-bg-color-2-tinted": "rgba(from #3A99FB r g b / var(--sjs2-opacity-x060))", + "--sjs2-color-data-chart-bg-color-3-tinted": "rgba(from #FF6771 r g b / var(--sjs2-opacity-x060))", + "--sjs2-color-data-chart-bg-color-4-tinted": "rgba(from #1DB496 r g b / var(--sjs2-opacity-x060))", + "--sjs2-color-data-chart-bg-color-5-tinted": "rgba(from #FFC152 r g b / var(--sjs2-opacity-x060))", + "--sjs2-color-data-chart-bg-color-6-tinted": "rgba(from #ABA1FF r g b / var(--sjs2-opacity-x060))", + "--sjs2-color-data-chart-bg-color-7-tinted": "rgba(from #7D8CA5 r g b / var(--sjs2-opacity-x060))", + "--sjs2-color-data-chart-bg-color-8-tinted": "rgba(from #4FC46C r g b / var(--sjs2-opacity-x060))", + "--sjs2-color-data-chart-bg-color-9-tinted": "rgba(from #E87BCB r g b / var(--sjs2-opacity-x060))", + "--sjs2-color-data-chart-bg-color-10-tinted": "rgba(from #4E6198 r g b / var(--sjs2-opacity-x060))", + "--sjs2-color-data-chart-fg-on-color-1": "var(--sjs2-palette-gray-000)", + "--sjs2-color-data-chart-fg-on-color-2": "var(--sjs2-palette-gray-000)", + "--sjs2-color-data-chart-fg-on-color-3": "var(--sjs2-palette-gray-000)", + "--sjs2-color-data-chart-fg-on-color-4": "var(--sjs2-palette-gray-000)", + "--sjs2-color-data-chart-fg-on-color-5": "var(--sjs2-palette-gray-000)", + "--sjs2-color-data-chart-fg-on-color-6": "var(--sjs2-palette-gray-000)", + "--sjs2-color-data-chart-fg-on-color-7": "var(--sjs2-palette-gray-000)", + "--sjs2-color-data-chart-fg-on-color-8": "var(--sjs2-palette-gray-000)", + "--sjs2-color-data-chart-fg-on-color-9": "var(--sjs2-palette-gray-000)", + "--sjs2-color-data-chart-fg-on-color-10": "var(--sjs2-palette-gray-000)", + "--sjs2-color-data-chart-border-color-1": "#84CAD4", + "--sjs2-color-data-chart-border-color-2": "#3A99FB", + "--sjs2-color-data-chart-border-color-3": "#FF6771", + "--sjs2-color-data-chart-border-color-4": "#1DB496", + "--sjs2-color-data-chart-border-color-5": "#FFC152", + "--sjs2-color-data-chart-border-color-6": "#ABA1FF", + "--sjs2-color-data-chart-border-color-7": "#7D8CA5", + "--sjs2-color-data-chart-border-color-8": "#4FC46C", + "--sjs2-color-data-chart-border-color-9": "#E87BCB", + "--sjs2-color-data-chart-border-color-10": "#4E6198", + "--sjs2-color-data-grid-fg-label": "var(--sjs2-color-fg-basic-primary)", + "--sjs2-color-data-grid-border-line": "var(--sjs2-color-border-basic-secondary)", + "--sjs2-color-data-grid-border-axis": "var(--sjs2-color-border-basic-primary)", + "--sjs2-opacity-visible": "var(--sjs2-opacity-x100)", + "--sjs2-opacity-hovered": "var(--sjs2-opacity-x100)", + "--sjs2-opacity-pressed": "var(--sjs2-opacity-x100)", + "--sjs2-opacity-disabled": "var(--sjs2-opacity-x025)", + "--sjs2-opacity-hidden": "var(--sjs2-opacity-x000)", + "--sjs2-border-width-default": "var(--sjs2-border-width-x100)", + "--sjs2-border-width-a11y": "var(--sjs2-border-width-x400)", + "--sjs2-border-spread-form-default": "var(--sjs2-border-width-x100)", + "--sjs2-border-spread-form-hovered": "var(--sjs2-border-width-x100)", + "--sjs2-border-spread-form-pressed": "var(--sjs2-border-width-x100)", + "--sjs2-border-spread-form-focused": "var(--sjs2-border-width-x200)", + "--sjs2-border-spread-form-highlighted": "var(--sjs2-border-width-x200)", + "--sjs2-border-spread-form-disabled": "var(--sjs2-border-width-x100)", + "--sjs2-border-spread-form-invalid": "var(--sjs2-border-width-x200)", + "--sjs2-border-spread-form-readonly": "var(--sjs2-border-width-x100)", + "--sjs2-border-spread-form-preview": "var(--sjs2-border-width-x100)", + "--sjs2-border-spread-trigger-default": "var(--sjs2-border-width-x100)", + "--sjs2-border-spread-trigger-hovered": "var(--sjs2-border-width-x100)", + "--sjs2-border-spread-trigger-pressed": "var(--sjs2-border-width-x100)", + "--sjs2-border-spread-trigger-focused": "var(--sjs2-border-width-x200)", + "--sjs2-border-spread-trigger-disabled": "var(--sjs2-border-width-x100)", + "--sjs2-border-spread-trigger-preview": "var(--sjs2-border-width-x100)", + "--sjs2-border-spread-surface-default": "var(--sjs2-border-width-x100)", + "--sjs2-border-spread-surface-hovered": "var(--sjs2-border-width-x100)", + "--sjs2-border-spread-surface-pressed": "var(--sjs2-border-width-x100)", + "--sjs2-border-spread-surface-focused": "var(--sjs2-border-width-x200)", + "--sjs2-border-spread-surface-disabled": "var(--sjs2-border-width-x100)", + "--sjs2-border-spread-surface-dragging": "4", + "--sjs2-border-spread-elevated-default": "2", + "--sjs2-border-spread-floating-default": "4", + "--sjs2-border-blur-form-default": "0", + "--sjs2-border-blur-form-hovered": "0", + "--sjs2-border-blur-form-pressed": "0", + "--sjs2-border-blur-form-focused": "0", + "--sjs2-border-blur-form-highlighted": "0", + "--sjs2-border-blur-form-disabled": "0", + "--sjs2-border-blur-form-invalid": "0", + "--sjs2-border-blur-form-readonly": "0", + "--sjs2-border-blur-form-preview": "0", + "--sjs2-border-blur-trigger-default": "0", + "--sjs2-border-blur-trigger-hovered": "0", + "--sjs2-border-blur-trigger-pressed": "0", + "--sjs2-border-blur-trigger-focused": "0", + "--sjs2-border-blur-trigger-disabled": "0", + "--sjs2-border-blur-trigger-preview": "0", + "--sjs2-border-blur-surface-default": "4", + "--sjs2-border-blur-surface-hovered": "4", + "--sjs2-border-blur-surface-pressed": "4", + "--sjs2-border-blur-surface-focused": "0", + "--sjs2-border-blur-surface-disabled": "0", + "--sjs2-border-blur-surface-dragging": "12", + "--sjs2-border-blur-elevated-default": "8", + "--sjs2-border-blur-floating-default": "12", + "--sjs2-border-offset-x-form-default": "0", + "--sjs2-border-offset-x-form-hovered": "0", + "--sjs2-border-offset-x-form-pressed": "0", + "--sjs2-border-offset-x-form-focused": "0", + "--sjs2-border-offset-x-form-highlighted": "0", + "--sjs2-border-offset-x-form-disabled": "0", + "--sjs2-border-offset-x-form-invalid": "0", + "--sjs2-border-offset-x-form-readonly": "0", + "--sjs2-border-offset-x-form-preview": "0", + "--sjs2-border-offset-x-trigger-default": "0", + "--sjs2-border-offset-x-trigger-hovered": "0", + "--sjs2-border-offset-x-trigger-pressed": "0", + "--sjs2-border-offset-x-trigger-focused": "0", + "--sjs2-border-offset-x-trigger-disabled": "0", + "--sjs2-border-offset-x-trigger-preview": "0", + "--sjs2-border-offset-x-surface-default": "0", + "--sjs2-border-offset-x-surface-hovered": "0", + "--sjs2-border-offset-x-surface-pressed": "0", + "--sjs2-border-offset-x-surface-focused": "0", + "--sjs2-border-offset-x-surface-disabled": "0", + "--sjs2-border-offset-x-surface-dragging": "0", + "--sjs2-border-offset-x-elevated-default": "0", + "--sjs2-border-offset-x-floating-default": "0", + "--sjs2-border-offset-y-form-default": "0", + "--sjs2-border-offset-y-form-hovered": "0", + "--sjs2-border-offset-y-form-pressed": "0", + "--sjs2-border-offset-y-form-focused": "0", + "--sjs2-border-offset-y-form-highlighted": "0", + "--sjs2-border-offset-y-form-disabled": "0", + "--sjs2-border-offset-y-form-invalid": "0", + "--sjs2-border-offset-y-form-readonly": "0", + "--sjs2-border-offset-y-form-preview": "0", + "--sjs2-border-offset-y-trigger-default": "0", + "--sjs2-border-offset-y-trigger-hovered": "0", + "--sjs2-border-offset-y-trigger-pressed": "0", + "--sjs2-border-offset-y-trigger-focused": "0", + "--sjs2-border-offset-y-trigger-disabled": "0", + "--sjs2-border-offset-y-trigger-preview": "0", + "--sjs2-border-offset-y-surface-default": "2", + "--sjs2-border-offset-y-surface-hovered": "2", + "--sjs2-border-offset-y-surface-pressed": "2", + "--sjs2-border-offset-y-surface-focused": "0", + "--sjs2-border-offset-y-surface-disabled": "0", + "--sjs2-border-offset-y-surface-dragging": "6", + "--sjs2-border-offset-y-elevated-default": "4", + "--sjs2-border-offset-y-floating-default": "6" + } +} as const; + +export default DefaultDark; diff --git a/src/sjs-design-tokens/default-light.ts b/src/sjs-design-tokens/default-light.ts new file mode 100644 index 000000000..b4550ba71 --- /dev/null +++ b/src/sjs-design-tokens/default-light.ts @@ -0,0 +1,726 @@ +// Auto-generated theme: default-light +export const Default = { + "themeName": "default-light", + "iconSet": "v2", + "isLight": true, + "cssVariables": { + "--sjs2-base-unit-size": "8px", + "--sjs2-base-unit-spacing": "8px", + "--sjs2-base-unit-radius": "8px", + "--sjs2-base-unit-border-width": "1px", + "--sjs2-base-unit-font-size": "8px", + "--sjs2-base-unit-line-height": "8px", + "--sjs2-base-unit-opacity": "1%", + "--sjs2-base-unit-scale": "1%", + "--sjs2-scale-x000": "calc(var(--sjs2-base-unit-scale) * 0)", + "--sjs2-scale-x025": "calc(var(--sjs2-base-unit-scale) * 25)", + "--sjs2-scale-x050": "calc(var(--sjs2-base-unit-scale) * 50)", + "--sjs2-scale-x075": "calc(var(--sjs2-base-unit-scale) * 75)", + "--sjs2-scale-x095": "calc(var(--sjs2-base-unit-scale) * 95)", + "--sjs2-scale-x100": "calc(var(--sjs2-base-unit-scale) * 100)", + "--sjs2-scale-x200": "calc(var(--sjs2-base-unit-scale) * 200)", + "--sjs2-size-x000": "calc(var(--sjs2-base-unit-size) * 0)", + "--sjs2-size-x025": "calc(var(--sjs2-base-unit-size) * 0.25)", + "--sjs2-size-x050": "calc(var(--sjs2-base-unit-size) * 0.50)", + "--sjs2-size-x075": "calc(var(--sjs2-base-unit-size) * 0.75)", + "--sjs2-size-x100": "calc(var(--sjs2-base-unit-size) * 1)", + "--sjs2-size-x150": "calc(var(--sjs2-base-unit-size) * 1.50)", + "--sjs2-size-x200": "calc(var(--sjs2-base-unit-size) * 2)", + "--sjs2-size-x250": "calc(var(--sjs2-base-unit-size) * 2.50)", + "--sjs2-size-x300": "calc(var(--sjs2-base-unit-size) * 3)", + "--sjs2-size-x350": "calc(var(--sjs2-base-unit-size) * 3.50)", + "--sjs2-size-x400": "calc(var(--sjs2-base-unit-size) * 4)", + "--sjs2-size-x500": "calc(var(--sjs2-base-unit-size) * 5)", + "--sjs2-size-x600": "calc(var(--sjs2-base-unit-size) * 6)", + "--sjs2-size-x700": "calc(var(--sjs2-base-unit-size) * 7)", + "--sjs2-size-x800": "calc(var(--sjs2-base-unit-size) * 8)", + "--sjs2-size-x900": "calc(var(--sjs2-base-unit-size) * 9)", + "--sjs2-size-x1000": "calc(var(--sjs2-base-unit-size) * 10)", + "--sjs2-size-x1100": "calc(var(--sjs2-base-unit-size) * 11)", + "--sjs2-size-x1200": "calc(var(--sjs2-base-unit-size) * 12)", + "--sjs2-size-x1300": "calc(var(--sjs2-base-unit-size) * 13)", + "--sjs2-size-x1400": "calc(var(--sjs2-base-unit-size) * 14)", + "--sjs2-size-x1500": "calc(var(--sjs2-base-unit-size) * 15)", + "--sjs2-radius-x000": "calc(var(--sjs2-base-unit-radius) * 0)", + "--sjs2-radius-x025": "calc(var(--sjs2-base-unit-radius) * 0.25)", + "--sjs2-radius-x050": "calc(var(--sjs2-base-unit-radius) * 0.50)", + "--sjs2-radius-x075": "calc(var(--sjs2-base-unit-radius) * 0.75)", + "--sjs2-radius-x100": "calc(var(--sjs2-base-unit-radius) * 1)", + "--sjs2-radius-x150": "calc(var(--sjs2-base-unit-radius) * 1.50)", + "--sjs2-radius-x200": "calc(var(--sjs2-base-unit-radius) * 2)", + "--sjs2-radius-x250": "calc(var(--sjs2-base-unit-radius) * 2.50)", + "--sjs2-radius-x300": "calc(var(--sjs2-base-unit-radius) * 3)", + "--sjs2-radius-x400": "calc(var(--sjs2-base-unit-radius) * 4)", + "--sjs2-radius-x500": "calc(var(--sjs2-base-unit-radius) * 5)", + "--sjs2-radius-x600": "calc(var(--sjs2-base-unit-radius) * 6)", + "--sjs2-radius-x700": "calc(var(--sjs2-base-unit-radius) * 7)", + "--sjs2-radius-x800": "calc(var(--sjs2-base-unit-radius) * 8)", + "--sjs2-radius-round": "9999px", + "--sjs2-spacing-x000": "calc(var(--sjs2-base-unit-spacing) * 0)", + "--sjs2-spacing-x025": "calc(var(--sjs2-base-unit-spacing) * 0.25)", + "--sjs2-spacing-x050": "calc(var(--sjs2-base-unit-spacing) * 0.50)", + "--sjs2-spacing-x075": "calc(var(--sjs2-base-unit-spacing) * 0.75)", + "--sjs2-spacing-x100": "calc(var(--sjs2-base-unit-spacing) * 1)", + "--sjs2-spacing-x150": "calc(var(--sjs2-base-unit-spacing) * 1.5)", + "--sjs2-spacing-x200": "calc(var(--sjs2-base-unit-spacing) * 2)", + "--sjs2-spacing-x250": "calc(var(--sjs2-base-unit-spacing) * 2.50)", + "--sjs2-spacing-x300": "calc(var(--sjs2-base-unit-spacing) * 3)", + "--sjs2-spacing-x400": "calc(var(--sjs2-base-unit-spacing) * 4)", + "--sjs2-spacing-x500": "calc(var(--sjs2-base-unit-spacing) * 5)", + "--sjs2-spacing-x600": "calc(var(--sjs2-base-unit-spacing) * 6)", + "--sjs2-spacing-x700": "calc(var(--sjs2-base-unit-spacing) * 7)", + "--sjs2-spacing-x800": "calc(var(--sjs2-base-unit-spacing) * 8)", + "--sjs2-spacing-negative-x025": "calc(var(--sjs2-base-unit-spacing) * -0.25)", + "--sjs2-spacing-negative-x050": "calc(var(--sjs2-base-unit-spacing) * -0.50)", + "--sjs2-spacing-negative-x075": "calc(var(--sjs2-base-unit-spacing) * -0.75)", + "--sjs2-spacing-negative-x100": "calc(var(--sjs2-base-unit-spacing) * -1)", + "--sjs2-spacing-negative-x150": "calc(var(--sjs2-base-unit-spacing) * -1.5)", + "--sjs2-spacing-negative-x200": "calc(var(--sjs2-base-unit-spacing) * -2)", + "--sjs2-spacing-negative-x250": "calc(var(--sjs2-base-unit-spacing) * -2.50)", + "--sjs2-spacing-negative-x300": "calc(var(--sjs2-base-unit-spacing) * -3)", + "--sjs2-spacing-negative-x400": "calc(var(--sjs2-base-unit-spacing) * -4)", + "--sjs2-spacing-negative-x500": "calc(var(--sjs2-base-unit-spacing) * -5)", + "--sjs2-spacing-negative-x600": "calc(var(--sjs2-base-unit-spacing) * -6)", + "--sjs2-spacing-negative-x700": "calc(var(--sjs2-base-unit-spacing) * -7)", + "--sjs2-spacing-negative-x800": "calc(var(--sjs2-base-unit-spacing) * -8)", + "--sjs2-opacity-x000": "calc(var(--sjs2-base-unit-opacity) * 0)", + "--sjs2-opacity-x005": "calc(var(--sjs2-base-unit-opacity) * 5)", + "--sjs2-opacity-x010": "calc(var(--sjs2-base-unit-opacity) * 10)", + "--sjs2-opacity-x015": "calc(var(--sjs2-base-unit-opacity) * 15)", + "--sjs2-opacity-x020": "calc(var(--sjs2-base-unit-opacity) * 20)", + "--sjs2-opacity-x025": "calc(var(--sjs2-base-unit-opacity) * 25)", + "--sjs2-opacity-x030": "calc(var(--sjs2-base-unit-opacity) * 30)", + "--sjs2-opacity-x035": "calc(var(--sjs2-base-unit-opacity) * 35)", + "--sjs2-opacity-x040": "calc(var(--sjs2-base-unit-opacity) * 40)", + "--sjs2-opacity-x045": "calc(var(--sjs2-base-unit-opacity) * 45)", + "--sjs2-opacity-x050": "calc(var(--sjs2-base-unit-opacity) * 50)", + "--sjs2-opacity-x055": "calc(var(--sjs2-base-unit-opacity) * 55)", + "--sjs2-opacity-x060": "calc(var(--sjs2-base-unit-opacity) * 60)", + "--sjs2-opacity-x065": "calc(var(--sjs2-base-unit-opacity) * 65)", + "--sjs2-opacity-x070": "calc(var(--sjs2-base-unit-opacity) * 70)", + "--sjs2-opacity-x075": "calc(var(--sjs2-base-unit-opacity) * 75)", + "--sjs2-opacity-x080": "calc(var(--sjs2-base-unit-opacity) * 80)", + "--sjs2-opacity-x085": "calc(var(--sjs2-base-unit-opacity) * 85)", + "--sjs2-opacity-x090": "calc(var(--sjs2-base-unit-opacity) * 90)", + "--sjs2-opacity-x095": "calc(var(--sjs2-base-unit-opacity) * 95)", + "--sjs2-opacity-x100": "calc(var(--sjs2-base-unit-opacity) * 100)", + "--sjs2-border-width-x000": "calc(var(--sjs2-base-unit-border-width) * 0)", + "--sjs2-border-width-x100": "calc(var(--sjs2-base-unit-border-width) * 1)", + "--sjs2-border-width-x200": "calc(var(--sjs2-base-unit-border-width) * 2)", + "--sjs2-border-width-x400": "calc(var(--sjs2-base-unit-border-width) * 4)", + "--sjs2-font-weight-regular": "Regular", + "--sjs2-font-weight-medium": "Medium", + "--sjs2-font-weight-semibold": "SemiBold", + "--sjs2-font-weight-bold": "Bold", + "--sjs2-font-size-x000": "calc(var(--sjs2-base-unit-font-size) * 0)", + "--sjs2-font-size-x100": "calc(var(--sjs2-base-unit-font-size) * 1)", + "--sjs2-font-size-x150": "calc(var(--sjs2-base-unit-font-size) * 1.5)", + "--sjs2-font-size-x200": "calc(var(--sjs2-base-unit-font-size) * 2)", + "--sjs2-font-size-x250": "calc(var(--sjs2-base-unit-font-size) * 2.5)", + "--sjs2-font-size-x300": "calc(var(--sjs2-base-unit-font-size) * 3)", + "--sjs2-font-size-x350": "calc(var(--sjs2-base-unit-font-size) * 3.5)", + "--sjs2-font-size-x400": "calc(var(--sjs2-base-unit-font-size) * 4)", + "--sjs2-font-size-x500": "calc(var(--sjs2-base-unit-font-size) * 5)", + "--sjs2-font-size-x600": "calc(var(--sjs2-base-unit-font-size) * 6)", + "--sjs2-line-height-x000": "calc(var(--sjs2-base-unit-line-height) * 0)", + "--sjs2-line-height-x100": "calc(var(--sjs2-base-unit-line-height) * 1)", + "--sjs2-line-height-x200": "calc(var(--sjs2-base-unit-line-height) * 2)", + "--sjs2-line-height-x300": "calc(var(--sjs2-base-unit-line-height) * 3)", + "--sjs2-line-height-x400": "calc(var(--sjs2-base-unit-line-height) * 4)", + "--sjs2-line-height-x500": "calc(var(--sjs2-base-unit-line-height) * 5)", + "--sjs2-line-height-x600": "calc(var(--sjs2-base-unit-line-height) * 6)", + "--sjs2-text-case-default": "none", + "--sjs2-text-case-uppercase": "uppercase", + "--sjs2-palette-gray-100": "#F5F5F5", + "--sjs2-palette-gray-150": "#EDEDED", + "--sjs2-palette-gray-200": "#E5E5E5", + "--sjs2-palette-gray-250": "#D4D4D4", + "--sjs2-palette-gray-300": "#CDCDCD", + "--sjs2-palette-gray-400": "#B3B2B2", + "--sjs2-palette-gray-500": "#8E8E8E", + "--sjs2-palette-gray-600": "#5F5E61", + "--sjs2-palette-gray-700": "#424146", + "--sjs2-palette-gray-750": "#36353C", + "--sjs2-palette-gray-800": "#2D2C33", + "--sjs2-palette-gray-900": "#1C1B20", + "--sjs2-palette-gray-950": "#161519", + "--sjs2-palette-gray-999": "#111014", + "--sjs2-palette-gray-000": "#fff", + "--sjs2-palette-red-400": "#ff6e84", + "--sjs2-palette-red-600": "#E50A3E", + "--sjs2-palette-red-700": "#C30935", + "--sjs2-palette-green-400": "#15CDAB", + "--sjs2-palette-green-600": "#19B394", + "--sjs2-palette-green-700": "#15947A", + "--sjs2-palette-blue-400": "#66B4FC", + "--sjs2-palette-blue-600": "#437FD9", + "--sjs2-palette-blue-700": "#2A6CD0", + "--sjs2-palette-yellow-400": "#FEC64A", + "--sjs2-palette-yellow-600": "#FF9814", + "--sjs2-palette-yellow-700": "#F08700", + "--sjs2-palette-violet-400": "#C36FF4", + "--sjs2-palette-violet-600": "#A62CEC", + "--sjs2-palette-violet-700": "#9614E1", + "--sjs2-palette-olive-400": "#6FC648", + "--sjs2-palette-olive-600": "#4FAF24", + "--sjs2-palette-olive-700": "#41901E", + "--sjs2-palette-purple-400": "#A190FA", + "--sjs2-palette-purple-600": "#6E5BD1", + "--sjs2-palette-purple-700": "#5640C9", + "--sjs2-palette-indianred-400": "#F9786A", + "--sjs2-palette-indianred-600": "#AF496B", + "--sjs2-palette-indianred-700": "#973F5C", + "--sjs2-radius-semantic-form": "var(--sjs2-radius-x100)", + "--sjs2-radius-semantic-form-item": "var(--sjs2-radius-x050)", + "--sjs2-radius-control-action": "var(--sjs2-radius-semantic-form)", + "--sjs2-radius-control-action-icon": "var(--sjs2-radius-semantic-form)", + "--sjs2-radius-control-button": "var(--sjs2-radius-semantic-form)", + "--sjs2-radius-control-menu-item": "var(--sjs2-radius-semantic-form)", + "--sjs2-radius-control-drop-item": "var(--sjs2-radius-x100)", + "--sjs2-radius-control-checkbox": "var(--sjs2-radius-semantic-form-item)", + "--sjs2-radius-control-rating": "var(--sjs2-radius-round)", + "--sjs2-radius-control-ranking": "var(--sjs2-radius-round)", + "--sjs2-radius-control-boolean": "var(--sjs2-radius-round)", + "--sjs2-radius-control-boolean-item": "var(--sjs2-radius-round)", + "--sjs2-radius-control-toggle": "var(--sjs2-radius-round)", + "--sjs2-radius-control-toggle-thumb": "var(--sjs2-radius-round)", + "--sjs2-radius-control-track": "var(--sjs2-radius-round)", + "--sjs2-radius-control-track-item": "var(--sjs2-radius-round)", + "--sjs2-radius-control-track-thumb": "var(--sjs2-radius-round)", + "--sjs2-radius-container-panel": "var(--sjs2-radius-x150)", + "--sjs2-radius-container-panel-nested": "var(--sjs2-radius-x100)", + "--sjs2-radius-container-menu": "var(--sjs2-radius-x250)", + "--sjs2-radius-container-drop": "var(--sjs2-radius-x200)", + "--sjs2-radius-container-modal": "var(--sjs2-radius-x300)", + "--sjs2-radius-container-notifier": "var(--sjs2-radius-x200)", + "--sjs2-radius-container-tooltip": "var(--sjs2-radius-x050)", + "--sjs2-radius-container-drag": "var(--sjs2-radius-semantic-form)", + "--sjs2-layout-control-formbox-small-horizontal": "var(--sjs2-spacing-x050)", + "--sjs2-layout-control-formbox-small-vertical": "var(--sjs2-spacing-x050)", + "--sjs2-layout-control-formbox-small-gap": "var(--sjs2-spacing-x050)", + "--sjs2-layout-control-formbox-medium-horizontal": "var(--sjs2-spacing-x050)", + "--sjs2-layout-control-formbox-medium-vertical": "var(--sjs2-spacing-x050)", + "--sjs2-layout-control-formbox-medium-gap": "var(--sjs2-spacing-x050)", + "--sjs2-layout-control-message-small-spacer": "var(--sjs2-spacing-x100)", + "--sjs2-layout-control-message-small-horizontal": "var(--sjs2-spacing-x150)", + "--sjs2-layout-control-message-small-vertical": "var(--sjs2-spacing-x100)", + "--sjs2-layout-control-message-small-gap": "var(--sjs2-spacing-x100)", + "--sjs2-layout-control-message-medium-spacer": "var(--sjs2-spacing-x100)", + "--sjs2-layout-control-message-medium-horizontal": "var(--sjs2-spacing-x150)", + "--sjs2-layout-control-message-medium-vertical": "var(--sjs2-spacing-x100)", + "--sjs2-layout-control-message-medium-gap": "var(--sjs2-spacing-x100)", + "--sjs2-layout-control-input-small-content-vertical": "var(--sjs2-spacing-x050)", + "--sjs2-layout-control-input-small-content-horizontal": "var(--sjs2-spacing-x100)", + "--sjs2-layout-control-input-small-swatch-vertical": "var(--sjs2-spacing-x050)", + "--sjs2-layout-control-input-small-swatch-left": "var(--sjs2-spacing-x100)", + "--sjs2-layout-control-input-small-swatch-right": "var(--sjs2-spacing-x000)", + "--sjs2-layout-control-input-small-icon-vertical": "var(--sjs2-spacing-x050)", + "--sjs2-layout-control-input-small-icon-left": "var(--sjs2-spacing-x050)", + "--sjs2-layout-control-input-small-icon-right": "var(--sjs2-spacing-x000)", + "--sjs2-layout-control-input-small-label-vertical": "var(--sjs2-spacing-x050)", + "--sjs2-layout-control-input-small-label-horizontal": "var(--sjs2-spacing-x100)", + "--sjs2-layout-control-input-small-group-gap": "var(--sjs2-spacing-x050)", + "--sjs2-layout-control-input-small-limit-vertical": "var(--sjs2-spacing-x100)", + "--sjs2-layout-control-input-small-limit-left": "var(--sjs2-spacing-x100)", + "--sjs2-layout-control-input-small-limit-right": "var(--sjs2-spacing-x100)", + "--sjs2-layout-control-input-medium-content-vertical": "var(--sjs2-spacing-x100)", + "--sjs2-layout-control-input-medium-content-horizontal": "var(--sjs2-spacing-x150)", + "--sjs2-layout-control-input-medium-swatch-vertical": "var(--sjs2-spacing-x100)", + "--sjs2-layout-control-input-medium-swatch-left": "var(--sjs2-spacing-x150)", + "--sjs2-layout-control-input-medium-swatch-right": "var(--sjs2-spacing-x000)", + "--sjs2-layout-control-input-medium-icon-vertical": "var(--sjs2-spacing-x100)", + "--sjs2-layout-control-input-medium-icon-left": "var(--sjs2-spacing-x100)", + "--sjs2-layout-control-input-medium-icon-right": "var(--sjs2-spacing-x000)", + "--sjs2-layout-control-input-medium-label-vertical": "var(--sjs2-spacing-x100)", + "--sjs2-layout-control-input-medium-label-horizontal": "var(--sjs2-spacing-x150)", + "--sjs2-layout-control-input-medium-group-gap": "var(--sjs2-spacing-x050)", + "--sjs2-layout-control-input-medium-limit-vertical": "var(--sjs2-spacing-x150)", + "--sjs2-layout-control-input-medium-limit-left": "var(--sjs2-spacing-x100)", + "--sjs2-layout-control-input-medium-limit-right": "var(--sjs2-spacing-x100)", + "--sjs2-layout-control-action-xx-small-label-vertical": "var(--sjs2-spacing-x000)", + "--sjs2-layout-control-action-xx-small-label-horizontal": "var(--sjs2-spacing-x050)", + "--sjs2-layout-control-action-xx-small-icon-vertical": "var(--sjs2-spacing-x000)", + "--sjs2-layout-control-action-xx-small-icon-horizontal": "var(--sjs2-spacing-x000)", + "--sjs2-layout-control-action-xx-small-box-vertical": "var(--sjs2-spacing-x050)", + "--sjs2-layout-control-action-xx-small-box-horizontal": "var(--sjs2-spacing-x050)", + "--sjs2-layout-control-action-xx-small-box-gap": "var(--sjs2-spacing-x000)", + "--sjs2-layout-control-action-xx-small-addon-vertical": "var(--sjs2-spacing-x000)", + "--sjs2-layout-control-action-xx-small-addon-horizontal": "var(--sjs2-spacing-x000)", + "--sjs2-layout-control-action-x-small-label-horizontal": "var(--sjs2-spacing-x050)", + "--sjs2-layout-control-action-x-small-label-vertical": "var(--sjs2-spacing-x050)", + "--sjs2-layout-control-action-x-small-icon-vertical": "var(--sjs2-spacing-x050)", + "--sjs2-layout-control-action-x-small-icon-horizontal": "var(--sjs2-spacing-x050)", + "--sjs2-layout-control-action-x-small-box-vertical": "var(--sjs2-spacing-x050)", + "--sjs2-layout-control-action-x-small-box-horizontal": "var(--sjs2-spacing-x050)", + "--sjs2-layout-control-action-x-small-box-gap": "var(--sjs2-spacing-x000)", + "--sjs2-layout-control-action-x-small-addon-vertical": "var(--sjs2-spacing-x050)", + "--sjs2-layout-control-action-x-small-addon-horizontal": "var(--sjs2-spacing-x050)", + "--sjs2-layout-control-action-small-label-horizontal": "var(--sjs2-spacing-x075)", + "--sjs2-layout-control-action-small-label-vertical": "var(--sjs2-spacing-x000)", + "--sjs2-layout-control-action-small-icon-vertical": "var(--sjs2-spacing-x000)", + "--sjs2-layout-control-action-small-icon-horizontal": "var(--sjs2-spacing-x000)", + "--sjs2-layout-control-action-small-box-vertical": "var(--sjs2-spacing-x100)", + "--sjs2-layout-control-action-small-box-horizontal": "var(--sjs2-spacing-x100)", + "--sjs2-layout-control-action-small-box-gap": "var(--sjs2-spacing-x000)", + "--sjs2-layout-control-action-small-addon-vertical": "var(--sjs2-spacing-x050)", + "--sjs2-layout-control-action-small-addon-horizontal": "var(--sjs2-spacing-x050)", + "--sjs2-layout-control-action-medium-label-horizontal": "var(--sjs2-spacing-x100)", + "--sjs2-layout-control-action-medium-label-vertical": "var(--sjs2-spacing-x000)", + "--sjs2-layout-control-action-medium-icon-vertical": "var(--sjs2-spacing-x000)", + "--sjs2-layout-control-action-medium-icon-horizontal": "var(--sjs2-spacing-x000)", + "--sjs2-layout-control-action-medium-box-vertical": "var(--sjs2-spacing-x150)", + "--sjs2-layout-control-action-medium-box-horizontal": "var(--sjs2-spacing-x150)", + "--sjs2-layout-control-action-medium-box-gap": "var(--sjs2-spacing-x000)", + "--sjs2-layout-control-action-medium-addon-vertical": "var(--sjs2-spacing-x050)", + "--sjs2-layout-control-action-medium-addon-horizontal": "var(--sjs2-spacing-x050)", + "--sjs2-layout-control-action-large-label-horizontal": "var(--sjs2-spacing-x150)", + "--sjs2-layout-control-action-large-label-vertical": "var(--sjs2-spacing-x000)", + "--sjs2-layout-control-action-large-icon-vertical": "var(--sjs2-spacing-x000)", + "--sjs2-layout-control-action-large-icon-horizontal": "var(--sjs2-spacing-x000)", + "--sjs2-layout-control-action-large-box-vertical": "var(--sjs2-spacing-x200)", + "--sjs2-layout-control-action-large-box-horizontal": "var(--sjs2-spacing-x200)", + "--sjs2-layout-control-action-large-box-gap": "var(--sjs2-spacing-x000)", + "--sjs2-layout-control-action-large-addon-vertical": "var(--sjs2-spacing-x050)", + "--sjs2-layout-control-action-large-addon-horizontal": "var(--sjs2-spacing-x050)", + "--sjs2-layout-control-caption-small-box-left": "var(--sjs2-spacing-x000)", + "--sjs2-layout-control-caption-small-box-right": "var(--sjs2-spacing-x050)", + "--sjs2-layout-control-caption-small-box-vertical": "var(--sjs2-spacing-x000)", + "--sjs2-layout-control-caption-small-box-gap": "var(--sjs2-spacing-x050)", + "--sjs2-layout-control-caption-small-group-gap": "var(--sjs2-spacing-x000)", + "--sjs2-layout-control-caption-small-description-horizontal": "var(--sjs2-spacing-x000)", + "--sjs2-layout-control-caption-small-description-top": "var(--sjs2-spacing-x000)", + "--sjs2-layout-control-caption-small-description-bottom": "var(--sjs2-spacing-x200)", + "--sjs2-layout-control-caption-small-caption-horizontal": "var(--sjs2-spacing-x000)", + "--sjs2-layout-control-caption-small-caption-vertical": "var(--sjs2-spacing-x100)", + "--sjs2-layout-control-caption-medium-box-left": "var(--sjs2-spacing-x000)", + "--sjs2-layout-control-caption-medium-box-right": "var(--sjs2-spacing-x050)", + "--sjs2-layout-control-caption-medium-box-vertical": "var(--sjs2-spacing-x000)", + "--sjs2-layout-control-caption-medium-box-gap": "var(--sjs2-spacing-x050)", + "--sjs2-layout-control-caption-medium-group-gap": "var(--sjs2-spacing-x000)", + "--sjs2-layout-control-caption-medium-description-horizontal": "var(--sjs2-spacing-x000)", + "--sjs2-layout-control-caption-medium-description-top": "var(--sjs2-spacing-x000)", + "--sjs2-layout-control-caption-medium-description-bottom": "var(--sjs2-spacing-x200)", + "--sjs2-layout-control-caption-medium-caption-horizontal": "var(--sjs2-spacing-x000)", + "--sjs2-layout-control-caption-medium-caption-vertical": "var(--sjs2-spacing-x100)", + "--sjs2-layout-container-drop-horizontal": "var(--sjs2-spacing-x100)", + "--sjs2-layout-container-drop-vertical": "var(--sjs2-spacing-x100)", + "--sjs2-size-semantic-xx-small": "var(--sjs2-size-x300)", + "--sjs2-size-semantic-x-small": "var(--sjs2-size-x400)", + "--sjs2-size-semantic-small": "var(--sjs2-size-x500)", + "--sjs2-size-semantic-medium": "var(--sjs2-size-x600)", + "--sjs2-size-semantic-large": "var(--sjs2-size-x700)", + "--sjs2-size-icon-small": "var(--sjs2-size-x200)", + "--sjs2-size-icon-medium": "var(--sjs2-size-x300)", + "--sjs2-size-icon-large": "var(--sjs2-size-x400)", + "--sjs2-is-panelless": "false", + "--sjs2-typography-font-family-default": "Open Sans", + "--sjs2-typography-font-family-code": "DM Mono", + "--sjs2-typography-font-size-small": "var(--sjs2-font-size-x150)", + "--sjs2-typography-font-size-default": "var(--sjs2-font-size-x200)", + "--sjs2-typography-font-size-medium": "var(--sjs2-font-size-x300)", + "--sjs2-typography-font-size-large": "var(--sjs2-font-size-x400)", + "--sjs2-typography-line-height-small": "var(--sjs2-line-height-x200)", + "--sjs2-typography-line-height-default": "var(--sjs2-line-height-x300)", + "--sjs2-typography-line-height-medium": "var(--sjs2-line-height-x400)", + "--sjs2-typography-line-height-large": "var(--sjs2-line-height-x500)", + "--sjs2-typography-font-weight-default": "var(--sjs2-font-weight-regular)", + "--sjs2-typography-font-weight-strong": "var(--sjs2-font-weight-semibold)", + "--sjs2-color-project-brand-400": "hsl(from var(--sjs2-color-project-brand-600) h s calc(l * 1.1))", + "--sjs2-color-project-brand-600": "#19B394", + "--sjs2-color-project-brand-700": "hsl(from var(--sjs2-color-project-brand-600) h s calc(l * 0.85))", + "--sjs2-color-project-accent-400": "hsl(from var(--sjs2-color-project-accent-600) h s calc(l * 1.1))", + "--sjs2-color-project-accent-600": "#19B394", + "--sjs2-color-project-accent-700": "hsl(from var(--sjs2-color-project-accent-600) h s calc(l * 0.85))", + "--sjs2-color-utility-body": "var(--sjs2-palette-gray-000)", + "--sjs2-color-utility-surface": "#1c1b200d", + "--sjs2-color-utility-surface-muted": "#1c1b200d", + "--sjs2-color-utility-sheet": "var(--sjs2-palette-gray-000)", + "--sjs2-color-utility-scrollbar": "rgba(from var(--sjs2-palette-gray-999) r g b / var(--sjs2-opacity-x015))", + "--sjs2-color-utility-a11y": "rgba(from var(--sjs2-palette-blue-400) r g b / var(--sjs2-opacity-x060))", + "--sjs2-color-utility-overlay-screen": "rgba(from var(--sjs2-palette-gray-700) r g b / var(--sjs2-opacity-x060))", + "--sjs2-color-utility-overlay-border": "rgba(from var(--sjs2-palette-gray-900) r g b / var(--sjs2-opacity-x040))", + "--sjs2-color-utility-shadow-surface-default": "rgba(from var(--sjs2-palette-gray-999) r g b / var(--sjs2-opacity-x010))", + "--sjs2-color-utility-shadow-surface-hovered": "rgba(from var(--sjs2-palette-gray-999) r g b / var(--sjs2-opacity-x010))", + "--sjs2-color-utility-shadow-surface-pressed": "rgba(from var(--sjs2-palette-gray-999) r g b / var(--sjs2-opacity-x010))", + "--sjs2-color-utility-shadow-surface-focused": "rgba(from var(--sjs2-palette-gray-999) r g b / var(--sjs2-opacity-x010))", + "--sjs2-color-utility-shadow-surface-disabled": "rgba(from var(--sjs2-palette-gray-999) r g b / var(--sjs2-opacity-x010))", + "--sjs2-color-utility-shadow-surface-dragging": "rgba(from #004C44 r g b / var(--sjs2-opacity-x015))", + "--sjs2-color-utility-shadow-elevated-default": "rgba(from #004C44 r g b / var(--sjs2-opacity-x015))", + "--sjs2-color-utility-shadow-floating-default": "rgba(from #004C44 r g b / var(--sjs2-opacity-x020))", + "--sjs2-color-bg-basic-primary": "var(--sjs2-palette-gray-000)", + "--sjs2-color-bg-basic-secondary": "rgba(from var(--sjs2-palette-gray-900) r g b / var(--sjs2-opacity-x005))", + "--sjs2-color-bg-basic-tertiary": "rgba(from var(--sjs2-palette-gray-900) r g b / var(--sjs2-opacity-x010))", + "--sjs2-color-bg-basic-primary-dim": "rgba(from var(--sjs2-palette-gray-900) r g b / var(--sjs2-opacity-x005))", + "--sjs2-color-bg-basic-secondary-dim": "rgba(from var(--sjs2-palette-gray-900) r g b / var(--sjs2-opacity-x010))", + "--sjs2-color-bg-basic-tertiary-dim": "rgba(from var(--sjs2-palette-gray-900) r g b / var(--sjs2-opacity-x015))", + "--sjs2-color-bg-brand-primary": "var(--sjs2-color-project-brand-600)", + "--sjs2-color-bg-brand-secondary": "rgba(from var(--sjs2-color-project-brand-600) r g b / var(--sjs2-opacity-x010))", + "--sjs2-color-bg-brand-tertiary": "rgba(from var(--sjs2-color-project-brand-600) r g b / var(--sjs2-opacity-x000))", + "--sjs2-color-bg-brand-primary-dim": "var(--sjs2-color-project-brand-700)", + "--sjs2-color-bg-brand-secondary-dim": "rgba(from var(--sjs2-color-project-brand-600) r g b / var(--sjs2-opacity-x015))", + "--sjs2-color-bg-brand-tertiary-dim": "rgba(from var(--sjs2-color-project-brand-600) r g b / var(--sjs2-opacity-x010))", + "--sjs2-color-bg-accent-primary": "var(--sjs2-color-project-accent-600)", + "--sjs2-color-bg-accent-secondary": "rgba(from var(--sjs2-color-project-accent-600) r g b / var(--sjs2-opacity-x010))", + "--sjs2-color-bg-accent-tertiary": "rgba(from var(--sjs2-color-project-accent-600) r g b / var(--sjs2-opacity-x000))", + "--sjs2-color-bg-accent-primary-dim": "var(--sjs2-color-project-accent-700)", + "--sjs2-color-bg-accent-secondary-dim": "rgba(from var(--sjs2-color-project-accent-600) r g b / var(--sjs2-opacity-x015))", + "--sjs2-color-bg-accent-tertiary-dim": "rgba(from var(--sjs2-color-project-accent-600) r g b / var(--sjs2-opacity-x010))", + "--sjs2-color-bg-note-primary": "var(--sjs2-palette-blue-600)", + "--sjs2-color-bg-note-secondary": "rgba(from var(--sjs2-palette-blue-600) r g b / var(--sjs2-opacity-x010))", + "--sjs2-color-bg-note-tertiary": "rgba(from var(--sjs2-palette-blue-600) r g b / var(--sjs2-opacity-x000))", + "--sjs2-color-bg-note-primary-dim": "var(--sjs2-palette-blue-700)", + "--sjs2-color-bg-note-secondary-dim": "rgba(from var(--sjs2-palette-blue-600) r g b / var(--sjs2-opacity-x015))", + "--sjs2-color-bg-note-tertiary-dim": "rgba(from var(--sjs2-palette-blue-600) r g b / var(--sjs2-opacity-x010))", + "--sjs2-color-bg-neutral-primary": "var(--sjs2-palette-gray-900)", + "--sjs2-color-bg-neutral-secondary": "rgba(from var(--sjs2-palette-gray-900) r g b / var(--sjs2-opacity-x010))", + "--sjs2-color-bg-neutral-tertiary": "rgba(from var(--sjs2-palette-gray-900) r g b / var(--sjs2-opacity-x000))", + "--sjs2-color-bg-neutral-primary-dim": "var(--sjs2-palette-gray-700)", + "--sjs2-color-bg-neutral-secondary-dim": "rgba(from var(--sjs2-palette-gray-900) r g b / var(--sjs2-opacity-x010))", + "--sjs2-color-bg-neutral-tertiary-dim": "rgba(from var(--sjs2-palette-gray-900) r g b / var(--sjs2-opacity-x005))", + "--sjs2-color-bg-positive-primary": "var(--sjs2-palette-green-600)", + "--sjs2-color-bg-positive-secondary": "rgba(from var(--sjs2-palette-green-600) r g b / var(--sjs2-opacity-x010))", + "--sjs2-color-bg-positive-tertiary": "rgba(from var(--sjs2-palette-green-600) r g b / var(--sjs2-opacity-x000))", + "--sjs2-color-bg-positive-primary-dim": "var(--sjs2-palette-green-700)", + "--sjs2-color-bg-positive-secondary-dim": "rgba(from var(--sjs2-palette-green-600) r g b / var(--sjs2-opacity-x015))", + "--sjs2-color-bg-positive-tertiary-dim": "rgba(from var(--sjs2-palette-green-600) r g b / var(--sjs2-opacity-x010))", + "--sjs2-color-bg-warning-primary": "var(--sjs2-palette-yellow-600)", + "--sjs2-color-bg-warning-secondary": "rgba(from var(--sjs2-palette-yellow-600) r g b / var(--sjs2-opacity-x010))", + "--sjs2-color-bg-warning-tertiary": "rgba(from var(--sjs2-palette-yellow-600) r g b / var(--sjs2-opacity-x000))", + "--sjs2-color-bg-warning-primary-dim": "var(--sjs2-palette-yellow-700)", + "--sjs2-color-bg-warning-secondary-dim": "rgba(from var(--sjs2-palette-yellow-600) r g b / var(--sjs2-opacity-x015))", + "--sjs2-color-bg-warning-tertiary-dim": "rgba(from var(--sjs2-palette-yellow-600) r g b / var(--sjs2-opacity-x010))", + "--sjs2-color-bg-alert-primary": "var(--sjs2-palette-red-600)", + "--sjs2-color-bg-alert-secondary": "rgba(from var(--sjs2-palette-red-600) r g b / var(--sjs2-opacity-x010))", + "--sjs2-color-bg-alert-tertiary": "rgba(from var(--sjs2-palette-red-600) r g b / var(--sjs2-opacity-x000))", + "--sjs2-color-bg-alert-primary-dim": "var(--sjs2-palette-red-700)", + "--sjs2-color-bg-alert-secondary-dim": "rgba(from var(--sjs2-palette-red-600) r g b / var(--sjs2-opacity-x015))", + "--sjs2-color-bg-alert-tertiary-dim": "rgba(from var(--sjs2-palette-red-600) r g b / var(--sjs2-opacity-x010))", + "--sjs2-color-bg-static-main-primary": "var(--sjs2-palette-gray-900)", + "--sjs2-color-bg-static-main-secondary": "rgba(from var(--sjs2-palette-gray-900) r g b / var(--sjs2-opacity-x010))", + "--sjs2-color-bg-static-main-primary-dim": "var(--sjs2-palette-gray-700)", + "--sjs2-color-bg-static-main-secondary-dim": "rgba(from var(--sjs2-palette-gray-900) r g b / var(--sjs2-opacity-x015))", + "--sjs2-color-bg-static-sub-primary": "var(--sjs2-palette-gray-000)", + "--sjs2-color-bg-static-sub-secondary": "rgba(from var(--sjs2-palette-gray-000) r g b / var(--sjs2-opacity-x010))", + "--sjs2-color-bg-static-sub-primary-dim": "hsl(from var(--sjs2-palette-gray-100) h s calc(l * 1.1))", + "--sjs2-color-bg-static-sub-secondary-dim": "rgba(from var(--sjs2-palette-gray-000) r g b / var(--sjs2-opacity-x015))", + "--sjs2-color-bg-state-common-disabled": "var(--sjs2-palette-gray-250)", + "--sjs2-color-fg-basic-primary": "var(--sjs2-palette-gray-900)", + "--sjs2-color-fg-basic-primary-muted": "var(--sjs2-palette-gray-700)", + "--sjs2-color-fg-basic-secondary": "rgba(from var(--sjs2-palette-gray-900) r g b / var(--sjs2-opacity-x060))", + "--sjs2-color-fg-basic-tertiary": "rgba(from var(--sjs2-palette-gray-900) r g b / var(--sjs2-opacity-x040))", + "--sjs2-color-fg-neutral-primary": "var(--sjs2-palette-gray-000)", + "--sjs2-color-fg-brand-primary": "var(--sjs2-color-project-accent-600)", + "--sjs2-color-fg-accent-primary": "var(--sjs2-color-project-accent-600)", + "--sjs2-color-fg-note-primary": "var(--sjs2-palette-blue-700)", + "--sjs2-color-fg-positive-primary": "var(--sjs2-palette-green-600)", + "--sjs2-color-fg-warning-primary": "var(--sjs2-palette-yellow-700)", + "--sjs2-color-fg-alert-primary": "var(--sjs2-palette-red-700)", + "--sjs2-color-fg-static-main-primary": "var(--sjs2-palette-gray-000)", + "--sjs2-color-fg-static-sub-primary": "var(--sjs2-palette-gray-900)", + "--sjs2-color-fg-state-common-disabled": "rgba(from var(--sjs2-palette-gray-900) r g b / var(--sjs2-opacity-x040))", + "--sjs2-color-border-basic-primary": "var(--sjs2-palette-gray-900)", + "--sjs2-color-border-basic-secondary": "var(--sjs2-palette-gray-250)", + "--sjs2-color-border-brand-primary": "var(--sjs2-color-project-brand-600)", + "--sjs2-color-border-accent-primary": "var(--sjs2-color-project-accent-600)", + "--sjs2-color-border-note-primary": "var(--sjs2-palette-blue-600)", + "--sjs2-color-border-positive-primary": "var(--sjs2-palette-green-600)", + "--sjs2-color-border-warning-primary": "var(--sjs2-palette-yellow-600)", + "--sjs2-color-border-alert-primary": "var(--sjs2-palette-red-600)", + "--sjs2-color-border-neutral-primary": "var(--sjs2-palette-gray-000)", + "--sjs2-color-border-static-main-primary": "var(--sjs2-palette-gray-000)", + "--sjs2-color-border-static-sub-primary": "var(--sjs2-palette-gray-900)", + "--sjs2-color-control-formbox-default-bg": "var(--sjs2-color-bg-basic-secondary)", + "--sjs2-color-control-formbox-default-border": "var(--sjs2-color-border-basic-secondary)", + "--sjs2-color-control-formbox-disabled-bg": "var(--sjs2-color-bg-basic-primary)", + "--sjs2-color-control-formbox-disabled-border": "var(--sjs2-palette-gray-250)", + "--sjs2-color-control-formbox-readonly-bg": "var(--sjs2-color-bg-basic-primary)", + "--sjs2-color-control-formbox-readonly-border": "var(--sjs2-palette-gray-250)", + "--sjs2-color-control-formbox-focused-bg": "var(--sjs2-color-bg-basic-secondary)", + "--sjs2-color-control-formbox-focused-border": "var(--sjs2-color-border-brand-primary)", + "--sjs2-color-control-formbox-invalid-bg": "var(--sjs2-color-bg-basic-secondary)", + "--sjs2-color-control-formbox-invalid-border": "var(--sjs2-color-border-alert-primary)", + "--sjs2-color-control-formbox-highlighted-bg": "var(--sjs2-color-bg-basic-secondary)", + "--sjs2-color-control-formbox-highlighted-border": "var(--sjs2-color-border-basic-primary)", + "--sjs2-color-control-formbox-design-bg": "var(--sjs2-color-bg-basic-secondary)", + "--sjs2-color-control-formbox-design-border": "var(--sjs2-color-border-basic-secondary)", + "--sjs2-color-control-input-default-line": "var(--sjs2-color-border-basic-secondary)", + "--sjs2-color-control-input-default-value": "var(--sjs2-color-fg-basic-primary)", + "--sjs2-color-control-input-default-placeholder": "var(--sjs2-color-fg-basic-secondary)", + "--sjs2-color-control-input-default-label": "var(--sjs2-color-fg-basic-secondary)", + "--sjs2-color-control-input-default-limit": "var(--sjs2-color-fg-basic-secondary)", + "--sjs2-color-control-input-default-icon": "var(--sjs2-color-fg-basic-tertiary)", + "--sjs2-color-control-input-disabled-line": "var(--sjs2-palette-gray-250)", + "--sjs2-color-control-input-disabled-value": "var(--sjs2-palette-gray-250)", + "--sjs2-color-control-input-disabled-placeholder": "var(--sjs2-palette-gray-250)", + "--sjs2-color-control-input-disabled-label": "var(--sjs2-palette-gray-250)", + "--sjs2-color-control-input-disabled-limit": "var(--sjs2-palette-gray-250)", + "--sjs2-color-control-input-disabled-icon": "var(--sjs2-palette-gray-250)", + "--sjs2-color-control-input-readonly-line": "var(--sjs2-palette-gray-250)", + "--sjs2-color-control-input-readonly-value": "var(--sjs2-color-fg-basic-primary)", + "--sjs2-color-control-input-readonly-placeholder": "var(--sjs2-color-fg-basic-secondary)", + "--sjs2-color-control-input-readonly-label": "var(--sjs2-color-fg-basic-secondary)", + "--sjs2-color-control-input-readonly-limit": "var(--sjs2-color-fg-basic-secondary)", + "--sjs2-color-control-input-readonly-icon": "var(--sjs2-color-fg-basic-tertiary)", + "--sjs2-color-control-check-false-default-bg": "var(--sjs2-color-bg-basic-secondary)", + "--sjs2-color-control-check-false-default-border": "var(--sjs2-color-border-basic-secondary)", + "--sjs2-color-control-check-false-disabled-bg": "var(--sjs2-color-bg-basic-primary)", + "--sjs2-color-control-check-false-disabled-border": "var(--sjs2-color-border-basic-secondary)", + "--sjs2-color-control-check-false-readonly-bg": "var(--sjs2-color-bg-basic-primary)", + "--sjs2-color-control-check-false-readonly-border": "var(--sjs2-color-border-basic-secondary)", + "--sjs2-color-control-check-false-focused-bg": "var(--sjs2-color-bg-basic-secondary)", + "--sjs2-color-control-check-false-focused-border": "var(--sjs2-color-border-brand-primary)", + "--sjs2-color-control-check-false-hovered-bg": "var(--sjs2-color-bg-basic-secondary-dim)", + "--sjs2-color-control-check-false-hovered-border": "var(--sjs2-color-border-basic-secondary)", + "--sjs2-color-control-check-false-design-bg": "var(--sjs2-color-bg-basic-secondary)", + "--sjs2-color-control-check-false-design-border": "var(--sjs2-color-border-basic-secondary)", + "--sjs2-color-control-check-true-default-bg": "var(--sjs2-color-bg-brand-primary)", + "--sjs2-color-control-check-true-default-border": "var(--sjs2-color-border-brand-primary)", + "--sjs2-color-control-check-true-default-icon": "var(--sjs2-color-fg-static-main-primary)", + "--sjs2-color-control-check-true-disabled-bg": "var(--sjs2-color-bg-basic-primary)", + "--sjs2-color-control-check-true-disabled-border": "var(--sjs2-color-border-basic-secondary)", + "--sjs2-color-control-check-true-disabled-icon": "var(--sjs2-palette-gray-400)", + "--sjs2-color-control-check-true-readonly-bg": "var(--sjs2-color-bg-basic-primary)", + "--sjs2-color-control-check-true-readonly-border": "var(--sjs2-color-border-basic-secondary)", + "--sjs2-color-control-check-true-readonly-icon": "var(--sjs2-palette-gray-400)", + "--sjs2-color-control-check-true-focused-bg": "var(--sjs2-color-bg-basic-primary)", + "--sjs2-color-control-check-true-focused-border": "var(--sjs2-color-border-brand-primary)", + "--sjs2-color-control-check-true-focused-icon": "var(--sjs2-color-fg-brand-primary)", + "--sjs2-color-control-check-true-hovered-bg": "var(--sjs2-color-bg-brand-primary-dim)", + "--sjs2-color-control-check-true-hovered-border": "var(--sjs2-color-bg-brand-primary-dim)", + "--sjs2-color-control-check-true-hovered-icon": "var(--sjs2-color-fg-static-main-primary)", + "--sjs2-color-control-segmented-false-default-bg": "rgba(from var(--sjs2-color-bg-basic-secondary) r g b / var(--sjs2-opacity-hidden))", + "--sjs2-color-control-segmented-false-default-border": "rgba(from var(--sjs2-color-border-basic-secondary) r g b / var(--sjs2-opacity-hidden))", + "--sjs2-color-control-segmented-false-default-value": "var(--sjs2-color-fg-basic-primary)", + "--sjs2-color-control-segmented-false-disabled-bg": "rgba(from var(--sjs2-color-bg-basic-secondary) r g b / var(--sjs2-opacity-hidden))", + "--sjs2-color-control-segmented-false-disabled-border": "rgba(from var(--sjs2-color-border-basic-secondary) r g b / var(--sjs2-opacity-hidden))", + "--sjs2-color-control-segmented-false-disabled-value": "var(--sjs2-palette-gray-250)", + "--sjs2-color-control-segmented-false-readonly-bg": "rgba(from var(--sjs2-color-bg-basic-secondary) r g b / var(--sjs2-opacity-hidden))", + "--sjs2-color-control-segmented-false-readonly-border": "rgba(from var(--sjs2-color-border-basic-secondary) r g b / var(--sjs2-opacity-hidden))", + "--sjs2-color-control-segmented-false-readonly-value": "var(--sjs2-palette-gray-400)", + "--sjs2-color-control-segmented-false-focused-bg": "var(--sjs2-color-bg-basic-secondary)", + "--sjs2-color-control-segmented-false-focused-border": "var(--sjs2-color-border-brand-primary)", + "--sjs2-color-control-segmented-false-focused-value": "var(--sjs2-color-fg-basic-primary)", + "--sjs2-color-control-segmented-false-hovered-bg": "var(--sjs2-color-bg-basic-secondary-dim)", + "--sjs2-color-control-segmented-false-hovered-border": "var(--sjs2-color-border-basic-secondary)", + "--sjs2-color-control-segmented-false-hovered-value": "var(--sjs2-color-fg-basic-primary)", + "--sjs2-color-control-segmented-true-default-bg": "var(--sjs2-color-bg-basic-primary)", + "--sjs2-color-control-segmented-true-default-border": "var(--sjs2-color-border-basic-secondary)", + "--sjs2-color-control-segmented-true-default-value": "var(--sjs2-color-fg-brand-primary)", + "--sjs2-color-control-segmented-true-disabled-bg": "var(--sjs2-color-bg-basic-primary)", + "--sjs2-color-control-segmented-true-disabled-border": "var(--sjs2-color-border-basic-secondary)", + "--sjs2-color-control-segmented-true-disabled-value": "var(--sjs2-palette-gray-400)", + "--sjs2-color-control-segmented-true-readonly-bg": "var(--sjs2-color-bg-basic-primary)", + "--sjs2-color-control-segmented-true-readonly-border": "var(--sjs2-color-border-basic-secondary)", + "--sjs2-color-control-segmented-true-readonly-value": "var(--sjs2-color-fg-basic-primary)", + "--sjs2-color-control-segmented-true-focused-bg": "var(--sjs2-color-bg-basic-primary)", + "--sjs2-color-control-segmented-true-focused-border": "var(--sjs2-color-border-brand-primary)", + "--sjs2-color-control-segmented-true-focused-value": "var(--sjs2-color-fg-brand-primary)", + "--sjs2-color-control-toggle-false-default-bg": "var(--sjs2-color-bg-basic-secondary)", + "--sjs2-color-control-toggle-false-default-border": "var(--sjs2-color-border-basic-secondary)", + "--sjs2-color-control-toggle-false-default-thumb": "var(--sjs2-color-fg-basic-secondary)", + "--sjs2-color-control-toggle-false-disabled-bg": "var(--sjs2-color-bg-basic-secondary)", + "--sjs2-color-control-toggle-false-disabled-border": "var(--sjs2-color-border-basic-secondary)", + "--sjs2-color-control-toggle-false-disabled-thumb": "var(--sjs2-color-fg-basic-tertiary)", + "--sjs2-color-control-toggle-false-readonly-bg": "var(--sjs2-color-bg-basic-secondary)", + "--sjs2-color-control-toggle-false-readonly-border": "var(--sjs2-color-border-basic-secondary)", + "--sjs2-color-control-toggle-false-readonly-thumb": "var(--sjs2-color-fg-basic-tertiary)", + "--sjs2-color-control-toggle-false-focused-bg": "var(--sjs2-color-bg-basic-secondary)", + "--sjs2-color-control-toggle-false-focused-border": "var(--sjs2-color-border-brand-primary)", + "--sjs2-color-control-toggle-false-focused-thumb": "var(--sjs2-color-fg-basic-secondary)", + "--sjs2-color-control-toggle-false-hovered-bg": "var(--sjs2-color-bg-basic-secondary-dim)", + "--sjs2-color-control-toggle-false-hovered-border": "var(--sjs2-color-border-basic-secondary)", + "--sjs2-color-control-toggle-false-hovered-thumb": "var(--sjs2-color-fg-basic-secondary)", + "--sjs2-color-control-toggle-true-default-bg": "var(--sjs2-color-bg-brand-primary)", + "--sjs2-color-control-toggle-true-default-border": "var(--sjs2-color-border-brand-primary)", + "--sjs2-color-control-toggle-true-default-thumb": "var(--sjs2-color-fg-static-main-primary)", + "--sjs2-color-control-toggle-true-disabled-bg": "var(--sjs2-color-bg-basic-secondary)", + "--sjs2-color-control-toggle-true-disabled-border": "var(--sjs2-color-border-basic-secondary)", + "--sjs2-color-control-toggle-true-disabled-thumb": "var(--sjs2-color-fg-static-main-primary)", + "--sjs2-color-control-toggle-true-readonly-bg": "var(--sjs2-color-bg-basic-secondary)", + "--sjs2-color-control-toggle-true-readonly-border": "var(--sjs2-color-border-basic-secondary)", + "--sjs2-color-control-toggle-true-readonly-thumb": "var(--sjs2-color-fg-static-main-primary)", + "--sjs2-color-control-toggle-true-focused-bg": "var(--sjs2-color-bg-basic-primary)", + "--sjs2-color-control-toggle-true-focused-border": "var(--sjs2-color-border-brand-primary)", + "--sjs2-color-control-toggle-true-focused-thumb": "var(--sjs2-color-fg-brand-primary)", + "--sjs2-color-control-toggle-true-hovered-bg": "var(--sjs2-color-bg-brand-primary-dim)", + "--sjs2-color-control-toggle-true-hovered-border": "var(--sjs2-color-border-brand-primary)", + "--sjs2-color-control-toggle-true-hovered-thumb": "var(--sjs2-color-fg-static-main-primary)", + "--sjs2-color-control-message-bg": "var(--sjs2-color-bg-alert-secondary)", + "--sjs2-color-control-message-icon": "var(--sjs2-color-fg-alert-primary)", + "--sjs2-color-control-message-text": "var(--sjs2-color-fg-basic-primary)", + "--sjs2-color-control-track-default-bg": "var(--sjs2-color-bg-basic-secondary)", + "--sjs2-color-control-track-default-fg": "var(--sjs2-color-fg-brand-primary)", + "--sjs2-color-control-track-default-thumb": "var(--sjs2-color-bg-basic-primary)", + "--sjs2-color-control-track-default-dot": "var(--sjs2-color-fg-brand-primary)", + "--sjs2-color-control-track-default-thumb-border": "var(--sjs2-color-border-basic-secondary)", + "--sjs2-color-control-track-disabled-bg": "var(--sjs2-color-bg-basic-secondary)", + "--sjs2-color-control-track-disabled-fg": "var(--sjs2-color-fg-basic-tertiary)", + "--sjs2-color-control-track-disabled-thumb": "var(--sjs2-color-bg-basic-primary)", + "--sjs2-color-control-track-disabled-dot": "var(--sjs2-color-fg-state-common-disabled)", + "--sjs2-color-control-track-disabled-thumb-border": "var(--sjs2-color-border-basic-secondary)", + "--sjs2-color-control-track-readonly-bg": "var(--sjs2-color-bg-basic-secondary)", + "--sjs2-color-control-track-readonly-fg": "var(--sjs2-color-fg-brand-primary)", + "--sjs2-color-control-track-readonly-thumb": "var(--sjs2-color-bg-basic-primary)", + "--sjs2-color-control-track-readonly-dot": "var(--sjs2-color-bg-basic-primary)", + "--sjs2-color-control-track-readonly-thumb-border": "var(--sjs2-color-border-basic-secondary)", + "--sjs2-color-control-track-focused-bg": "var(--sjs2-color-bg-basic-secondary)", + "--sjs2-color-control-track-focused-fg": "var(--sjs2-color-fg-brand-primary)", + "--sjs2-color-control-track-focused-thumb": "var(--sjs2-color-bg-basic-primary)", + "--sjs2-color-control-track-focused-dot": "var(--sjs2-color-fg-brand-primary)", + "--sjs2-color-control-track-focused-thumb-border": "var(--sjs2-color-border-basic-secondary)", + "--sjs2-color-control-track-invalid-bg": "var(--sjs2-color-bg-alert-secondary)", + "--sjs2-color-control-track-invalid-fg": "var(--sjs2-color-fg-alert-primary)", + "--sjs2-color-control-track-invalid-thumb": "var(--sjs2-color-bg-basic-primary)", + "--sjs2-color-control-track-invalid-dot": "var(--sjs2-color-fg-alert-primary)", + "--sjs2-color-control-track-invalid-thumb-border": "var(--sjs2-color-border-basic-secondary)", + "--sjs2-color-control-track-design-bg": "var(--sjs2-color-bg-basic-secondary)", + "--sjs2-color-control-track-design-fg": "var(--sjs2-color-fg-basic-tertiary)", + "--sjs2-color-control-track-design-thumb": "var(--sjs2-color-bg-basic-primary)", + "--sjs2-color-control-track-design-dot": "var(--sjs2-color-bg-basic-primary)", + "--sjs2-color-control-track-design-thumb-border": "var(--sjs2-color-border-basic-secondary)", + "--sjs2-color-data-chart-bg-color-1": "#84CAD4", + "--sjs2-color-data-chart-bg-color-1-tinted": "rgba(from #84CAD4 r g b / var(--sjs2-opacity-x060))", + "--sjs2-color-data-chart-bg-color-2": "#3A99FB", + "--sjs2-color-data-chart-bg-color-2-tinted": "rgba(from #3A99FB r g b / var(--sjs2-opacity-x060))", + "--sjs2-color-data-chart-bg-color-3": "#FF6771", + "--sjs2-color-data-chart-bg-color-3-tinted": "rgba(from #FF6771 r g b / var(--sjs2-opacity-x060))", + "--sjs2-color-data-chart-bg-color-4": "#1DB496", + "--sjs2-color-data-chart-bg-color-4-tinted": "rgba(from #1DB496 r g b / var(--sjs2-opacity-x060))", + "--sjs2-color-data-chart-bg-color-5": "#FFC152", + "--sjs2-color-data-chart-bg-color-5-tinted": "rgba(from #FFC152 r g b / var(--sjs2-opacity-x060))", + "--sjs2-color-data-chart-bg-color-6": "#ABA1FF", + "--sjs2-color-data-chart-bg-color-6-tinted": "rgba(from #ABA1FF r g b / var(--sjs2-opacity-x060))", + "--sjs2-color-data-chart-bg-color-7": "#7D8CA5", + "--sjs2-color-data-chart-bg-color-7-tinted": "rgba(from #7D8CA5 r g b / var(--sjs2-opacity-x060))", + "--sjs2-color-data-chart-bg-color-8": "#4FC46C", + "--sjs2-color-data-chart-bg-color-8-tinted": "rgba(from #4FC46C r g b / var(--sjs2-opacity-x060))", + "--sjs2-color-data-chart-bg-color-9": "#E87BCB", + "--sjs2-color-data-chart-bg-color-9-tinted": "rgba(from #E87BCB r g b / var(--sjs2-opacity-x060))", + "--sjs2-color-data-chart-bg-color-10": "#4E6198", + "--sjs2-color-data-chart-bg-color-10-tinted": "rgba(from #4E6198 r g b / var(--sjs2-opacity-x060))", + "--sjs2-color-data-chart-fg-on-color-1": "var(--sjs2-palette-gray-000)", + "--sjs2-color-data-chart-fg-on-color-2": "var(--sjs2-palette-gray-000)", + "--sjs2-color-data-chart-fg-on-color-3": "var(--sjs2-palette-gray-000)", + "--sjs2-color-data-chart-fg-on-color-4": "var(--sjs2-palette-gray-000)", + "--sjs2-color-data-chart-fg-on-color-5": "var(--sjs2-palette-gray-000)", + "--sjs2-color-data-chart-fg-on-color-6": "var(--sjs2-palette-gray-000)", + "--sjs2-color-data-chart-fg-on-color-7": "var(--sjs2-palette-gray-000)", + "--sjs2-color-data-chart-fg-on-color-8": "var(--sjs2-palette-gray-000)", + "--sjs2-color-data-chart-fg-on-color-9": "var(--sjs2-palette-gray-000)", + "--sjs2-color-data-chart-fg-on-color-10": "var(--sjs2-palette-gray-000)", + "--sjs2-color-data-chart-border-color-1": "#84CAD4", + "--sjs2-color-data-chart-border-color-2": "#3A99FB", + "--sjs2-color-data-chart-border-color-3": "#FF6771", + "--sjs2-color-data-chart-border-color-4": "#1DB496", + "--sjs2-color-data-chart-border-color-5": "#FFC152", + "--sjs2-color-data-chart-border-color-6": "#ABA1FF", + "--sjs2-color-data-chart-border-color-7": "#7D8CA5", + "--sjs2-color-data-chart-border-color-8": "#4FC46C", + "--sjs2-color-data-chart-border-color-9": "#E87BCB", + "--sjs2-color-data-chart-border-color-10": "#4E6198", + "--sjs2-color-data-grid-fg-label": "var(--sjs2-color-fg-basic-primary)", + "--sjs2-color-data-grid-border-line": "#DCDCDC", + "--sjs2-color-data-grid-border-axis": "var(--sjs2-color-border-basic-primary)", + "--sjs2-opacity-visible": "var(--sjs2-opacity-x100)", + "--sjs2-opacity-hovered": "var(--sjs2-opacity-x100)", + "--sjs2-opacity-pressed": "var(--sjs2-opacity-x100)", + "--sjs2-opacity-disabled": "var(--sjs2-opacity-x025)", + "--sjs2-opacity-hidden": "var(--sjs2-opacity-x000)", + "--sjs2-border-width-default": "var(--sjs2-border-width-x100)", + "--sjs2-border-width-a11y": "var(--sjs2-border-width-x400)", + "--sjs2-border-spread-form-default": "var(--sjs2-border-width-x100)", + "--sjs2-border-spread-form-hovered": "var(--sjs2-border-width-x100)", + "--sjs2-border-spread-form-pressed": "var(--sjs2-border-width-x100)", + "--sjs2-border-spread-form-focused": "var(--sjs2-border-width-x200)", + "--sjs2-border-spread-form-highlighted": "var(--sjs2-border-width-x200)", + "--sjs2-border-spread-form-disabled": "var(--sjs2-border-width-x100)", + "--sjs2-border-spread-form-invalid": "var(--sjs2-border-width-x200)", + "--sjs2-border-spread-form-readonly": "var(--sjs2-border-width-x100)", + "--sjs2-border-spread-form-preview": "var(--sjs2-border-width-x100)", + "--sjs2-border-spread-trigger-default": "var(--sjs2-border-width-x100)", + "--sjs2-border-spread-trigger-hovered": "var(--sjs2-border-width-x100)", + "--sjs2-border-spread-trigger-pressed": "var(--sjs2-border-width-x100)", + "--sjs2-border-spread-trigger-focused": "var(--sjs2-border-width-x200)", + "--sjs2-border-spread-trigger-disabled": "var(--sjs2-border-width-x100)", + "--sjs2-border-spread-trigger-preview": "var(--sjs2-border-width-x100)", + "--sjs2-border-spread-surface-default": "var(--sjs2-border-width-x100)", + "--sjs2-border-spread-surface-hovered": "var(--sjs2-border-width-x100)", + "--sjs2-border-spread-surface-pressed": "var(--sjs2-border-width-x100)", + "--sjs2-border-spread-surface-focused": "var(--sjs2-border-width-x200)", + "--sjs2-border-spread-surface-disabled": "var(--sjs2-border-width-x100)", + "--sjs2-border-spread-surface-dragging": "4", + "--sjs2-border-spread-elevated-default": "2", + "--sjs2-border-spread-floating-default": "4", + "--sjs2-border-blur-form-default": "0", + "--sjs2-border-blur-form-hovered": "0", + "--sjs2-border-blur-form-pressed": "0", + "--sjs2-border-blur-form-focused": "0", + "--sjs2-border-blur-form-highlighted": "0", + "--sjs2-border-blur-form-disabled": "0", + "--sjs2-border-blur-form-invalid": "0", + "--sjs2-border-blur-form-readonly": "0", + "--sjs2-border-blur-form-preview": "0", + "--sjs2-border-blur-trigger-default": "0", + "--sjs2-border-blur-trigger-hovered": "0", + "--sjs2-border-blur-trigger-pressed": "0", + "--sjs2-border-blur-trigger-focused": "0", + "--sjs2-border-blur-trigger-disabled": "0", + "--sjs2-border-blur-trigger-preview": "0", + "--sjs2-border-blur-surface-default": "0", + "--sjs2-border-blur-surface-hovered": "0", + "--sjs2-border-blur-surface-pressed": "0", + "--sjs2-border-blur-surface-focused": "0", + "--sjs2-border-blur-surface-disabled": "0", + "--sjs2-border-blur-surface-dragging": "12", + "--sjs2-border-blur-elevated-default": "8", + "--sjs2-border-blur-floating-default": "12", + "--sjs2-border-offset-x-form-default": "0", + "--sjs2-border-offset-x-form-hovered": "0", + "--sjs2-border-offset-x-form-pressed": "0", + "--sjs2-border-offset-x-form-focused": "0", + "--sjs2-border-offset-x-form-highlighted": "0", + "--sjs2-border-offset-x-form-disabled": "0", + "--sjs2-border-offset-x-form-invalid": "0", + "--sjs2-border-offset-x-form-readonly": "0", + "--sjs2-border-offset-x-form-preview": "0", + "--sjs2-border-offset-x-trigger-default": "0", + "--sjs2-border-offset-x-trigger-hovered": "0", + "--sjs2-border-offset-x-trigger-pressed": "0", + "--sjs2-border-offset-x-trigger-focused": "0", + "--sjs2-border-offset-x-trigger-disabled": "0", + "--sjs2-border-offset-x-trigger-preview": "0", + "--sjs2-border-offset-x-surface-default": "0", + "--sjs2-border-offset-x-surface-hovered": "0", + "--sjs2-border-offset-x-surface-pressed": "0", + "--sjs2-border-offset-x-surface-focused": "0", + "--sjs2-border-offset-x-surface-disabled": "0", + "--sjs2-border-offset-x-surface-dragging": "0", + "--sjs2-border-offset-x-elevated-default": "0", + "--sjs2-border-offset-x-floating-default": "0", + "--sjs2-border-offset-y-form-default": "0", + "--sjs2-border-offset-y-form-hovered": "0", + "--sjs2-border-offset-y-form-pressed": "0", + "--sjs2-border-offset-y-form-focused": "0", + "--sjs2-border-offset-y-form-highlighted": "0", + "--sjs2-border-offset-y-form-disabled": "0", + "--sjs2-border-offset-y-form-invalid": "0", + "--sjs2-border-offset-y-form-readonly": "0", + "--sjs2-border-offset-y-form-preview": "0", + "--sjs2-border-offset-y-trigger-default": "0", + "--sjs2-border-offset-y-trigger-hovered": "0", + "--sjs2-border-offset-y-trigger-pressed": "0", + "--sjs2-border-offset-y-trigger-focused": "0", + "--sjs2-border-offset-y-trigger-disabled": "0", + "--sjs2-border-offset-y-trigger-preview": "0", + "--sjs2-border-offset-y-surface-default": "0", + "--sjs2-border-offset-y-surface-hovered": "0", + "--sjs2-border-offset-y-surface-pressed": "0", + "--sjs2-border-offset-y-surface-focused": "0", + "--sjs2-border-offset-y-surface-disabled": "0", + "--sjs2-border-offset-y-surface-dragging": "6", + "--sjs2-border-offset-y-elevated-default": "4", + "--sjs2-border-offset-y-floating-default": "6" + } +} as const; + +export default Default; diff --git a/src/statisticCalculators.ts b/src/statisticCalculators.ts index 353c072b6..ece5672f1 100644 --- a/src/statisticCalculators.ts +++ b/src/statisticCalculators.ts @@ -1,7 +1,7 @@ import { DataProvider } from "./dataProvider"; -import { IDataInfo } from "./visualizerBase"; +import { ICalculatedDataInfo, ICalculationResult, IDataInfo } from "./visualizerBase"; -export function defaultStatisticsCalculator(data: Array, dataInfo: IDataInfo): Array { +export function defaultStatisticsCalculator(data: Array, dataInfo: IDataInfo): ICalculationResult { const dataNames = dataInfo.dataNames; const statistics: Array>> = []; @@ -71,7 +71,7 @@ export function defaultStatisticsCalculator(data: Array, dataInfo: IDataInf }; data.forEach((dataRow: any) => { - const nestedDataRows = getNestedDataRows(dataRow, dataInfo); + const nestedDataRows = getNestedDataRows(dataRow, dataInfo.dataPath); nestedDataRows.forEach(nestedDataRow => { dataNames.forEach((dataName, index) => { processDataRow(nestedDataRow, dataName, index); @@ -79,10 +79,14 @@ export function defaultStatisticsCalculator(data: Array, dataInfo: IDataInf }); }); - return dataInfo.dataNames.length > 1 ? statistics : statistics[0] as any; + return { + data: dataInfo.dataNames.length > 1 ? statistics as any : statistics[0], + values, + series + }; } -export function histogramStatisticsCalculator(data: { [series: string]: Array<{continuous: number, row: any}> }, intervals: Array<{ start: number, end: number, label: string }>, dataInfo: IDataInfo, aggregateDataNames = []): Array { +export function histogramStatisticsCalculator(data: any, intervals: Array<{start: number | Date, end: number | Date, label: string}>, dataInfo: IDataInfo, aggregateDataNames = []): ICalculationResult { const seriesValues = dataInfo.getSeriesValues(); const statistics: Array> = []; if (seriesValues.length === 0) { @@ -109,17 +113,25 @@ export function histogramStatisticsCalculator(data: { [series: string]: Array<{c } }); } - return statistics; + + const result: ICalculationResult = { + data: statistics, + values: intervals.map(i => i.label), + }; + if(seriesValues.length > 1) { + result.series = seriesValues; + } + return result; } -export function mathStatisticsCalculator(data: Array, dataInfo: IDataInfo) { +export function mathStatisticsCalculator(data: Array, dataInfo: IDataInfo): ICalculationResult { let resultMin = Number.MAX_VALUE, resultMax = -Number.MAX_VALUE, resultAverage = 0; let actualAnswerCount = 0; data.forEach((dataRow) => { - const nestedDataRows = getNestedDataRows(dataRow, dataInfo); + const nestedDataRows = getNestedDataRows(dataRow, dataInfo.dataPath); nestedDataRows.forEach(nestedDataRow => { const answerData = nestedDataRow[dataInfo.dataNames[0]]; if (answerData !== undefined) { @@ -141,20 +153,23 @@ export function mathStatisticsCalculator(data: Array, dataInfo: IDataInfo) } resultAverage = Math.ceil(resultAverage * 100) / 100; - return [resultAverage, resultMin, resultMax]; + return { + data: [[resultAverage, resultMin, resultMax, data.length]], + values: ["average", "min", "max", "count"] + }; } -export function getNestedDataRows(dataRow: any, dataInfo: IDataInfo): Array { +export function getNestedDataRows(dataRow: any, dataPath: string): Array { let nestedDataRows = []; - if(!dataInfo.dataPath) { + if(!dataPath) { nestedDataRows = [dataRow]; } else { - if(dataRow[dataInfo.dataPath] === undefined) return []; - if(typeof dataRow[dataInfo.dataPath] !== "object") return []; - if(Array.isArray(dataRow[dataInfo.dataPath])) { - nestedDataRows = dataRow[dataInfo.dataPath]; + if(dataRow[dataPath] === undefined) return []; + if(typeof dataRow[dataPath] !== "object") return []; + if(Array.isArray(dataRow[dataPath])) { + nestedDataRows = dataRow[dataPath]; } else { - nestedDataRows = [dataRow[dataInfo.dataPath]]; + nestedDataRows = [dataRow[dataPath]]; } } return nestedDataRows; diff --git a/src/statistics-table.scss b/src/statistics-table.scss index 19a84ca7e..5279b42e0 100644 --- a/src/statistics-table.scss +++ b/src/statistics-table.scss @@ -9,37 +9,81 @@ .sa-statistics-table { width: 100%; - font-family: $font-family; - font-size: $root-font-size; - color: $text-color; - // border-collapse: collapse; - background-color: $background-color; } .sa-statistics-table__cell { - border-width: 1px; - padding: 8px; - border-style: solid; - border-color: $border-color; - background-color: $background-color; - min-height: $form-element-height; + border-bottom: var(--dsb-table-cell-border-width, 1px) dashed var(--dsb-table-cell-border-color, #DCDCDC); +} + +.sa-statistics-table__cell-text { + color: var(--dsb-table-cell-text-color, rgba(0, 0, 0, 0.90)); + margin-left: calc(var(--dsb-table-row-gap, 32px) / 2); + margin-right: calc(var(--dsb-table-row-gap, 32px) / 2); + + /* ctr/Default */ + font-family: $font-family; + font-size: var(--ctr-font-default-size, 16px); + font-style: normal; + font-weight: 400; + line-height: var(--ctr-font-default-line-height, 24px); /* 150% */ +} + +.sa-statistics-table__cell:first-child .sa-statistics-table__cell-text { + margin-inline-start: 0; +} +.sa-statistics-table__cell:last-child .sa-statistics-table__cell-text { + margin-inline-end: 0; } -.sa-statistics-table__cell-value { - text-align: right; - min-width: 30px; +.sa-statistics-table__cell-value.sa-statistics-table__cell-value { + .sa-statistics-table__cell-text, + .sa-statistics-table__cell-header-text { + text-align: right; + } } .sa-statistics-table__cell-header { - font-weight: bold; + border-top: var(--dsb-table-cell-border-width, 1px) dashed var(--dsb-table-cell-border-color, #DCDCDC); + border-bottom: var(--dsb-table-cell-border-width, 1px) dashed var(--dsb-table-cell-border-color, #DCDCDC); } +.sa-statistics-table__cell-header-text { + color: var(--dsb-table-header-text-color, rgba(0, 0, 0, 0.90)); + padding: var(--dsb-table-cell-padding-top, 8px) var(--dsb-table-cell-padding-right-no-border, 0px) var(--dsb-table-cell-padding-bottom, 8px) var(--dsb-table-cell-padding-left-no-border, 0px); + margin-left: calc(var(--dsb-table-row-gap, 32px) / 2); + margin-right: calc(var(--dsb-table-row-gap, 32px) / 2); + text-align: left; + + /* ctr/Default Bold */ + font-family: $font-family; + font-size: var(--ctr-font-default-size, 16px); + font-style: normal; + font-weight: 600; + line-height: var(--ctr-font-default-line-height, 24px); /* 150% */ +} + +.sa-statistics-table__cell-header:first-child .sa-statistics-table__cell-header-text { + margin-inline-start: 0; +} + +.sa-statistics-table__cell-header:last-child .sa-statistics-table__cell-header-text { + margin-inline-end: 0; +} + + .sa-choices-sparkline { - min-width: 100px; - height: 24px; - border: 1px solid $main-color; + display: flex; + flex: 1 0 0; + flex-direction: column; + align-items: flex-start; + padding: var(--dsb-table-cell-padding-top-progressbar, 16px) var(--dsb-table-cell-padding-right-no-border, 0px) var(--dsb-table-cell-padding-bottom-progressbar, 16px) var(--dsb-table-cell-padding-left-no-border, 0px); + margin-left: calc(var(--dsb-table-row-gap, 32px) / 2); + margin-right: calc(var(--dsb-table-row-gap, 32px) / 2); } .sa-choices-sparkline-value { - height: 100%; - background-color: $main-color; + display: flex; + align-items: flex-start; + height: var(--dsb-table-cell-progressbar-height, 8px); + border-radius: var(--dsb-table-cell-progressbar-corner-radius, 2px); + background: var(--dsb-table-cell-progressbar-color, #19B394); } diff --git a/src/statistics-table.ts b/src/statistics-table.ts index 853126faf..ba9a68bf7 100644 --- a/src/statistics-table.ts +++ b/src/statistics-table.ts @@ -21,11 +21,10 @@ export class StatisticsTableAdapter { const hasSeries = seriesLabels.length > 1; - const emptyTextNode = DocumentHelper.createElement("p", "", { - innerText: localization.getString("noResults"), - }); - if (datasets.length === 0 || datasets[0].length === 0) { + const emptyTextNode = DocumentHelper.createElement("p", "", { + innerText: localization.getString("noResults"), + }); container.appendChild(emptyTextNode); return; } @@ -39,29 +38,40 @@ export class StatisticsTableAdapter { container.appendChild(tableNode); var headerRow = DocumentHelper.createElement("tr"); - var labelCell = DocumentHelper.createElement("th", "sa-statistics-table__cell-header", { + var labelCell = DocumentHelper.createElement("th", "sa-statistics-table__cell-header"); + var cellHeaderContent = DocumentHelper.createElement("div", "sa-statistics-table__cell-header-text", { textContent: localization.getString("answer"), }); + labelCell.appendChild(cellHeaderContent); headerRow.appendChild(labelCell); - var sparklineCell = DocumentHelper.createElement("th", "sa-statistics-table__cell-header", { + var sparklineCell = DocumentHelper.createElement("th", "sa-statistics-table__cell-header"); + cellHeaderContent = DocumentHelper.createElement("div", "sa-statistics-table__cell-header-text", { textContent: localization.getString("statistics_chart"), }); + sparklineCell.appendChild(cellHeaderContent); headerRow.appendChild(sparklineCell); - var percentCell = DocumentHelper.createElement("th", "sa-statistics-table__cell-header", { + var percentCell = DocumentHelper.createElement("th", "sa-statistics-table__cell-header sa-statistics-table__cell-value"); + cellHeaderContent = DocumentHelper.createElement("div", "sa-statistics-table__cell-header-text", { textContent: localization.getString("percentage"), }); + percentCell.appendChild(cellHeaderContent); headerRow.appendChild(percentCell); - var valueCell = DocumentHelper.createElement("th", "sa-statistics-table__cell-header", { + var valueCell = DocumentHelper.createElement("th", "sa-statistics-table__cell-header sa-statistics-table__cell-value"); + cellHeaderContent = DocumentHelper.createElement("div", "sa-statistics-table__cell-header-text", { textContent: localization.getString("responses"), }); + valueCell.appendChild(cellHeaderContent); headerRow.appendChild(valueCell); tableNode.appendChild(headerRow); for(let index = data.length - 1; index >= 0; index--) { var row = DocumentHelper.createElement("tr"); - var labelCell = DocumentHelper.createElement("td", "sa-statistics-table__cell", { + var labelCell = DocumentHelper.createElement("td", "sa-statistics-table__cell"); + var labelCellContent = DocumentHelper.createElement("div", "sa-statistics-table__cell-text", { textContent: labels[index], }); + labelCell.appendChild(labelCellContent); + row.appendChild(labelCell); var sparklineCell = DocumentHelper.createElement("td", "sa-statistics-table__cell"); var outerBar = DocumentHelper.createElement("div", "sa-choices-sparkline"); @@ -70,13 +80,19 @@ export class StatisticsTableAdapter { outerBar.appendChild(innerBar); sparklineCell.appendChild(outerBar); row.appendChild(sparklineCell); - var percentCell = DocumentHelper.createElement("td", "sa-statistics-table__cell sa-statistics-table__cell-value", { + var percentCell = DocumentHelper.createElement("td", "sa-statistics-table__cell sa-statistics-table__cell-value"); + labelCellContent = DocumentHelper.createElement("div", "sa-statistics-table__cell-text", { textContent: "" + texts[idx][index] + "%", }); + percentCell.appendChild(labelCellContent); + row.appendChild(percentCell); - var valueCell = DocumentHelper.createElement("td", "sa-statistics-table__cell sa-statistics-table__cell-value", { + var valueCell = DocumentHelper.createElement("td", "sa-statistics-table__cell sa-statistics-table__cell-value"); + labelCellContent = DocumentHelper.createElement("div", "sa-statistics-table__cell-text", { textContent: data[index], }); + valueCell.appendChild(labelCellContent); + row.appendChild(valueCell); tableNode.appendChild(row); } @@ -98,9 +114,9 @@ export class StatisticsTable extends SelectBase { question: Question, data: Array<{ [index: string]: any }>, options?: Object, - name?: string + type?: string ) { - super(question, data, options, name || "choices"); + super(question, data, options, type || "choices"); this._statisticsTableAdapter = new StatisticsTableAdapter(this); this.showPercentages = true; } @@ -131,9 +147,9 @@ export class StatisticsTableBoolean extends BooleanModel { question: Question, data: Array<{ [index: string]: any }>, options?: Object, - name?: string + type?: string ) { - super(question, data, options, name || "options"); + super(question, data, options, type || "options"); this._statisticsTableAdapter = new StatisticsTableAdapter(this); this.showPercentages = true; } diff --git a/src/tables/extensions/columnextensions.ts b/src/tables/extensions/columnextensions.ts index 626c61ed3..d36893ba6 100644 --- a/src/tables/extensions/columnextensions.ts +++ b/src/tables/extensions/columnextensions.ts @@ -7,13 +7,16 @@ import { QuestionLocation, IColumn } from "../config"; TableExtensions.registerExtension({ location: "column", name: "drag", - visibleIndex: 0, + visibleIndex: 10, render: function (table: Table, options: any) { - const btn = DocumentHelper.createElement( - "button", - "sa-table__svg-button sa-table__drag-button" - ); - btn.appendChild(DocumentHelper.createSvgElement("drag")); + const btn = DocumentHelper.createSvgButton("drag-24x24"); + btn.className = "sa-table__svg-button sa-table__drag-button"; + btn.title = localization.getString("columnReorder"); + // const btn = DocumentHelper.createElement( + // "button", + // "sa-table__svg-button sa-table__drag-button" + // ); + // btn.appendChild(DocumentHelper.createSvgElement("drag-24x24")); btn.addEventListener("mousedown", () => { table.enableColumnReorder(); document.body.addEventListener("mouseup", () => { @@ -23,15 +26,16 @@ TableExtensions.registerExtension({ return btn; }, }); + TableExtensions.registerExtension({ location: "column", name: "sort", - visibleIndex: 1, + visibleIndex: 20, render: function (table: Table, options: any) { const descTitle = localization.getString("descOrder"); const ascTitle = localization.getString("ascOrder"); - var btn = DocumentHelper.createSvgButton("sorting"); - btn.title = ""; + var btn = DocumentHelper.createSvgButton("reorder-24x24"); + btn.title = localization.getString("defaultOrder"); var direction = "asc"; btn.onclick = () => { if (direction == "asc") { @@ -53,10 +57,9 @@ TableExtensions.registerExtension({ TableExtensions.registerExtension({ location: "column", name: "hide", - visibleIndex: 2, + visibleIndex: 30, render: function (table: Table, options: any) { - var btn = DocumentHelper.createSvgButton("hide"); - btn.title = localization.getString("hideColumn"); + var btn = DocumentHelper.createSvgButton("invisible-24x24", localization.getString("hideColumn")); btn.onclick = () => { table.setColumnVisibility(options.columnName, false); }; @@ -67,10 +70,9 @@ TableExtensions.registerExtension({ TableExtensions.registerExtension({ location: "column", name: "movetodetails", - visibleIndex: 3, + visibleIndex: 10, render: function (table: Table, options: any) { - const button = DocumentHelper.createSvgButton("movetodetails"); - button.title = localization.getString("moveToDetail"); + const button = DocumentHelper.createSvgButton("movetohorizontal-24x24", localization.getString("moveToDetail")); button.onclick = (e) => { e.stopPropagation(); table.setColumnLocation(options.columnName, QuestionLocation.Row); @@ -80,18 +82,23 @@ TableExtensions.registerExtension({ }); TableExtensions.registerExtension({ - location: "column", + location: "columnfilter", name: "filter", - visibleIndex: 4, + visibleIndex: 10, render: function (table: Table, options: any) { - var el = DocumentHelper.createInput( - "sa-table__filter", - localization.getString("filterPlaceholder") + const el = DocumentHelper.createTextEditor({ + showIcon: false, + onchange: (val) => { + table.applyColumnFilter(options.columnName, val); + } + } + // "sa-table__filter", + // localization.getString("filterPlaceholder") ); - el.onclick = (e) => e.stopPropagation(); - el.onchange = (e) => { - table.applyColumnFilter(options.columnName, el.value); - }; + // el.onclick = (e) => e.stopPropagation(); + // el.onchange = (e) => { + // table.applyColumnFilter(options.columnName, el.value); + // }; return el; }, }); diff --git a/src/tables/extensions/detailsextensions.ts b/src/tables/extensions/detailsextensions.ts index 0c65ac899..435ab105f 100644 --- a/src/tables/extensions/detailsextensions.ts +++ b/src/tables/extensions/detailsextensions.ts @@ -38,12 +38,12 @@ export class Details { } var td3 = DocumentHelper.createElement("td"); td3.appendChild(this.createShowAsColumnButton(column.name)); + row.appendChild(td3); row.appendChild(td1); row.appendChild(td2); - row.appendChild(td3); rows.push(row); }); - var row = DocumentHelper.createElement("tr", "sa-table__detail"); + var row = DocumentHelper.createElement("tr", "sa-table__detail sa-table-detail__actions"); var td = DocumentHelper.createElement("td", "", { colSpan: 3 }); var extensions = new TableExtensions(this.table); extensions.render(td, "details", { row: this.row }); @@ -59,11 +59,9 @@ export class Details { } protected createShowAsColumnButton = (columnName: string): HTMLElement => { - const button = DocumentHelper.createElement( - "button", - "sa-table__btn sa-table__btn--gray" - ); - button.appendChild(document.createTextNode(localization.getString("showAsColumn"))); + const button = DocumentHelper.createSvgButton("movetovertical-24x24", localization.getString("showAsColumn")); + // "button", + // "sa-table__btn sa-table__btn--gray" button.onclick = (e) => { e.stopPropagation(); this.table.setColumnLocation(columnName, QuestionLocation.Column); diff --git a/src/tables/extensions/footerextensions.ts b/src/tables/extensions/footerextensions.ts new file mode 100644 index 000000000..2aa69c4fc --- /dev/null +++ b/src/tables/extensions/footerextensions.ts @@ -0,0 +1,61 @@ +import { localization } from "../../localizationManager"; +import { Table } from "../table"; +import { DocumentHelper } from "../../utils"; +import { TableExtensions } from "./tableextensions"; + +TableExtensions.registerExtension({ + location: "footer", + name: "showentries", + visibleIndex: 30, + render: function (table: Table): HTMLElement { + if(table.options.paginationEnabled === false) { + return DocumentHelper.createElement("div"); + } + function getEntriesDropdown(table: Table): HTMLElement { + /* + const el = DocumentHelper.createElement("select"); + var optionsValues = table.paginationSizeSelector || ["1", "5", "10", "25", "50", "75", "100"]; + optionsValues.forEach(function (val) { + var option = DocumentHelper.createElement("option", "", { + value: val, + text: val, + }); + el.appendChild(option); + }); + el.value = String(table.getPageSize()); + + el.onchange = () => { + table.setPageSize(Number(el.value)); + }; + + return el; + */ + const optionsValues = table.paginationSizeSelector || ["1", "5", "10", "25", "50", "75", "100"]; + const el = DocumentHelper.createActionDropdown( + optionsValues.map(val => { return { value: val, text: val }; }), + (option: any) => { + return option.value === table.getPageSize(); + }, + (e: any) => { + if(e !== undefined && e !== null) { + table.setPageSize(Number(e)); + } + return true; + }, + () => { return String(table.getPageSize()); }, + ); + el.className += " sa-table__entries-value"; + return el; + } + const selectorContainer = DocumentHelper.createElement("div", "sa-table__entries"); + const showSpan = DocumentHelper.createElement("span", "sa-table__entries-label sa-table__entries-label--right", + { + innerText: localization.getString("entriesOnPageLabel"), + } + ); + + selectorContainer.appendChild(showSpan); + selectorContainer.appendChild(getEntriesDropdown(table)); + return selectorContainer; + }, +}); \ No newline at end of file diff --git a/src/tables/extensions/headerextensions.ts b/src/tables/extensions/headerextensions.ts index b9a872877..c13384db9 100644 --- a/src/tables/extensions/headerextensions.ts +++ b/src/tables/extensions/headerextensions.ts @@ -6,136 +6,61 @@ import { TableExtensions } from "./tableextensions"; TableExtensions.registerExtension({ location: "header", name: "filter", - visibleIndex: 0, + visibleIndex: 1, render: function (table: Table): HTMLElement { - const input = DocumentHelper.createInput( - "sa-table__global-filter sa-table__header-extension", - localization.getString("filterPlaceholder") - ); - input.onchange = (event: any) => { - table.applyFilter(event.target.value); - }; - return input; + // const input = DocumentHelper.createInput( + // "sa-table__global-filter sa-table__header-extension", + // localization.getString("filterPlaceholder") + // ); + // input.onchange = (event: any) => { + // table.applyFilter(event.target.value); + // }; + const el = DocumentHelper.createTextEditor({ + onchange: (val) => { table.applyFilter(val); } + }); + return el; }, }); TableExtensions.registerExtension({ location: "header", name: "showcolumn", - visibleIndex: 2, - destroy: function () { - this.onDestroy(); - }, + visibleIndex: 20, render: function (table: Table): HTMLElement { - const dropdown = DocumentHelper.createElement( - "select", - "sa-table__show-column sa-table__header-extension" - ); - - function update() { - var hiddenColumns = table.columns.filter( - (column: any) => !column.isVisible - ); - if (hiddenColumns.length == 0) { - dropdown.style.display = "none"; - return; + // const dropdown = DocumentHelper.createElement( + // "select", + // "sa-table__show-column sa-table__header-extension" + // ); + + const allColumns = table.columns.map((column) => { + var text = column.displayName || column.name; + if (!!text && text.length > 20) { + text = text.substring(0, 20) + "..."; } - dropdown.style.display = "inline-block"; - dropdown.innerHTML = ""; - var option = DocumentHelper.createElement("option", "", { - text: localization.getString("showColumn"), - disabled: true, - selected: true, - }); - dropdown.appendChild(option); - - hiddenColumns.forEach((column: any) => { - var text = column.displayName || column.name; - if (!!text && text.length > 20) { - text = text.substring(0, 20) + "..."; - } - var option = DocumentHelper.createElement("option", "", { - text: text, - title: column.displayName, - value: column.name, - }); - dropdown.appendChild(option); - }); - } - - dropdown.onchange = (e: any) => { - const val = e.target.value; - e.stopPropagation(); - if (!val) return; - table.setColumnVisibility(val, true); - }; - - update(); - - var onVisibilityChangedCallback = () => { - update(); - }; - - table.onColumnsVisibilityChanged.add(onVisibilityChangedCallback); - - this.onDestroy = () => { - table.onColumnsVisibilityChanged.remove(onVisibilityChangedCallback); - }; - return dropdown; - }, -}); - -TableExtensions.registerExtension({ - location: "header", - name: "showentries", - visibleIndex: 3, - render: function (table: Table): HTMLElement { - if(table.options.paginationEnabled === false) { - return DocumentHelper.createElement("div"); - } - function getEntriesDropdown(table: Table): HTMLElement { - const el = DocumentHelper.createElement("select"); - var optionsValues = table.paginationSizeSelector || ["1", "5", "10", "25", "50", "75", "100"]; - optionsValues.forEach(function (val) { - var option = DocumentHelper.createElement("option", "", { - value: val, - text: val, - }); - el.appendChild(option); - }); - el.value = String(table.getPageSize()); - - el.onchange = () => { - table.setPageSize(Number(el.value)); + return { + value: column.name, + text: text, + title: column.displayName || column.name, + icon: "check-24x24" }; - - return el; - } - const selectorContainer = DocumentHelper.createElement( - "div", - "sa-table__entries" - ); - const spaceSpan = DocumentHelper.createElement("span", "sa-table__header-space"); - const showSpan = DocumentHelper.createElement( - "span", - "sa-table__entries-label sa-table__entries-label--right", - { - innerText: localization.getString("showLabel"), - } - ); - const entriesSpan = DocumentHelper.createElement( - "span", - "sa-table__entries-label sa-table__entries-label--left", - { - innerText: localization.getString("entriesLabel"), - } + }); + const dropdown = DocumentHelper.createActionDropdown( + allColumns, + (option: any) => { + const hiddenColumns = table.columns.filter((column: any) => !column.isVisible); + return hiddenColumns.length === 0 || hiddenColumns.filter(el => el.name === option.value).length === 0; }, + (e: any) => { + if(!!e) { + if (!e) return; + const column = table.columns.filter((column: any) => column.name === e)[0]; + table.setColumnVisibility(e, !column.isVisible); + return false; + } + }, + localization.getString("columns") ); - - selectorContainer.appendChild(spaceSpan); - selectorContainer.appendChild(showSpan); - selectorContainer.appendChild(getEntriesDropdown(table)); - selectorContainer.appendChild(entriesSpan); - return selectorContainer; + dropdown.className += " sa-table__show-column sa-table__header-extension"; + return dropdown; }, }); @@ -144,35 +69,44 @@ TableExtensions.registerExtension({ name: "removerows", visibleIndex: -1, render: function (table) { - var btn = DocumentHelper.createElement( - "button", - "sa-table__btn sa-table__btn--green sa-table__header-extension ", - { innerText: localization.getString("removeRows") } - ); - btn.onclick = function () { - table.getCreatedRows().forEach(function (row) { - if (row.getIsSelected()) { - row.remove(); - } - }); - }; + const btn = DocumentHelper.createButton( + (e) => { + table.getCreatedRows().forEach(function (row) { + if (row.getIsSelected()) { + row.remove(); + } + }); + }, localization.getString("removeRows"), "sa-button"); + btn.className += " sa-table__header-extension sa-button-brand-tertiary"; return btn; + // var btn = DocumentHelper.createElement( + // "button", + // "sa-table__btn sa-table__header-extension ", + // { innerText: localization.getString("removeRows") } + // ); + // btn.onclick = function () { + // table.getCreatedRows().forEach(function (row) { + // if (row.getIsSelected()) { + // row.remove(); + // } + // }); + // }; + // return btn; }, }); TableExtensions.registerExtension({ location: "header", name: "changelocale", - visibleIndex: 1, + visibleIndex: 40, render: function (table) { var locales = table.getLocales(); if (table.options.disableLocaleSwitch || locales.length < 2) return null; + /* const el = ( DocumentHelper.createElement("select", "sa-table__header-extension", {}) ); - var optionsValues = [localization.getString("changeLocale")].concat( - locales - ); + var optionsValues = [localization.getString("changeLocale")].concat(locales); optionsValues.forEach(function (val) { var option = DocumentHelper.createElement("option", "", { value: val, @@ -183,6 +117,21 @@ TableExtensions.registerExtension({ el.onchange = () => { table.locale = el.value; }; + */ + + const optionsValues = locales.map(val => { return { value: val, text: localization.localeNames[val] || localization.getString(val) || val }; }); + const el = DocumentHelper.createActionDropdown( + optionsValues, + (option: any) => false, + (e: any) => { + if(!!e) { + table.locale = e; + } + return true; + }, + () => localization.getString("changeLocale"), + ); + el.className += " sa-table__header-extension"; return el; }, }); diff --git a/src/tables/extensions/rowextensions.ts b/src/tables/extensions/rowextensions.ts index 69f27ef95..9ca0524ee 100644 --- a/src/tables/extensions/rowextensions.ts +++ b/src/tables/extensions/rowextensions.ts @@ -8,8 +8,7 @@ TableExtensions.registerExtension({ name: "details", visibleIndex: 0, render: (_table: Table, options: any) => { - const btn = DocumentHelper.createSvgButton("detail"); - btn.title = localization.getString("showMinorColumns"); + const btn = DocumentHelper.createSvgButton("more-24x24", localization.getString("showMinorColumns")); btn.className += " sa-table__row-extension"; btn.onclick = () => { options.row.toggleDetails(); @@ -23,18 +22,34 @@ TableExtensions.registerExtension({ name: "select", visibleIndex: -1, render: function (_table, opt) { - var row = opt.row; - var checkbox = DocumentHelper.createElement( - "input", - "sa-table__row-extension", - { - type: "checkbox", - } - ); - checkbox.checked = row.getIsSelected(); - checkbox.onchange = function () { + const itemClassSelected = "sa-checkbox--checked"; + const row = opt.row; + const iconContainer = DocumentHelper.createSvgButton("check-24x24"); + iconContainer.onclick = () => { row.toggleSelect(); + if (row.getIsSelected()) { + iconContainer.classList.add(itemClassSelected); + } else { + iconContainer.classList.remove(itemClassSelected); + } }; - return checkbox; + iconContainer.className = "sa-checkbox sa-table__row-extension"; + + if (row.getIsSelected()) { + iconContainer.classList.add(itemClassSelected); + } + + // var checkbox = DocumentHelper.createElement( + // "input", + // "sa-table__row-extension", + // { + // type: "checkbox", + // } + // ); + // checkbox.checked = row.getIsSelected(); + // checkbox.onchange = function () { + // row.toggleSelect(); + // }; + return iconContainer; }, }); diff --git a/src/tables/extensions/tableextensions.ts b/src/tables/extensions/tableextensions.ts index eb0b66877..000d8dfaa 100644 --- a/src/tables/extensions/tableextensions.ts +++ b/src/tables/extensions/tableextensions.ts @@ -18,17 +18,21 @@ export class TableExtensions { if (!!extensions) { extensions = this.sortExtensions(extensions); extensions.forEach((extension) => { - if (!!extension.render && this.table.allowExtension(extension)) { - var action = extension.render(this.table, options); - if (!!action) { - targetNode.appendChild(action); - this.renderedExtensions.push(extension); - } - } + this.renderExtension(extension, targetNode, options); }); } } + public renderExtension(extension: ITableExtension, targetNode: HTMLElement, options?: any) { + if (!!extension.render && this.table.allowExtension(extension)) { + var action = extension.render(this.table, options); + if (!!action) { + targetNode.appendChild(action); + this.renderedExtensions.push(extension); + } + } + } + public destroy() { this.renderedExtensions.forEach((extension) => { if (!!extension.destroy) extension.destroy(); @@ -86,7 +90,7 @@ export class TableExtensions { return this.extensions[location].slice(0); } - private sortExtensions(extensions: Array) { + public sortExtensions(extensions: Array) { if (!Array.isArray(extensions)) return; return [] .concat(extensions.filter((extension) => extension.visibleIndex >= 0)) diff --git a/src/tables/table.scss b/src/tables/table.scss index e3fcecd71..041ea4473 100644 --- a/src/tables/table.scss +++ b/src/tables/table.scss @@ -24,15 +24,20 @@ $root-font-size: var(--root-font-size, 14px); @mixin arrow() { display: inline-block; - background: transparent; background-image: url("data:image/svg+xml,%3C%3Fxml version='1.0' encoding='utf-8'%3F%3E%3C!-- Generator: Adobe Illustrator 21.1.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) --%3E%3Csvg version='1.1' id='Layer_1' xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink' x='0px' y='0px' viewBox='0 0 10 10' style='enable-background:new 0 0 10 10;' xml:space='preserve'%3E%3Cstyle type='text/css'%3E .st0%7Bfill:%23a0a0a0;%7D%0A%3C/style%3E%3Cpolygon class='st0' points='2,2 0,4 5,9 10,4 8,2 5,5 '/%3E%3C/svg%3E%0A"); background-repeat: no-repeat, repeat; background-size: 9px 100%; - height: 10px; - width: 10px; + // height: 10px; + // width: 10px; white-space: nowrap; overflow: hidden; text-indent: -9999px; + + width: 24px; + height: 24px; + flex-shrink: 0; + box-sizing: content-box; + background-position: center 0, center 5px; } @mixin dropdown() { @@ -101,7 +106,7 @@ $root-font-size: var(--root-font-size, 14px); } .sa-table__detail-row.sa-table__detail-row.sa-table__detail-row.sa-table__detail-row { - background-color: $detail-color; + background: var(--sjs2-color-bg-basic-secondary, rgba(28, 27, 32, 0.05)); } .sa-table__detail-table.sa-table__detail-table { @@ -112,24 +117,35 @@ $root-font-size: var(--root-font-size, 14px); } .sa-table__detail { - border-top: 1px solid $border-color; + border-top: var(--sjs2-border-width-default, 1px) dashed var(--sjs2-color-border-basic-secondary, #D4D4D4); + td { box-sizing: border-box; - padding: 20px; border-left: none; border-right: none; white-space: initial; + + padding: var(--sjs2-spacing-x200, 16px) var(--sjs2-spacing-x300, 24px); + + color: var(--sjs2-color-fg-basic-primary, #1C1B20); + /* sjs2/typography/default-strong */ + font-family: var(--sjs2-typography-font-family-default, "Open Sans"); + font-size: var(--sjs2-typography-font-size-default, 16px); + font-style: normal; + font-weight: 600; + line-height: var(--sjs2-typography-line-height-default, 24px); /* 150% */ } td:first-child { - width: 267px; - border-left: none; - font-weight: bold; + display: flex; + padding: var(--sjs2-spacing-x100, 8px); + align-items: flex-start; + align-self: stretch; } - td:nth-child(2) { - width: 208px; - } + // td:nth-child(2) { + // width: 208px; + // } } .sa-table__btn { @@ -174,30 +190,139 @@ a.sa-table__btn { } .sa-table__svg-button { - width: 15px; - height: 15px; - padding: 0; + display: flex; + padding: var(--sjs2-layout-control-action-small-box-vertical, 8px) var(--sjs2-layout-control-action-small-box-horizontal, 8px); + justify-content: center; + align-items: center; + gap: var(--sjs2-layout-control-action-small-box-gap, 0); border: none; + box-sizing: content-box; + + &:hover { + border-radius: var(--sjs2-radius-control-action-icon, 8px); + background: var(--sjs2-color-bg-brand-tertiary-dim, rgba(25, 179, 148, 0.10)); + } + &:focus-visible { + border-radius: var(--sjs2-radius-control-action-icon, 8px); + outline: var(--sjs2-border-width-a11y, 4px) solid var(--sjs2-color-utility-a11y, rgba(102, 180, 252, 0.60)); + background: var(--sjs2-color-bg-brand-tertiary, rgba(25, 179, 148, 0.00)); + } + svg { + width: 24px; + height: 24px; + flex-shrink: 0; + } + use { - fill: $svg-color; + fill: var(--sjs2-color-fg-brand-primary, #19B394); } - &:hover { - use { - fill: $svg-hover-color; - } +} + +.sa-tabulator-column-header { + display: flex; + padding: var(--sjs2-spacing-x200, 16px) var(--sjs2-spacing-x300, 24px) var(--sjs2-spacing-x150, 12px) var(--sjs2-spacing-x300, 24px); + flex-direction: column; + align-items: flex-start; + gap: var(--sjs2-spacing-x100, 8px); + flex: 1 0 0; + background: var(--sjs2-color-bg-basic-primary, #FFF); +} + +.sa-tabulator-column-title-text { + color: var(--sjs2-color-fg-basic-primary, #1C1B20); + flex: 1 0 0; + + /* sjs2/typography/default-strong */ + font-family: var(--sjs2-typography-font-family-default, "Open Sans"); + font-size: var(--sjs2-typography-font-size-default, 16px); + font-style: normal; + font-weight: 600; + line-height: var(--sjs2-typography-line-height-default, 24px); /* 150% */ +} + +.sa-table-filter { + display: flex; + padding: var(--sjs2-layout-control-formbox-small-vertical, 4px) var(--sjs2-layout-control-formbox-small-horizontal, 4px); + align-items: flex-start; + gap: var(--sjs2-layout-control-formbox-small-gap, 4px); + align-self: stretch; + border-radius: var(--sjs2-radius-semantic-form, 8px); + background: var(--sjs2-color-control-formbox-default-bg, #F5F5F5); + box-shadow: var(--sjs2-border-offset-x-form-default, 0) var(--sjs2-border-offset-y-form-default, 0) var(--sjs2-border-blur-form-default, 0) var(--sjs2-border-spread-form-default, 1px) var(--sjs2-color-control-formbox-default-border, #D4D4D4) inset; + + &:focus-within { + background: var(--sjs2-color-control-formbox-focused-bg, #F5F5F5); + box-shadow: var(--sjs2-border-offset-x-form-focused, 0) var(--sjs2-border-offset-y-form-focused, 0) var(--sjs2-border-blur-form-focused, 0) var(--sjs2-border-spread-form-focused, 2px) var(--sjs2-color-control-formbox-focused-border, #19B394) inset; } +} + +.sa-table-filter_icon { + display: flex; + padding: var(--sjs2-layout-control-input-small-icon-vertical, 4px) var(--sjs2-layout-control-input-small-icon-right, 0) var(--sjs2-layout-control-input-small-icon-vertical, 4px) var(--sjs2-layout-control-input-small-icon-left, 4px); + justify-content: center; + align-items: center; + svg { - width: 15px; - height: 15px; + width: 24px; + height: 24px; + flex-shrink: 0; + } + + use { + fill: var(--sjs2-color-control-input-default-icon, rgba(28, 27, 32, 0.40)); + } +} + +.sa-table-filter_input.sa-table-filter_input { + display: flex; + padding: var(--sjs2-layout-control-input-small-content-vertical, 4px) var(--sjs2-layout-control-input-small-content-horizontal, 8px); + align-items: flex-start; + flex: 1 0 0; + border: none; + overflow: hidden; + color: var(--sjs2-color-control-input-default-value, #1C1B20); + text-overflow: ellipsis; + + /* sjs2/typography/default */ + font-family: var(--sjs2-typography-font-family-default, "Open Sans"); + font-size: var(--sjs2-typography-font-size-default, 16px); + font-style: normal; + font-weight: 400; + line-height: var(--sjs2-typography-line-height-default, 24px); /* 150% */ + + &::placeholder { + overflow: hidden; + color: var(--sjs2-color-control-input-default-placeholder, rgba(28, 27, 32, 0.60)); + text-overflow: ellipsis; } } +.sa-table__filter-container { + display: flex; + padding: var(--sjs2-spacing-x100, 8px) 0; + flex-direction: column; + align-items: flex-start; + align-self: stretch; + + // display: flex; + // margin: var(--sjs2-spacing-x100, 8px) 0; + // flex-direction: column; + // align-items: flex-start; + // align-self: stretch; + + // padding: var(--sjs2-layout-control-formbox-small-vertical, 4px) var(--sjs2-layout-control-formbox-small-horizontal, 4px); + // gap: var(--sjs2-layout-control-formbox-small-gap, 4px); + // border-radius: var(--sjs2-radius-semantic-form, 8px); + // background: var(--sjs2-color-control-formbox-default-bg, rgba(28, 27, 32, 0.05)); + // box-shadow: var(--sjs2-border-offset-x-form-default, 0) var(--sjs2-border-offset-y-form-default, 0) var(--sjs2-border-blur-form-default, 0) var(--sjs2-border-spread-form-default, 1px) var(--sjs2-color-control-formbox-default-border, #D4D4D4) inset; +} + .sa-table__action-container { - margin-bottom: 10px; - white-space: normal; + display: flex; + align-items: center; + align-self: stretch; + .sa-table__svg-button { - float: right; - margin: 0 0 13px 13px; pointer-events: all; } &:after { @@ -208,12 +333,7 @@ a.sa-table__btn { .sa-table__drag-button { float: left; cursor: move; - use { - fill: $main-color; - } - &:hover use { - fill: $main-color; - } + margin-inline-end: auto; } } @@ -233,52 +353,78 @@ a.sa-table__btn { .sa-table__filter.sa-table__filter { width: 100%; + min-width: 195px; + border: none; + border-radius: var(--dsb-table-view-column-search-corner-radius, 6px); + outline: var(--dsb-table-view-column-search-border-width, 0px) solid var(--dsb-table-view-column-search-border-color, #DCDCDC); + background: var(--dsb-table-view-column-search-background-color, #F4F4F4); + padding: var(--dsb-table-view-column-search-padding-top, 8px) var(--dsb-table-view-column-search-padding-right, 16px) var(--dsb-table-view-column-search-padding-bottom, 8px) var(--dsb-table-view-column-search-padding-left, 16px); + margin-inline-end: var(--dsb-table-view-header-toolbar-gap, 16px); + + overflow: hidden; + color: var(--dsb-table-view-column-search-text-color, rgba(0, 0, 0, 0.50)); + text-overflow: ellipsis; + + /* ctr/Default */ + font-family: $font-family; + font-size: var(--ctr-font-default-size, 16px); + font-style: normal; + font-weight: 400; + line-height: var(--ctr-font-default-line-height, 24px); /* 150% */ } -.sa-table__show-column.sa-table__show-column { - background: transparent; - background-image: url("data:image/svg+xml,%3C%3Fxml version='1.0' encoding='utf-8'%3F%3E%3C!-- Generator: Adobe Illustrator 24.0.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) --%3E%3Csvg version='1.1' id='Layer_1' xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink' x='0px' y='0px' viewBox='0 0 16 16' style='enable-background:new 0 0 16 16;' xml:space='preserve'%3E%3Cstyle type='text/css'%3E .st0%7Bfill:rgba(159, 159, 159, 0.5);%7D .st1%7Bfill:rgba(159, 159, 159, 0.5);%7D%0A%3C/style%3E%3Cg%3E%3Cpath class='st1' d='M8,2.03C3.63,2.03,0,8,0,8s3.63,6.03,8,6.03s8-6,8-6S12.37,2.03,8,2.03z M8,12c-2.58,0-5.13-2.81-6-4 c1.07-1.47,3.61-4,6-4c2.58,0,5.13,2.81,6,4C12.93,9.47,10.39,12,8,12z'/%3E%3Ccircle class='st1' cx='8' cy='8' r='3'/%3E%3C/g%3E%3C/svg%3E"), - url("data:image/svg+xml,%3C%3Fxml version='1.0' encoding='utf-8'%3F%3E%3C!-- Generator: Adobe Illustrator 21.1.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) --%3E%3Csvg version='1.1' id='Layer_1' xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink' x='0px' y='0px' viewBox='0 0 10 10' style='enable-background:new 0 0 10 10;' xml:space='preserve'%3E%3Cstyle type='text/css'%3E .st0%7Bfill:%23404040;%7D%0A%3C/style%3E%3Cpolygon class='st0' points='2,2 0,4 5,9 10,4 8,2 5,5 '/%3E%3C/svg%3E%0A"); - background-repeat: no-repeat, no-repeat; - background-position: - left 0.7em top 50%, - right 0.7em top 50%; - background-size: - 1em 100%, - 0.57em 100%; - padding-left: 35px; - border: solid 1px $border-color; - pointer-events: all; - margin-left: 20px; - &:focus { - background-image: url("data:image/svg+xml,%3C%3Fxml version='1.0' encoding='utf-8'%3F%3E%3C!-- Generator: Adobe Illustrator 24.0.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) --%3E%3Csvg version='1.1' id='Layer_1' xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink' x='0px' y='0px' viewBox='0 0 16 16' style='enable-background:new 0 0 16 16;' xml:space='preserve'%3E%3Cstyle type='text/css'%3E .st0%7Bfill:rgba(159, 159, 159, 0.5);%7D .st1%7Bfill:rgba(159, 159, 159, 0.5);%7D%0A%3C/style%3E%3Cg%3E%3Cpath class='st1' d='M8,2.03C3.63,2.03,0,8,0,8s3.63,6.03,8,6.03s8-6,8-6S12.37,2.03,8,2.03z M8,12c-2.58,0-5.13-2.81-6-4 c1.07-1.47,3.61-4,6-4c2.58,0,5.13,2.81,6,4C12.93,9.47,10.39,12,8,12z'/%3E%3Ccircle class='st1' cx='8' cy='8' r='3'/%3E%3C/g%3E%3C/svg%3E"), - url("data:image/svg+xml,%3C%3Fxml version='1.0' encoding='utf-8'%3F%3E%3C!-- Generator: Adobe Illustrator 21.1.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) --%3E%3Csvg version='1.1' id='Layer_1' xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink' x='0px' y='0px' viewBox='0 0 10 10' style='enable-background:new 0 0 10 10;' xml:space='preserve'%3E%3Cstyle type='text/css'%3E .st0%7Bfill:%231AB394;%7D%0A%3C/style%3E%3Cpolygon class='st0' points='2,2 0,4 5,9 10,4 8,2 5,5 '/%3E%3C/svg%3E ") !important; - } +.sa-table__filter.sa-table__filter:focus { + outline: var(--dsb-table-view-column-search-border-width-focused, 2px) solid var(--dsb-table-view-column-search-border-color-focused, #19B394); } +// .sa-table__show-column.sa-table__show-column { +// background: transparent; +// background-image: url("data:image/svg+xml,%3C%3Fxml version='1.0' encoding='utf-8'%3F%3E%3C!-- Generator: Adobe Illustrator 24.0.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) --%3E%3Csvg version='1.1' id='Layer_1' xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink' x='0px' y='0px' viewBox='0 0 16 16' style='enable-background:new 0 0 16 16;' xml:space='preserve'%3E%3Cstyle type='text/css'%3E .st0%7Bfill:rgba(159, 159, 159, 0.5);%7D .st1%7Bfill:rgba(159, 159, 159, 0.5);%7D%0A%3C/style%3E%3Cg%3E%3Cpath class='st1' d='M8,2.03C3.63,2.03,0,8,0,8s3.63,6.03,8,6.03s8-6,8-6S12.37,2.03,8,2.03z M8,12c-2.58,0-5.13-2.81-6-4 c1.07-1.47,3.61-4,6-4c2.58,0,5.13,2.81,6,4C12.93,9.47,10.39,12,8,12z'/%3E%3Ccircle class='st1' cx='8' cy='8' r='3'/%3E%3C/g%3E%3C/svg%3E"), +// url("data:image/svg+xml,%3C%3Fxml version='1.0' encoding='utf-8'%3F%3E%3C!-- Generator: Adobe Illustrator 21.1.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) --%3E%3Csvg version='1.1' id='Layer_1' xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink' x='0px' y='0px' viewBox='0 0 10 10' style='enable-background:new 0 0 10 10;' xml:space='preserve'%3E%3Cstyle type='text/css'%3E .st0%7Bfill:%23404040;%7D%0A%3C/style%3E%3Cpolygon class='st0' points='2,2 0,4 5,9 10,4 8,2 5,5 '/%3E%3C/svg%3E%0A"); +// background-repeat: no-repeat, no-repeat; +// background-position: +// left 0.7em top 50%, +// right 0.7em top 50%; +// background-size: +// 1em 100%, +// 0.57em 100%; +// padding-left: 35px; +// border: solid 1px $border-color; +// pointer-events: all; +// margin-left: 20px; +// &:focus { +// background-image: url("data:image/svg+xml,%3C%3Fxml version='1.0' encoding='utf-8'%3F%3E%3C!-- Generator: Adobe Illustrator 24.0.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) --%3E%3Csvg version='1.1' id='Layer_1' xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink' x='0px' y='0px' viewBox='0 0 16 16' style='enable-background:new 0 0 16 16;' xml:space='preserve'%3E%3Cstyle type='text/css'%3E .st0%7Bfill:rgba(159, 159, 159, 0.5);%7D .st1%7Bfill:rgba(159, 159, 159, 0.5);%7D%0A%3C/style%3E%3Cg%3E%3Cpath class='st1' d='M8,2.03C3.63,2.03,0,8,0,8s3.63,6.03,8,6.03s8-6,8-6S12.37,2.03,8,2.03z M8,12c-2.58,0-5.13-2.81-6-4 c1.07-1.47,3.61-4,6-4c2.58,0,5.13,2.81,6,4C12.93,9.47,10.39,12,8,12z'/%3E%3Ccircle class='st1' cx='8' cy='8' r='3'/%3E%3C/g%3E%3C/svg%3E"), +// url("data:image/svg+xml,%3C%3Fxml version='1.0' encoding='utf-8'%3F%3E%3C!-- Generator: Adobe Illustrator 21.1.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) --%3E%3Csvg version='1.1' id='Layer_1' xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink' x='0px' y='0px' viewBox='0 0 10 10' style='enable-background:new 0 0 10 10;' xml:space='preserve'%3E%3Cstyle type='text/css'%3E .st0%7Bfill:%231AB394;%7D%0A%3C/style%3E%3Cpolygon class='st0' points='2,2 0,4 5,9 10,4 8,2 5,5 '/%3E%3C/svg%3E ") !important; +// } +// } + .sa-table__entries { - float: right; - white-space: nowrap; + // float: right; + // white-space: nowrap; + display: flex; + justify-content: flex-end; + align-items: center; + gap: var(--sjs2-spacing-x100, 8px); } .sa-table__entries-label { - font-weight: bold; + // font-weight: bold; + color: var(--sjs2-color-fg-basic-primary, #1C1B20); + + /* sjs2/typography/default */ + font-family: var(--sjs2-typography-font-family-default, "Open Sans"); + font-size: var(--sjs2-typography-font-size-default, 16px); + font-style: normal; + font-weight: 400; + line-height: var(--sjs2-typography-line-height-default, 24px); /* 150% */ } -.sa-table__entries-label--right { - margin-right: 5px; -} - -.sa-table__entries-label--left { - margin-left: 5px; +.sa-table__entries-value .sa-action-dropdown-list { + bottom: 48px; } .sa-table__detail-row { - background-color: $detail-color; -} - -.sa-table__detail-table { - background-color: $detail-color; + background: var(--sjs2-color-bg-basic-secondary, rgba(28, 27, 32, 0.05)); } .sa-table input.sa-table__row-extension { @@ -286,16 +432,69 @@ a.sa-table__btn { } .sa-table__row-extension + .sa-table__row-extension { - margin-left: 10px; vertical-align: middle; } +.sa-table__row-extension { + margin: auto; +} + .sa-table__header-extensions { - float: left; - margin-left: 10px; - width: calc(100% - 540px); + display: flex; + align-items: center; + gap: 12px; + flex: 1 0 0; + flex-wrap: wrap; } -.sa-table__header-extension + .sa-table__header-extension { - margin-left: 10px; +// .sa-table__header-extension { +// flex: 1 0 auto; +// } + +.sa-checkbox.sa-checkbox { + display: flex; + width: var(--sjs2-size-x300, 24px); + height: var(--sjs2-size-x300, 24px); + flex-direction: column; + justify-content: center; + align-items: center; + border: none; + outline: none; + padding: 0; + + border-radius: var(--sjs2-radius-control-checkbox, 4px); + background: var(--sjs2-color-control-check-false-default-bg, #F5F5F5); + box-shadow: var(--sjs2-border-offset-x-form-default, 0) var(--sjs2-border-offset-y-form-default, 0) var(--sjs2-border-blur-form-default, 0) var(--sjs2-border-spread-form-default, 1px) var(--sjs2-color-control-check-false-default-border, #D4D4D4) inset; + + &:hover { + background: var(--sjs2-color-control-check-false-hovered-bg, rgba(28, 27, 32, 0.10)); + box-shadow: var(--sjs2-border-offset-x-form-hovered, 0) var(--sjs2-border-offset-y-form-hovered, 0) var(--sjs2-border-blur-form-hovered, 0) var(--sjs2-border-spread-form-hovered, 1px) var(--sjs2-color-control-check-false-hovered-border, #D4D4D4) inset; + } + + svg { + display: none; + width: var(--sjs2-size-x200, 16px); + height: var(--sjs2-size-x200, 16px);; + justify-content: center; + align-items: center; + flex-shrink: 0; + } + + use { + fill: var(--sjs2-color-control-check-true-default-icon, #FFF); + } } + +.sa-checkbox--checked.sa-checkbox--checked { + background: var(--sjs2-color-control-check-true-default-bg, #19B394); + box-shadow: var(--sjs2-border-offset-x-form-default, 0) var(--sjs2-border-offset-y-form-default, 0) var(--sjs2-border-blur-form-default, 0) var(--sjs2-border-spread-form-default, 1px) var(--sjs2-color-control-check-true-default-border, #19B394) inset; + + &:hover { + background: var(--sjs2-color-control-check-true-hovered-bg, #15987E); + box-shadow: var(--sjs2-border-offset-x-form-hovered, 0) var(--sjs2-border-offset-y-form-hovered, 0) var(--sjs2-border-blur-form-hovered, 0) var(--sjs2-border-spread-form-hovered, 1px) var(--sjs2-color-control-check-true-hovered-border, #15987E) inset; + } + + svg { + display: flex; + } +} \ No newline at end of file diff --git a/src/tables/tabulator.scss b/src/tables/tabulator.scss index 8e033698f..a61048d2c 100755 --- a/src/tables/tabulator.scss +++ b/src/tables/tabulator.scss @@ -2,40 +2,70 @@ @mixin doubleArrow() { display: inline-block; - background: transparent; background-image: url("data:image/svg+xml,%3C%3Fxml version='1.0' encoding='utf-8'%3F%3E%3C!-- Generator: Adobe Illustrator 21.1.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) --%3E%3Csvg version='1.1' id='Layer_1' xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink' x='0px' y='0px' viewBox='0 0 10 10' style='enable-background:new 0 0 10 10;' xml:space='preserve'%3E%3Cstyle type='text/css'%3E .st0%7Bfill:%23a0a0a0;%7D%0A%3C/style%3E%3Cpolygon class='st0' points='2,2 0,4 5,9 10,4 8,2 5,5 '/%3E%3C/svg%3E%0A"), url("data:image/svg+xml,%3C%3Fxml version='1.0' encoding='utf-8'%3F%3E%3C!-- Generator: Adobe Illustrator 21.1.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) --%3E%3Csvg version='1.1' id='Layer_1' xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink' x='0px' y='0px' viewBox='0 0 10 10' style='enable-background:new 0 0 10 10;' xml:space='preserve'%3E%3Cstyle type='text/css'%3E .st0%7Bfill:%23a0a0a0;%7D%0A%3C/style%3E%3Cpolygon class='st0' points='2,2 0,4 5,9 10,4 8,2 5,5 '/%3E%3C/svg%3E%0A"); background-repeat: no-repeat, no-repeat; background-size: 9px 100%; - background-position: - left 0, - left 5px; - height: 20px; - width: 10px; + // background-position: left 0, left 5px; + // height: 20px; + // width: 10px; white-space: nowrap; overflow: hidden; text-indent: -9999px; + + width: 24px; + height: 24px; + flex-shrink: 0; + box-sizing: content-box; + background-position: center -3px, center 3px; } -.sa-tabulator__header { - padding: 20px 13px; - background-color: $background-gray; - overflow: auto; +.sa-tabulator__wrapper { display: flex; - flex-direction: row; - gap: 10px; - flex-wrap: wrap; - - &:after { - content: ""; - clear: both; - display: block; - } + padding: var(--sjs2-spacing-x300, 24px); + flex-direction: column; + align-items: center; + gap: var(--sjs2-spacing-x300, 24px); + align-self: stretch; + background: var(--sjs2-color-utility-surface-muted, rgba(28, 27, 32, 0.05)); +} - .sa-table__header-space { - display: flex; - flex-grow: 1; - } +.sa-tabulator__table-container { + // overflow-y: auto; + width: 100%; +} + +.sa-tabulator__container { + max-width: 100%; + display: flex; + flex-direction: column; + align-items: flex-start; + flex: 1 0 0; + border-radius: var(--sjs2-radius-container-panel, 16px); + background: var(--sjs2-color-bg-basic-primary, #FFF); + + /* sjs2/border-effect/surface/default */ + box-shadow: var(--sjs2-border-offset-x-surface-default, 0) var(--sjs2-border-offset-y-surface-default, 0) var(--sjs2-border-blur-surface-default, 0) var(--sjs2-border-spread-surface-default, 1px) var(--sjs2-color-utility-shadow-surface-default, rgba(17, 16, 20, 0.10)); +} + +.sa-tabulator__header { + display: flex; + padding: var(--sjs2-spacing-x300, 24px); + align-items: flex-start; + flex: 1 0 0; + align-self: stretch; + border-bottom: var(--sjs2-border-width-default, 1px) solid var(--sjs2-color-border-basic-secondary, #D4D4D4); + + // &:after { + // content: ""; + // clear: both; + // display: block; + // } + + // .sa-table__footer-space { + // display: flex; + // flex-grow: 1; + // } .sa-table__entries { float: none; @@ -45,18 +75,53 @@ } } -.sa-tabulator__downloads-bar { - float: left; +.sa-tabulator__footer { + display: flex; + padding: var(--sjs2-spacing-x200, 16px) var(--sjs2-spacing-x300, 24px); + justify-content: space-between; + align-items: center; + flex: 1 0 0; + align-self: stretch; + border-top: var(--sjs2-border-width-default, 1px) solid var(--sjs2-color-border-basic-secondary, #D4D4D4); +} + +.sa-tabulator__header { .sa-table__btn { - margin-left: 10px; + display: flex; + min-width: var(--sjs2-size-semantic-small, 40px); + justify-content: center; + align-items: center; + + color: var(--sjs2-color-fg-brand-primary, #19B394); + text-align: center; + + /* sjs2/typography/default-strong */ + font-family: var(--sjs2-typography-font-family-default, "Open Sans"); + font-size: var(--sjs2-typography-font-size-default, 16px); + font-style: normal; + font-weight: 600; + line-height: var(--sjs2-typography-line-height-default, 24px); /* 150% */ } } +.tabulator-headers { + border-bottom: var(--sjs2-border-width-default, 1px) dashed var(--sjs2-color-border-basic-secondary, #D4D4D4); +} + +.sa-tabulator__downloads-bar { + // float: left; + // .sa-table__btn { + // margin-left: 10px; + // } +} + .sa-tabulator__pagination-container { - float: right; - margin-top: 8px; - min-width: 200px; - text-align: right; + // float: right; + // margin-top: 8px; + // min-width: 200px; + // text-align: right; + display: flex; + align-items: center; } .sa-tabulator__filter-container { @@ -74,66 +139,149 @@ //redefine tabulator's styles .sa-tabulator { .tabulator-page { - margin-right: 15px; - padding: 1px; - vertical-align: middle; - color: $text-gray; + // margin-right: 15px; + // padding: 1px; + // vertical-align: middle; + // color: $text-gray; cursor: pointer; outline: none; border: none; + display: flex; + padding: var(--sjs2-layout-control-action-small-box-vertical, 8px) var(--sjs2-layout-control-action-small-box-horizontal, 8px); + justify-content: center; + align-items: center; + gap: var(--sjs2-layout-control-action-small-box-gap, 0); + background: transparent; + + &:hover { + border-radius: var(--sjs2-radius-control-action-icon, 8px); + background: var(--sjs2-color-bg-brand-tertiary-dim, rgba(25, 179, 148, 0.10)); + } - &:last-child { - margin-right: 0; + &:focus-visible { + border-radius: var(--sjs2-radius-control-action, 8px); + border: unset; + outline: var(--sjs2-border-width-a11y, 4px) solid var(--sjs2-color-utility-a11y, rgba(102, 180, 252, 0.60)); + background: var(--sjs2-color-bg-brand-tertiary, rgba(25, 179, 148, 0.00)); } &:disabled { cursor: default; + opacity: var(--sjs2-opacity-disabled, 0.25); + } + } + + .tabulator-pages { + display: flex; + align-items: center; + + .tabulator-page { + display: flex; + min-width: var(--sjs2-size-semantic-small, 40px); + padding: var(--sjs2-layout-control-action-small-box-vertical, 8px) var(--sjs2-layout-control-action-small-box-horizontal, 8px); + justify-content: center; + align-items: center; + gap: var(--sjs2-layout-control-action-small-box-gap, 0); + border-radius: var(--_ctr-survey-action-button-corner-radius, 8px); + background: var(--sjs2-color-bg-brand-tertiary, rgba(25, 179, 148, 0.00)); + + color: var(--sjs2-color-fg-basic-tertiary, rgba(28, 27, 32, 0.40)); + text-align: center; + + /* sjs2/typography/default-strong */ + font-family: var(--sjs2-typography-font-family-default, "Open Sans"); + font-size: var(--sjs2-typography-font-size-default, 16px); + font-style: normal; + font-weight: 600; + line-height: var(--sjs2-typography-line-height-default, 24px); /* 150% */ + + &:hover { + border-radius: var(--_ctr-survey-action-button-corner-radius, 8px); + background: var(--sjs2-color-bg-brand-tertiary-dim, rgba(25, 179, 148, 0.10)); + } } } .tabulator-page[aria-label~="Prev"] { @include arrow(); transform: rotate(90deg); - margin-right: 20px; } .tabulator-page[aria-label~="Next"] { @include arrow(); transform: rotate(270deg); - margin-left: 20px; - margin-right: 0; } .tabulator-page[aria-label~="First"] { @include doubleArrow(); transform: rotate(90deg); - margin-right: 10px; } .tabulator-page[aria-label~="Last"] { @include doubleArrow(); transform: rotate(270deg); - margin-left: 10px; } .tabulator-page.active { - font-weight: bold; - border-bottom: 1px solid $text-gray; + display: flex; + min-width: var(--sjs2-size-semantic-small, 40px); + padding: var(--sjs2-layout-control-action-small-box-vertical, 8px) var(--sjs2-layout-control-action-small-box-horizontal, 8px); + justify-content: center; + align-items: center; + gap: var(--sjs2-layout-control-action-small-box-gap, 0); + + border-radius: var(--_ctr-survey-action-button-corner-radius, 8px); + border: var(--sjs2-border-width-default, 1px) solid var(--sjs2-color-border-basic-secondary, #D4D4D4); + background: var(--sjs2-color-bg-positive-tertiary, rgba(25, 179, 148, 0.00)); + + color: var(--sjs2-color-fg-basic-primary, #1C1B20); + text-align: center; + + /* sjs2/typography/default-strong */ + font-family: var(--sjs2-typography-font-family-default, "Open Sans"); + font-size: var(--sjs2-typography-font-size-default, 16px); + font-style: normal; + font-weight: 600; + line-height: var(--sjs2-typography-line-height-default, 24px); /* 150% */ + + &:hover { + cursor: default; + background-color: transparent; + } } .tabulator { - border: 1px solid #ddd; - background-color: $background-color; + border: none; + background-color: transparent; + + .tabulator-table { + background-color: transparent; + } .tabulator-row .tabulator-cell { - padding: 20px; - border-top: 1px solid #ddd; - border-right: 1px solid #ddd; + padding: var(--sjs2-spacing-x200, 16px) var(--sjs2-spacing-x300, 24px); + border-top: var(--sjs2-border-width-default, 1px) dashed var(--sjs2-color-border-basic-secondary, #D4D4D4); + border-right: var(--sjs2-border-width-default, 1px) dashed var(--sjs2-color-border-basic-secondary, #D4D4D4); + + color: var(--sjs2-color-fg-basic-primary, #1C1B20); + /* sjs2/typography/default */ + font-family: var(--sjs2-typography-font-family-default, "Open Sans"); + font-size: var(--sjs2-typography-font-size-default, 16px); + font-style: normal; + font-weight: 400; + line-height: var(--sjs2-typography-line-height-default, 24px); /* 150% */ + + &.sa-tabulator-cell__action-details { + padding: var(--sjs2-spacing-x100, 8px); + } + + &.sa-tabulator-cell__action-select { + padding: var(--sjs2-spacing-x200, 16px); + } } .tabulator-header .tabulator-col { - padding: 13px 20px; - border-right: 1px solid #ddd; + border-right: var(--sjs2-border-width-default, 1px) dashed var(--sjs2-color-border-basic-secondary, #D4D4D4); } .tabulator-header .tabulator-col .tabulator-col-content { @@ -145,12 +293,16 @@ } .tabulator-header .tabulator-col.tabulator-sortable:hover { - background-color: white; + background-color: transparent; } .tabulator-header, .tabulator-header .tabulator-col { - background-color: white; + background-color: transparent; + } + + .tabulator-col.tabulator-moving { + border: var(--sjs2-border-width-default, 1px) dashed var(--sjs2-color-border-basic-secondary, #D4D4D4); } .tabulator-header .tabulator-col:first-child { @@ -161,17 +313,17 @@ display: none; } + .tabulator-row { + background: var(--sjs2-color-bg-basic-primary, #FFF); + } + .tabulator-row.tabulator-selectable:hover { cursor: default; - background-color: $background-color; + background: var(--sjs2-color-bg-basic-primary-dim, rgba(28, 27, 32, 0.05)); } .tabulator-row.tabulator-selectable.sa-table__detail-row:hover { - background-color: $detail-color; - } - - .tabulator-row.tabulator-row-even { - background-color: $background-color; + background: var(--sjs2-color-bg-basic-secondary, rgba(28, 27, 32, 0.05)); } .tabulator-header .tabulator-col .tabulator-col-content { @@ -182,14 +334,26 @@ padding-right: 0; } - .tabulator-tableholder::-webkit-scrollbar { - height: 10px; - width: 10px; - background-color: $scroll-color; - } - - .tabulator-tableholder::-webkit-scrollbar-thumb { - background: $main-color; + .tabulator-tableholder { + &::-webkit-scrollbar { + width: 8px; + height: 8px; + background-color: transparent; + } + + &::-webkit-scrollbar-thumb { + background-clip: padding-box; + border-radius: var(--ctr-scrollbar-corner-radius, 1024px); + background: var(--sjs2-color-utility-scrollbar, rgba(17, 16, 20, 0.15)); + } + + &::-webkit-scrollbar-track { + background: transparent; + } + + &::-webkit-scrollbar-corner { + background: transparent; + } } } } diff --git a/src/tables/tabulator.ts b/src/tables/tabulator.ts index a927c7699..2e2c8330e 100755 --- a/src/tables/tabulator.ts +++ b/src/tables/tabulator.ts @@ -7,6 +7,7 @@ import { ARIAL_FONT } from "./custom_jspdf_font"; import { svgTemplate } from "../svgbundle"; import type { DownloadType, SortDirection, TabulatorFull, RowComponent } from "tabulator-tables"; import { TableExtensions } from "./extensions/tableextensions"; +import { DashboardTheme, IDashboardTheme } from "../theme"; import "./tabulator.scss"; if (!!document) { @@ -55,8 +56,8 @@ export const defaultDownloadOptions = { export const defaultOptions: ITabulatorOptions = { tabulatorOptions: {}, - actionsColumnWidth: 60, - columnMinWidth: 248, + actionsColumnWidth: 56, + columnMinWidth: 384, downloadHiddenColumns: false, downloadButtons: ["csv"], downloadOptions: defaultDownloadOptions, @@ -87,6 +88,9 @@ const escapeCellFormula = (field: string) => { type TabulatorParameters = ConstructorParameters; type TabulatorConstuctor = { new (...args: TabulatorParameters): TabulatorFull }; export class Tabulator extends Table { + private _appliedTheme: DashboardTheme; + private _theme = new DashboardTheme(); + private static tabulatorTablesConstructor: TabulatorConstuctor; public static initTabulatorConstructor(tabulatorTablesConstructor: TabulatorConstuctor): void { this.tabulatorTablesConstructor = tabulatorTablesConstructor; @@ -131,19 +135,28 @@ export class Tabulator extends Table { targetNode = document.getElementById(targetNode); } targetNode.className += " sa-table sa-tabulator"; + if(!this._appliedTheme) { + this._appliedTheme = this.theme; + } + if(this._appliedTheme) { + this._appliedTheme.applyThemeToElement(targetNode); + } const columns = this.getColumns(); const data = this.tableData; + var wrapper = DocumentHelper.createElement("div", "sa-tabulator__wrapper"); + var container = DocumentHelper.createElement("div", "sa-tabulator__container"); var header = DocumentHelper.createElement("div", "sa-tabulator__header"); - var paginationElement = DocumentHelper.createElement( - "div", - "sa-tabulator__pagination-container" - ); - this.tableContainer = DocumentHelper.createElement("div"); + var footer = DocumentHelper.createElement("div", "sa-tabulator__footer"); + var paginationElement = DocumentHelper.createElement("div", "sa-tabulator__pagination-container"); + this.tableContainer = DocumentHelper.createElement("div", "sa-tabulator__table-container"); - targetNode.appendChild(header); - targetNode.appendChild(this.tableContainer); + container.appendChild(header); + container.appendChild(this.tableContainer); + container.appendChild(footer); + wrapper.appendChild(container); + targetNode.appendChild(wrapper); var config: any = {}; Object.assign( @@ -155,7 +168,7 @@ export class Tabulator extends Table { paginationMode: "local", paginationSize: this.currentPageSize, movableColumns: true, - // maxHeight: "100%", + maxHeight: "50vw", columns, rowFormatter: this.rowFormatter, paginationElement: paginationElement, @@ -215,18 +228,17 @@ export class Tabulator extends Table { this.tabulatorTables.on("columnResized", this.columnResizedCallback); this.tabulatorTables.on("columnMoved", this.columnMovedCallback); - const extensionsContainer = DocumentHelper.createElement( - "div", - "sa-table__header-extensions" - ); + const extensionsContainer = DocumentHelper.createElement("div", "sa-table__header-extensions"); + this.extensions.render(extensionsContainer, "header"); + header.appendChild(extensionsContainer); header.appendChild(this.createDownloadsBar()); - this.extensions.render(header, "header"); - // header.appendChild(extensionsContainer); - header.appendChild(paginationElement); + this.extensions.render(footer, "footer"); + footer.appendChild(paginationElement); this.renderResult = targetNode; } private createDownloadsBar(): HTMLElement { + /* var createDownloadButton = (type: DownloadType, caption: string): HTMLElement => { const btn = DocumentHelper.createElement( "button", @@ -255,6 +267,24 @@ export class Tabulator extends Table { ); }); return container; + */ + + const values = this._options.downloadButtons.map(val => { return { value: val, text: localization.getString(`${val}DownloadCaption`) }; }); + const exportAsAction = DocumentHelper.createActionDropdown( + values, + (option: any) => false, + (e: any) => { + if(!!e) { + this.download(e); + } + return true; + }, + localization.getString("exportAs"), + undefined, + false + ); + exportAsAction.className += " sa-tabulator__downloads-bar sa-button-brand-secondary"; + return exportAsAction; } public destroy = () => { @@ -264,7 +294,8 @@ export class Tabulator extends Table { private columnMovedCallback = (column: any, columns: any[]) => { var from = this._columns.indexOf(this.getColumnByName(column.getField())); - var to = columns.indexOf(column) - 1; + const rowExtensions = TableExtensions.getExtensions("row").filter(e => e.visibleIndex >= 0); + var to = columns.indexOf(column) - rowExtensions.length; this.moveColumn(from, to); this.disableColumnReorder(); }; @@ -316,14 +347,18 @@ export class Tabulator extends Table { onRendered: any, columnName: any ): HTMLElement { - var container = DocumentHelper.createElement("div"); - var title = DocumentHelper.createElement("span", "", { + var container = DocumentHelper.createElement("div", "sa-tabulator-column-header"); + var title = DocumentHelper.createElement("span", "sa-tabulator-column-title-text", { innerText: cell.getValue(), }); - var actions = this.getHeaderActions(columnName); - container.appendChild(actions); + const actionContainer = this.getHeaderActions(columnName); + const containerFilter = DocumentHelper.createElement("div", "sa-table__filter-container"); + this.extensions.render(containerFilter, "columnfilter", { columnName: columnName }); + + container.appendChild(actionContainer); container.appendChild(title); - ["mousemove", "mousedown"].forEach(eventName => actions.addEventListener(eventName, (event) => { + container.appendChild(containerFilter); + ["mousemove", "mousedown"].forEach(eventName => actionContainer.addEventListener(eventName, (event) => { if (!this.isColumnReorderEnabled) { event.stopPropagation(); } @@ -332,10 +367,7 @@ export class Tabulator extends Table { } private getHeaderActions(columnName: string): HTMLElement { - const container = DocumentHelper.createElement( - "div", - "sa-table__action-container" - ); + const container = DocumentHelper.createElement("div", "sa-table__action-container"); this.extensions.render(container, "column", { columnName: columnName }); return container; } @@ -372,20 +404,22 @@ export class Tabulator extends Table { }, }; }); - // const rowExtensions = TableExtensions.getExtensions("row").filter(e => e.visibleIndex >= 0); + const rowExtensions = TableExtensions.getExtensions("row").filter(e => e.visibleIndex >= 0); // const detailsExtension = TableExtensions.getExtensions("details").filter(e => e.visibleIndex >= 0); // const hasRowColumns = this.columns.some(c => c.location === QuestionLocation.Row); // if(rowExtensions.length > 1 || detailsExtension.length > 0 // || rowExtensions.length == 1 && (rowExtensions[0].name == "details" && hasRowColumns || rowExtensions[0].name != "details")) { - columns.unshift({ - download: false, - resizable: false, - headerSort: false, - minWidth: this._options.actionsColumnWidth, - width: this._options.actionsColumnWidth, - tooltip: (_: MouseEvent, cell: any) => { - return localization.getString("actionsColumn"); - } + rowExtensions.forEach(ext => { + columns.unshift({ + download: false, + resizable: false, + headerSort: false, + minWidth: this._options.actionsColumnWidth, + width: this._options.actionsColumnWidth, + tooltip: (_: MouseEvent, cell: any) => { + return undefined; + } + }); }); // } @@ -502,6 +536,22 @@ export class Tabulator extends Table { dataItem["surveyOriginalData"] = item; return dataItem; } + + get theme() : DashboardTheme { + return this._theme; + } + set theme(theme: DashboardTheme) { + this._theme = theme; + this._appliedTheme = undefined; + } + + public applyTheme(theme: IDashboardTheme): void { + this.theme.setTheme(theme); + this._appliedTheme = this.theme; + if(this.renderResult) { + this._appliedTheme.applyThemeToElement(this.renderResult); + } + } } export class TabulatorRow extends TableRow { @@ -530,6 +580,18 @@ export class TabulatorRow extends TableRow { return null; } + public render() { + let rowExtensions = TableExtensions.getExtensions("row").filter(e => e.visibleIndex >= 0); + rowExtensions = this.extensions.sortExtensions(rowExtensions); + rowExtensions.forEach((rowExt, index) => { + const cellAction = this.innerRow.getCells()[index].getElement(); + cellAction.innerHTML = ""; + this.extensions.renderExtension(rowExt, cellAction, { row: this }); + cellAction.classList.add("sa-tabulator-cell__action"); + cellAction.classList.add("sa-tabulator-cell__action-" + rowExt.name.toLowerCase()); + }); + } + public remove(): void { this.innerRow.delete(); super.remove(); diff --git a/src/text.scss b/src/text.scss index 495b03a3e..8960ea57d 100644 --- a/src/text.scss +++ b/src/text.scss @@ -14,16 +14,21 @@ color: $text-color; border-width: 1px; border-collapse: collapse; - background-color: $background-color; +} + +.sa-text-table tr:first-child { + border-top: var(--dsb-table-cell-border-width, 1px) dashed var(--dsb-table-cell-border-color, #DCDCDC); } .sa-text-table__cell { - border-width: 1px; - padding: 8px; - border-style: solid; - border-color: $border-color; - background-color: $background-color; - min-height: $form-element-height; + color: var(--dsb-table-cell-text-color, rgba(0, 0, 0, 0.90)); + font-family: $font-family; + font-size: var(--ctr-font-default-size, 16px); + font-style: normal; + font-weight: 400; + line-height: var(--ctr-font-default-line-height, 24px); + padding: var(--dsb-table-cell-padding-top, 8px) var(--dsb-table-cell-padding-right-no-border, 0px) var(--dsb-table-cell-padding-bottom, 8px) var(--dsb-table-cell-padding-left-no-border, 0px); + border-bottom: var(--dsb-table-cell-border-width, 1px) dashed var(--dsb-table-cell-border-color, #DCDCDC); } .sa-text-table__cell--number { @@ -31,5 +36,12 @@ } th.sa-text-table__cell { + color: var(--dsb-table-header-text-color, rgba(0, 0, 0, 0.90)); + + /* ctr/Default Bold */ + font-family: $font-family; + font-size: var(--ctr-font-default-size, 16px); + font-style: normal; font-weight: 600; + line-height: var(--ctr-font-default-line-height, 24px); /* 150% */ } diff --git a/src/text.ts b/src/text.ts index b349abc38..d095f68bb 100644 --- a/src/text.ts +++ b/src/text.ts @@ -1,5 +1,5 @@ import { Question, QuestionMultipleTextModel } from "survey-core"; -import { VisualizerBase } from "./visualizerBase"; +import { ICalculationResult, VisualizerBase } from "./visualizerBase"; import { VisualizationManager } from "./visualizationManager"; import { localization } from "./localizationManager"; import { DocumentHelper } from "./utils"; @@ -10,12 +10,12 @@ export class TextTableAdapter { constructor(private model: Text) {} public async create(container: HTMLElement): Promise { - const { columnCount, data } = (await this.model.getCalculatedValues()) as any; - const emptyTextNode = DocumentHelper.createElement("p", "", { - innerText: localization.getString("noResults"), - }); + const answersData = await this.model.getAnswersData(); - if (data.length === 0) { + if (answersData.datasets.length === 0 || answersData.datasets[0].length === 0) { + var emptyTextNode = DocumentHelper.createElement("p", "", { + innerText: localization.getString("noResults"), + }); container.appendChild(emptyTextNode); return; } @@ -27,7 +27,7 @@ export class TextTableAdapter { tableNode.style.backgroundColor = this.model.backgroundColor; container.appendChild(tableNode); - if(this.model.columns) { + if(this.model.columns && this.model.columns.length > 0) { var row = DocumentHelper.createElement("tr"); this.model.columns.forEach(column => { var td = DocumentHelper.createElement("th", "sa-text-table__cell", { @@ -38,9 +38,9 @@ export class TextTableAdapter { tableNode.appendChild(row); } - data.forEach((rowData) => { + answersData.datasets.forEach((rowData) => { var row = DocumentHelper.createElement("tr"); - for (var i = 0; i < columnCount; i++) { + for (var i = 0; i < answersData.seriesLabels.length; i++) { const column = this.model.columns[i]; var td = DocumentHelper.createElement("td", "sa-text-table__cell" + (column?.type == "number" ? " sa-text-table__cell--number" : ""), { textContent: rowData[i], @@ -66,15 +66,15 @@ export class Text extends VisualizerBase { question: Question, data: Array<{ [index: string]: any }>, options?: Object, - name?: string + type?: string ) { - super(question, data, options, name || "text"); + super(question, data, options, type || "text"); this._textTableAdapter = new TextTableAdapter(this); } public get columns(): Array<{ name: string, title: string, type: string }> { const columns = []; - if(this.question.getType() == "multipletext") { + if(this.dataType == "multipletext") { (this.question as QuestionMultipleTextModel).items.forEach(item => { columns.push({ name: item.name, title: item.title, type: item.inputType }); }); @@ -82,7 +82,11 @@ export class Text extends VisualizerBase { return columns; } - protected getCalculatedValuesCore(): any { + public getValues(): Array { + return []; + } + + protected getCalculatedValuesCore(): ICalculationResult { let result: Array> = []; let columnCount = 0; @@ -108,7 +112,9 @@ export class Text extends VisualizerBase { } }); - return { columnCount: columnCount, data: result }; + const series = []; + series.length = columnCount; + return { data: result as any, values: [], series }; } protected destroyContent(container: HTMLElement) { diff --git a/src/theme.ts b/src/theme.ts new file mode 100644 index 000000000..7bf1c3166 --- /dev/null +++ b/src/theme.ts @@ -0,0 +1,251 @@ +import Default from "./sjs-design-tokens/default-light"; +import { DocumentHelper } from "./utils"; + +export interface IDashboardTheme { + cssVariables?: { [index: string]: string | any }; +} + +export interface FontSettings { + family: string; + color: string; + size: string; + weight: number; +} + +function getRGBaColor(colorValue: string): string { + if (!colorValue) return null; + if (colorValue.indexOf("rgba") === 0) { + return colorValue; + } + + const canvasElement = document.createElement("canvas") as HTMLCanvasElement; + if (!canvasElement) return null; + var ctx = canvasElement.getContext("2d"); + ctx.fillStyle = colorValue; + + if (ctx.fillStyle == "#000000") { + ctx.fillStyle = colorValue; + } + const newStr = ctx.fillStyle; + + const regex = /color\s*\(\s*srgb\s+([\d.]+)\s+([\d.]+)\s+([\d.]+)\s*(?:\/\s*([\d.]+))?\s*\)/i; + const match = newStr.match(regex); + + if (!match) { + if (newStr.indexOf("rgba") === 0) { + return newStr; + } + var result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(newStr); + return result ? `rgba(${parseInt(result[1], 16)}, ${parseInt(result[2], 16)}, ${parseInt(result[3], 16)}, 1)` : null; + } + + const r = parseFloat(match[1]); + const g = parseFloat(match[2]); + const b = parseFloat(match[3]); + const alpha = match[4] ? parseFloat(match[4]) : 1; + + const r255 = Math.round(r * 255); + const g255 = Math.round(g * 255); + const b255 = Math.round(b * 255); + + return `rgba(${r255}, ${g255}, ${b255}, ${alpha})`; +} + +export class DashboardTheme implements IDashboardTheme { + static barGap = 0.05; + static fontFamily = "'Open Sans', 'Segoe UI', SegoeUI, Arial, sans-serif"; + private _cssStyleDeclaration; + private _computedValuesCache: { [key: string]: string } = {}; + + private getCssVariableValue(propertyName: string, checkIsNumber = false) { + let value = undefined; + if (this._computedValuesCache[propertyName]) { + value = this._computedValuesCache[propertyName]; + } else if(!!this._cssStyleDeclaration) { + value = this._cssStyleDeclaration.getPropertyValue(propertyName); + } + + if(checkIsNumber) { + const numValue = parseFloat(value); + if(isNaN(numValue)) { + return undefined; + } + } + return value; + } + + private initComputedValuesCache(rootElement: HTMLElement) { + const tempElement = document.createElement("div"); + tempElement.style.position = "absolute"; + tempElement.style.visibility = "hidden"; + tempElement.style.top = "0"; + tempElement.style.left = "0"; + rootElement.appendChild(tempElement); + + Object.keys(this.cssVariables).forEach(key => { + let value; + if (key.indexOf("palette") !== -1 || key.indexOf("color") !== -1) { + tempElement.style.setProperty("color", `var(${key})`); + const computedStyle = getComputedStyle(tempElement); + value = computedStyle.getPropertyValue("color"); + value = getRGBaColor(value); + } else if(key.indexOf("font-family") === -1 && key.indexOf("opacity") === -1 && key.indexOf("scale") === -1) { + tempElement.style.setProperty("width", `var(${key})`); + const computedStyle = getComputedStyle(tempElement); + value = computedStyle.getPropertyValue("width"); + } else { + value = this._cssStyleDeclaration.getPropertyValue(key); + } + this._computedValuesCache[key] = value; + }); + rootElement.removeChild(tempElement); + } + + constructor(private theme: IDashboardTheme = Default) { + this.setTheme(theme); + } + + public applyThemeToElement(element: HTMLElement): void { + if(!element) return; + + if(!this.theme) { + element.removeAttribute("style"); + this._cssStyleDeclaration = undefined; + return; + } + + DocumentHelper.setStyles(element, this.cssVariables); + if (!!getComputedStyle) { + this._cssStyleDeclaration = getComputedStyle(element); + } + this.initComputedValuesCache(element); + } + + public setTheme(theme: IDashboardTheme): void { + this.theme = theme; + this._computedValuesCache = {}; + // const calculater = DocumentHelper.createElement("div"); + // document.body.appendChild(calculater); + // this.applyThemeToElement(calculater); + // calculater.remove(); + } + + public get cssVariables(): { [index: string]: string | any } { + return this.theme.cssVariables; + } + + public get defaultFontFamily() { + return this.getCssVariableValue("--sjs2-typography-font-family-default") || DashboardTheme.fontFamily; + } + + public get backgroundColor(): string { + return this.getCssVariableValue("--sjs2-color-bg-basic-primary"); + } + + public get axisGridColor(): string { + return this.getCssVariableValue("--sjs2-color-data-grid-border-line"); + } + + public get axisBorderColor(): string { + return this.getCssVariableValue("--sjs2-color-data-grid-border-axis"); + } + + public get modebarActiveColor(): string { + return this.getCssVariableValue("--sjs2-color-fg-brand-primary"); + } + + public get modebarColor(): string { + return this.getCssVariableValue("--sjs2-color-bg-brand-secondary-dim"); + } + + public isFontLoaded(fontFaceName: string) { + return !fontFaceName || !document || !document.fonts || document.fonts.check("1em " + fontFaceName); + } + + public isAxisLabelFontLoaded() { + return this.isFontLoaded(this.axisLabelFont?.family); + } + + public get axisLabelFont(): FontSettings { + return { + color: this.getCssVariableValue("--sjs2-color-data-grid-fg-label"), + family: this.defaultFontFamily, + size: this.getCssVariableValue("--sjs2-typography-font-size-small", true), + weight: 400 + }; + } + + public get insideLabelFont(): FontSettings { + return { + color: this.getCssVariableValue("--sjs2-color-data-chart-fg-on-color-1"), + family: this.defaultFontFamily, + size: this.getCssVariableValue("--sjs2-typography-font-size-small", true), + weight: 600 + }; + } + + public get legendLabelFont(): FontSettings { + return { + color: this.getCssVariableValue("--sjs2-color-fg-basic-primary"), + family: this.defaultFontFamily, + size: this.getCssVariableValue("--sjs2-typography-font-size-small", true), + weight: 400 + }; + } + + public get legendSetting() { + return { + borderWidth: this.getCssVariableValue("--sjs2-border-width-default"), + borderColor: this.getCssVariableValue("--sjs2-color-border-basic-secondary"), + borderRadius: this.getCssVariableValue("--sjs2-radius-x250"), + }; + } + + public get tooltipBackground() { + return this.getCssVariableValue("--sjs2-color-bg-neutral-primary"); + } + + public get tooltipFont(): FontSettings { + return { + color: this.getCssVariableValue("--sjs2-color-fg-neutral-primary"), + family: this.defaultFontFamily, + size: this.getCssVariableValue("--sjs2-typography-font-size-small", true), + weight: 600 + }; + } + + public get gaugeBackground() { + return this.getCssVariableValue("--sjs2-color-bg-basic-secondary"); + } + public get gaugeBarColor() { + return this.getCssVariableValue("--sjs2-color-fg-brand-primary"); + } + + public get gaugeValueFont(): FontSettings { + return { + color: this.getCssVariableValue("--sjs2-color-fg-basic-primary"), + family: this.defaultFontFamily, + size: this.getCssVariableValue("--sjs2-typography-font-size-large", true), + weight: 600 + }; + } + + public get gaugeTickFont(): FontSettings { + return { + color: this.getCssVariableValue("--sjs2-color-data-grid-fg-label"), + family: this.defaultFontFamily, + size: this.getCssVariableValue("--sjs2-typography-font-size-small", true), + weight: 400 + }; + } + + public get radarLabelFont(): FontSettings { + return { + color: this.getCssVariableValue("--sjs2-color-fg-basic-primary"), + family: this.defaultFontFamily, + size: this.getCssVariableValue("--sjs2-typography-font-size-small", true), + weight: 400 + }; + } + +} \ No newline at end of file diff --git a/src/utils/dateRangeWidget.scss b/src/utils/dateRangeWidget.scss new file mode 100644 index 000000000..332b6a1e7 --- /dev/null +++ b/src/utils/dateRangeWidget.scss @@ -0,0 +1,251 @@ +.sa-date-range { + display: flex; + align-items: center; + align-self: stretch; + align-content: center; + gap: 16px var(--sjs2-spacing-x200, 16px); + flex-wrap: wrap; +} + +.sa-date-range-container { + display: flex; + flex-direction: column; + align-items: flex-start; + align-self: stretch; + max-width: min-content; +} + +.sa-date-range_editors { + display: flex; + align-items: center; + gap: var(--sjs2-spacing-x150, 12px); +} + +.sa-date-range_editor { + display: flex; +} + +.sa-date-range_editor-formbox { + display: flex; + padding: var(--sjs2-layout-control-formbox-small-vertical, 4px) var(--sjs2-layout-control-formbox-small-horizontal, 4px); + align-items: flex-start; + gap: var(--sjs2-layout-control-formbox-small-gap, 4px); + align-self: stretch; + border-radius: var(--sjs2-radius-semantic-form, 8px); + background: var(--sjs2-color-control-formbox-default-bg, rgba(28, 27, 32, 0.05)); + outline: var(--sjs2-border-offset-x-form-default, 0) var(--sjs2-border-offset-y-form-default, 0) var(--sjs2-border-blur-form-default, 0) var(--sjs2-border-spread-form-default, 1px) var(--sjs2-color-control-formbox-default-border, #D4D4D4) inset; + + &:focus-visible { + background: var(--sjs2-color-control-formbox-focused-bg, #F5F5F5); + box-shadow: var(--sjs2-border-offset-x-form-focused, 0) var(--sjs2-border-offset-y-form-focused, 0) var(--sjs2-border-blur-form-focused, 0) var(--sjs2-border-spread-form-focused, 2px) var(--sjs2-color-control-formbox-focused-border, #19B394) inset; + } +} + +.sa-range-error { + display: none; + align-items: flex-start; + align-self: stretch; +} + +.sa-range-error_panel { + display: flex; + padding: var(--sjs2-layout-control-message-small-vertical, 8px) var(--sjs2-layout-control-message-small-horizontal, 12px); + align-items: flex-start; + gap: var(--sjs2-layout-control-message-small-gap, 8px); + flex: 1 0 0; + align-self: stretch; + border-radius: var(--sjs2-radius-semantic-form, 8px); + background: var(--sjs2-color-control-message-error-bg, rgba(229, 10, 62, 0.10)); +} +.sa-range-error_text { + flex: 1 0 0; + color: var(--sjs2-color-control-message-error-text, #1C1B20); + + /* sjs2/typography/default */ + font-family: var(--sjs2-typography-font-family-default, "Open Sans"); + font-size: var(--sjs2-typography-font-size-default, 16px); + font-style: normal; + font-weight: 400; + line-height: var(--sjs2-typography-line-height-default, 24px); /* 150% */ +} + +.sa-date-range--invalid .sa-range-error { + display: flex; + padding-top: var(--sjs2-layout-control-message-small-spacer, 8px); + flex-direction: column; + align-items: flex-start; + align-self: stretch; +} + +.sa-date-range_editor--invalid .sa-date-range_editor-formbox { + background: var(--sjs2-color-control-formbox-invalid-bg, #F5F5F5); + box-shadow: var(--sjs2-border-offset-x-form-invalid, 0) var(--sjs2-border-offset-y-form-invalid, 0) var(--sjs2-border-blur-form-invalid, 0) var(--sjs2-border-spread-form-invalid, 2px) var(--sjs2-color-control-formbox-invalid-border, #E50A3E) inset; +} + +.sa-date-range_editor-content { + display: flex; + padding: var(--sjs2-layout-control-input-small-content-vertical, 4px) var(--sjs2-layout-control-input-small-content-horizontal, 8px); + align-items: flex-start; + flex: 1 0 0; +} + +.sa-date-range_editor-input { + display: -webkit-box; + -webkit-box-orient: vertical; + -webkit-line-clamp: 1; + flex: 1 0 0; + overflow: hidden; + color: var(--sjs2-color-control-input-default-value, #1C1B20); + text-overflow: ellipsis; + background: transparent; + border: none; + outline: none; + + /* sjs2/typography/default */ + font-family: var(--sjs2-typography-font-family-default, "Open Sans"); + font-size: var(--sjs2-typography-font-size-default, 16px); + font-style: normal; + font-weight: 400; + line-height: var(--sjs2-typography-line-height-default, 24px); /* 150% */ +} + +.sa-vertical-divider { + display: flex; + width: 1px; + height: 40px; + flex-direction: column; + align-items: flex-start; + align-self: stretch; + + .sa-line { + display: flex; + flex-direction: column; + align-items: flex-start; + flex: 1 0 0; + align-self: stretch; + background: var(--sjs2-color-border-basic-secondary, #D4D4D4); + } +} +@media screen and (max-width: 1000px) { + .sa-vertical-divider { + display: none; + } +} + +@media screen and (max-width: 1200px) { + .sa-vertical-divider2 { + display: none; + } +} + +.sa-horizontal-divider { + display: flex; + flex-direction: column; + align-items: flex-start; + align-self: stretch; + + .sa-line { + display: flex; + flex-direction: column; + align-items: flex-start; + align-self: stretch; + + height: var(--sjs2-border-width-static-x100, 1px); + background: var(--sjs2-color-border-basic-secondary, #D4D4D4); + } +} + + +.sa-date-range_chips { + display: flex; + align-items: flex-start; + align-content: flex-start; + gap: 8px var(--sjs2-spacing-x100, 8px); + align-self: stretch; + flex-wrap: wrap; +} + +.sa-date-range_chip { + display: flex; + min-width: var(--sjs2-size-semantic-x-small, 32px); + align-items: center; + cursor: pointer; +} + +.sa-date-range_chip-box { + display: flex; + min-width: var(--sjs2-size-semantic-x-small, 32px); + padding: var(--sjs2-layout-control-action-small-box-vertical, 8px) var(--sjs2-layout-control-action-small-box-horizontal, 8px); + justify-content: center; + align-items: center; + gap: var(--sjs2-layout-control-action-small-box-gap, 0); + border-radius: var(--sjs2-radius-control-action, 8px); + outline: 1px solid var(--sjs2-color-border-basic-secondary, #D4D4D4); + background: var(--sjs2-color-bg-basic-primary, #FFF); + + &:hover { + border-radius: var(--sjs2-radius-control-action, 8px); + outline: 1px solid var(--sjs2-color-border-basic-secondary, #D4D4D4); + background: var(--sjs2-color-bg-basic-primary-dim, rgba(28, 27, 32, 0.05)); + } +} + +.sa-date-range_chip--active .sa-date-range_chip-box { + border-radius: var(--sjs2-radius-control-action, 8px); + outline: var(--sjs2-border-width-x200, 2px) solid var(--sjs2-color-border-brand-primary, #19B394); + background: var(--sjs2-color-bg-basic-primary, #FFF); + + &:hover { + border-radius: var(--sjs2-radius-control-action, 8px); + outline: var(--sjs2-border-width-x200, 2px) solid var(--sjs2-color-border-brand-primary, #19B394); + background: var(--sjs2-color-bg-brand-tertiary-dim, rgba(25, 179, 148, 0.10)); + } +} + +.sa-date-range_chip-label { + color: var(--sjs2-color-fg-basic-primary, #1C1B20); + text-align: center; + display: flex; + padding: var(--sjs2-layout-control-action-small-label-vertical, 0) var(--sjs2-layout-control-action-small-label-horizontal, 6px); + justify-content: center; + align-items: center; + + /* sjs2/typography/default */ + font-family: var(--sjs2-typography-font-family-default, "Open Sans"); + font-size: var(--sjs2-typography-font-size-default, 16px); + font-style: normal; + font-weight: 400; + line-height: var(--sjs2-typography-line-height-default, 24px); /* 150% */ +} + +.sa-date-range_chip--active .sa-date-range_chip-label { + color: var(--sjs2-color-fg-basic-primary, #1C1B20); + text-align: center; + + /* sjs2/typography/default-strong */ + font-family: var(--sjs2-typography-font-family-default, "Open Sans"); + font-size: var(--sjs2-typography-font-size-default, 16px); + font-style: normal; + font-weight: 600; + line-height: var(--sjs2-typography-line-height-default, 24px); /* 150% */ +} + +.sa-count { + display: flex; + padding: var(--sjs2-spacing-x100, 8px) 0; + justify-content: center; + align-items: center; + align-self: self-start; + gap: 10px; +} + +.sa-count_text { + color: var(--sjs2-color-fg-basic-primary, #1C1B20); + + /* sjs2/typography/default-strong */ + font-family: var(--sjs2-typography-font-family-default, "Open Sans"); + font-size: var(--sjs2-typography-font-size-default, 16px); + font-style: normal; + font-weight: 600; + line-height: var(--sjs2-typography-line-height-default, 24px); /* 150% */ +} diff --git a/src/utils/dateRangeWidget.ts b/src/utils/dateRangeWidget.ts new file mode 100644 index 000000000..dfeb92fc7 --- /dev/null +++ b/src/utils/dateRangeWidget.ts @@ -0,0 +1,266 @@ +import { DocumentHelper } from "."; +import { localization } from "../localizationManager"; +import "./dateRangeWidget.scss"; + +export interface IDateRange { + start?: number; + end?: number; +} +export interface IDateRangeWidgetOptions { + setDateRange: (dateRange: IDateRange) => void; + onBeforeRender: (options: IDateRangeOptions) => void; +} +export interface IDateRangeOptions { + showTotalCount?: boolean; + initialRange?: IDateRange; + chipsConfig: {[key: string]: any}; +} + +export class DateRangeWidget { + static invalidRangeClassName = "sa-date-range--invalid"; + static invalidRangeEditorClassName = "sa-date-range_editor--invalid"; + + private currentDateRange: IDateRange + + private dateRangeContainer: HTMLElement; + private startDateEditor: HTMLElement; + private endDateEditor: HTMLElement; + private startDateInput: HTMLInputElement; + private endDateInput: HTMLInputElement; + private countLabel: HTMLElement; + private rangeErrorMessage: HTMLElement; + private chipsContainer: HTMLElement; + + private elementRemoveClassName(element: Element, className: string) { + if (element.classList.contains(className)) { + element.classList.remove(className); + } + } + private setDateRange(): void { + this.updateMinMaxAttributes(); + this.config.setDateRange({ ...this.currentDateRange }); + } + private dateEditorChangeValue(): void { + this.setDateRange(); + this.resetChipsState(this.chipsContainer); + } + private updateMinMaxAttributes(): void { + if (this.currentDateRange.end !== undefined) { + this.startDateInput.max = new Date(this.currentDateRange.end).toISOString().split("T")[0]; + } else { + this.startDateInput.removeAttribute("max"); + } + + if (this.currentDateRange.start !== undefined) { + this.endDateInput.min = new Date(this.currentDateRange.start).toISOString().split("T")[0]; + } else { + this.endDateInput.removeAttribute("min"); + } + } + private setDateIntoInput(dateValue: number, input: HTMLInputElement): void { + if (!!dateValue) { + const date = new Date(dateValue); + input.value = date.toISOString().split("T")[0]; + } else { + input.value = ""; + } + } + private createErrorMessage(textContent?: string) { + const messageDiv = DocumentHelper.createElement("div", "sa-range-error"); + const panelDiv = DocumentHelper.createElement("div", "sa-range-error_panel"); + const errorMessageDiv = DocumentHelper.createElement("div", "sa-range-error_text"); + errorMessageDiv.textContent = textContent; + this.rangeErrorMessage = errorMessageDiv; + + messageDiv.appendChild(panelDiv); + panelDiv.appendChild(errorMessageDiv); + + return messageDiv; + } + private createDateEditor(dateValue: number, changeHandler: (input: HTMLInputElement) => void): HTMLElement { + const dateEditor = DocumentHelper.createElement("div", "sa-date-range_editor"); + const formBox = DocumentHelper.createElement("div", "sa-date-range_editor-formbox"); + const content = DocumentHelper.createElement("div", "sa-date-range_editor-content"); + const input = DocumentHelper.createElement("input", "sa-date-range_editor-input", + { + type: "date" + } + ); + this.setDateIntoInput(dateValue, input); + + input.onchange = (e) => { + if (!!changeHandler) { + changeHandler(input); + } + }; + + content.appendChild(input); + formBox.appendChild(content); + dateEditor.appendChild(formBox); + + return dateEditor; + } + private createDivider(): HTMLElement { + const divider = DocumentHelper.createElement("div", "sa-vertical-divider"); + const line = DocumentHelper.createElement("div", "sa-line"); + divider.appendChild(line); + return divider; + } + private createChip(text: string, isActive: boolean, container: HTMLElement, clickHandler: () => {}): HTMLElement { + const activaStateClass = "sa-date-range_chip--active"; + const chip = DocumentHelper.createElement("div", "sa-date-range_chip"); + if (isActive) { + chip.classList.add(activaStateClass); + } + + const self = this; + chip.addEventListener("click", function() { + self.resetChipsState(container); + chip.classList.add(activaStateClass); + clickHandler(); + }); + + const box = DocumentHelper.createElement("div", "sa-date-range_chip-box"); + const labelContainer = DocumentHelper.createElement("div", "sa-date-range_chip-label"); + const labelText = DocumentHelper.createElement("div", "sa-date-range_chip-text"); + labelText.textContent = text; + + labelContainer.appendChild(labelText); + box.appendChild(labelContainer); + chip.appendChild(box); + container.appendChild(chip); + + return chip; + } + private resetChipsState(container: HTMLElement): void { + const chips = container.querySelectorAll(".sa-date-range_chip"); + chips.forEach(chip => { + this.elementRemoveClassName(chip, "sa-date-range_chip--active"); + }); + } + private setFilter(start, end): void { + this.currentDateRange.start = !!start ? (new Date(start)).getTime() : undefined; + this.currentDateRange.end = !!end ? (new Date(end)).getTime() : undefined; + this.setDateRange(); + this.setDateIntoInput(start, this.startDateInput); + this.setDateIntoInput(end, this.endDateInput); + this.elementRemoveClassName(this.startDateEditor, DateRangeWidget.invalidRangeEditorClassName); + this.elementRemoveClassName(this.endDateEditor, DateRangeWidget.invalidRangeEditorClassName); + } + private getDefaultChipsConfig(): {[key: string]: any} { + return { + allTime: () => { + this.setFilter(undefined, undefined); + }, + lastYear: () => { + const end = new Date(); + const start = new Date(); + start.setFullYear(end.getFullYear() - 1); + this.setFilter(start, end); + }, + lastQuarter: () => { + const end = new Date(); + const start = new Date(); + start.setMonth(end.getMonth() - 3); + this.setFilter(start, end); + }, + lastMonth: () => { + const end = new Date(); + const start = new Date(); + start.setMonth(end.getMonth() - 1); + this.setFilter(start, end); + }, + lastWeek: () => { + const end = new Date(); + const start = new Date(); + start.setDate(end.getDate() - 7); + this.setFilter(start, end); + }, + }; + } + + constructor(private config: IDateRangeWidgetOptions) { + } + + public render(): HTMLElement { + const options = { chipsConfig: this.getDefaultChipsConfig() }; + this.config.onBeforeRender(options); + + this.currentDateRange = !!options.initialRange ? options.initialRange : {}; + const rangeElement = DocumentHelper.createElement("div", "sa-date-range"); + const rangeContainer = DocumentHelper.createElement("div", "sa-date-range-container"); + const dateRangeEditors = DocumentHelper.createElement("div", "sa-date-range_editors"); + this.dateRangeContainer = rangeContainer; + rangeContainer.appendChild(dateRangeEditors); + rangeElement.appendChild(rangeContainer); + + this.startDateEditor = this.createDateEditor(this.currentDateRange.start, (input: HTMLInputElement) => { + if (input.checkValidity()) { + this.currentDateRange.start = (new Date(input.value)).getTime(); + this.dateEditorChangeValue(); + this.elementRemoveClassName(this.startDateEditor, DateRangeWidget.invalidRangeEditorClassName); + this.elementRemoveClassName(this.dateRangeContainer, DateRangeWidget.invalidRangeClassName); + } else { + this.startDateEditor.classList.add(DateRangeWidget.invalidRangeEditorClassName); + this.dateRangeContainer.classList.add(DateRangeWidget.invalidRangeClassName); + this.rangeErrorMessage.textContent = input.validationMessage; + } + }); + dateRangeEditors.appendChild(this.startDateEditor); + this.startDateInput = this.startDateEditor.querySelector("input"); + + const separator = DocumentHelper.createElement("div", ""); + separator.textContent = "-"; + dateRangeEditors.appendChild(separator); + + this.endDateEditor = this.createDateEditor(this.currentDateRange.end, (input: HTMLInputElement) => { + if (input.checkValidity()) { + this.currentDateRange.end = (new Date(input.value)).getTime(); + this.dateEditorChangeValue(); + this.elementRemoveClassName(this.endDateEditor, DateRangeWidget.invalidRangeEditorClassName); + this.elementRemoveClassName(this.dateRangeContainer, DateRangeWidget.invalidRangeClassName); + } else { + this.endDateEditor.classList.add(DateRangeWidget.invalidRangeEditorClassName); + this.dateRangeContainer.classList.add(DateRangeWidget.invalidRangeClassName); + this.rangeErrorMessage.textContent = input.validationMessage; + } + }); + dateRangeEditors.appendChild(this.endDateEditor); + rangeContainer.appendChild(this.createErrorMessage()); + + this.endDateInput = this.endDateEditor.querySelector("input"); + + if (!!options.chipsConfig && Object.keys(options.chipsConfig).length > 0) { + const isActive = (index) => { + return !options.initialRange && index === 0; + }; + this.chipsContainer = DocumentHelper.createElement("div", "sa-date-range_chips"); + Object.keys(options.chipsConfig).forEach((chipLabel, index) => { + this.createChip(chipLabel, isActive(index), this.chipsContainer, options.chipsConfig[chipLabel]); + }); + + rangeElement.appendChild(this.createDivider()); + rangeElement.appendChild(this.chipsContainer); + } + + if (options.showTotalCount !== false) { + const divider2 = this.createDivider(); + divider2.classList.add("sa-vertical-divider2"); + rangeElement.appendChild(divider2); + const countContainer = DocumentHelper.createElement("div", "sa-count"); + this.countLabel = DocumentHelper.createElement("div", "sa-count_text"); + countContainer.appendChild(this.countLabel); + rangeElement.appendChild(countContainer); + } + + this.setFilter(this.currentDateRange.start, this.currentDateRange.end); + + return rangeElement; + } + + public updateAnswersCount(answersCount: number): void { + if (!!this.countLabel && answersCount !== undefined) { + this.countLabel.textContent = answersCount + " " + localization.getString("answersText"); + } + } +} diff --git a/src/utils/index.ts b/src/utils/index.ts index 8e86f9684..9695e92c6 100755 --- a/src/utils/index.ts +++ b/src/utils/index.ts @@ -45,16 +45,639 @@ export class DocumentHelper { return selectWrapper; } + /** + * Creates a custom dropdown element with icon support + * @param {Array<{value: string, text: string, icon?: string}>} options - Array of options + * @param {(option: {value: string, text: string, icon?: string}) => boolean} isSelected - Function to check if option is selected + * @param {(value: string) => void} handler - Selection handler + * @param {string} placeholder - Placeholder text + * @param {string} title - Title text + * @returns {HTMLElement} - Created dropdown element + */ + public static createDropdown( + options: Array<{value: string, text: string, title?: string, icon?: string}> | (() => Array<{value: string, text: string, title?: string, icon?: string}>), + isSelected: (option: {value: string, text: string, icon?: string}) => boolean, + handler: (value: string) => void, + placeholder = "Select...", + title?: string | (() => string), + className = "sa-dropdown" + ): HTMLDivElement { + const dropdownOpenedClass = className + "--opened"; + const dropdownElement = document.createElement("div"); + dropdownElement.className = className; + const titleElement = DocumentHelper.createElement("span", className + "__title"); + const dropdownHeader = document.createElement("div"); + dropdownHeader.className = className + "-header"; + dropdownHeader.setAttribute("tabindex", "0"); + dropdownHeader.setAttribute("role", "button"); + dropdownHeader.setAttribute("aria-haspopup", "listbox"); + dropdownHeader.setAttribute("aria-expanded", "false"); + const itemClassSelected = className + "-item--selected"; + + const updateTitle = () => { + const titleText = !!title && (typeof title == "string" ? title : title()); + titleElement.innerText = titleText; + if (!!titleText) { + dropdownElement.insertBefore(titleElement, dropdownContainer); + } else if (titleElement.parentElement === dropdownElement) { + dropdownElement.removeChild(titleElement); + } + }; + + const optionsSource = options || []; + let optionItems = Array.isArray(optionsSource) ? optionsSource : optionsSource(); + let selectedOption = optionItems.find(option => isSelected(option)); + const headerContent = document.createElement("div"); + headerContent.className = className + "-header-content"; + + const updateHeader = () => { + headerContent.innerHTML = ""; + optionItems = Array.isArray(optionsSource) ? optionsSource : optionsSource(); + selectedOption = optionItems.find(option => isSelected(option)); + + if (selectedOption) { + dropdownHeader.setAttribute("aria-label", `Selected: ${selectedOption.text}`); + } else { + dropdownHeader.setAttribute("aria-label", placeholder); + } + + if (selectedOption?.icon) { + const headerIcon = document.createElement("div"); + headerIcon.className = className + "-header-icon"; + headerIcon.innerHTML = selectedOption.icon; + headerContent.appendChild(headerIcon); + } + + const headerText = document.createElement("span"); + headerText.className = selectedOption ? className + "-header-text" : className + "-placeholder"; + headerText.textContent = selectedOption ? selectedOption.text : placeholder; + headerContent.appendChild(headerText); + }; + + // Initial header update + updateHeader(); + dropdownHeader.appendChild(headerContent); + + // Add arrow icon + const arrowElement = document.createElement("div"); + arrowElement.className = className + "-arrow"; + arrowElement.appendChild(DocumentHelper.createSvgElement("chevrondown-24x24")); + dropdownHeader.appendChild(arrowElement); + const dropdownList = document.createElement("ul"); + dropdownList.className = className + "-list"; + dropdownList.setAttribute("role", "listbox"); + const dropdownContainer = document.createElement("div"); + dropdownContainer.className = className + "-container"; + + const updateOptions = () => { + dropdownList.innerHTML = ""; + const optionsSource = options || []; + const optionItems = Array.isArray(optionsSource) ? optionsSource : optionsSource(); + optionItems.forEach(option => { + const dropdownItem = document.createElement("li"); + dropdownItem.className = className + "-item"; + if (option.title) { + dropdownItem.title = option.title; + } + dropdownItem.dataset.value = option.value; + dropdownItem.setAttribute("role", "option"); + dropdownItem.setAttribute("tabindex", "-1"); + dropdownItem.id = `${className}-item-${option.value}`; + + if (option.icon) { + const iconContainer = document.createElement("div"); + iconContainer.className = className + "-icon"; + iconContainer.appendChild(DocumentHelper.createSvgElement(option.icon)); + dropdownItem.appendChild(iconContainer); + } + + const textSpan = document.createElement("span"); + textSpan.textContent = option.text; + dropdownItem.appendChild(textSpan); + + if (isSelected(option)) { + dropdownItem.classList.add(itemClassSelected); + dropdownItem.setAttribute("aria-selected", "true"); + } else { + dropdownItem.setAttribute("aria-selected", "false"); + } + + dropdownItem.addEventListener("click", () => { + selectedOption = option; + handler(option.value); + updateHeader(); + + dropdownHeader.classList.remove(dropdownOpenedClass); + dropdownList.classList.remove(dropdownOpenedClass); + dropdownHeader.setAttribute("aria-expanded", "false"); + + // Remove selection from all items and add to current + dropdownList.querySelectorAll("." + className + "-item").forEach(item => { + item.classList.remove(itemClassSelected); + item.setAttribute("aria-selected", "false"); + }); + dropdownItem.classList.add(itemClassSelected); + dropdownItem.setAttribute("aria-selected", "true"); + }); + + dropdownList.appendChild(dropdownItem); + }); + }; + // Function to close dropdown when clicking outside + const handleClickOutside = (event) => { + if (!dropdownElement.contains(event.target)) { + dropdownHeader.classList.remove(dropdownOpenedClass); + dropdownList.classList.remove(dropdownOpenedClass); + dropdownHeader.setAttribute("aria-expanded", "false"); + currentFocusIndex = -1; + } + }; + + // Add open/close handler + dropdownHeader.addEventListener("click", (e) => { + const isOpened = dropdownHeader.classList.toggle(dropdownOpenedClass); + dropdownList.classList.toggle(dropdownOpenedClass); + dropdownHeader.setAttribute("aria-expanded", isOpened ? "true" : "false"); + + if (!isOpened) { + currentFocusIndex = -1; + } + }); + + let currentFocusIndex = -1; + + const focusItem = (index: number) => { + const items = dropdownList.querySelectorAll("." + className + "-item"); + if (items.length === 0) return; + + items.forEach(item => { + item.classList.remove(className + "-item--focused"); + item.setAttribute("aria-selected", "false"); + }); + + if (index < 0) index = items.length - 1; + if (index >= items.length) index = 0; + + currentFocusIndex = index; + const itemToFocus = items[currentFocusIndex] as HTMLElement; + itemToFocus.classList.add(className + "-item--focused"); + itemToFocus.setAttribute("aria-selected", "true"); + itemToFocus.scrollIntoView({ block: "nearest" }); + }; + + const handleKeyDown = (e: KeyboardEvent) => { + if (!dropdownHeader.classList.contains(dropdownOpenedClass)) { + if (e.key === "Enter" || e.key === " " || e.key === "ArrowDown") { + e.preventDefault(); + dropdownHeader.classList.add(dropdownOpenedClass); + dropdownList.classList.add(dropdownOpenedClass); + dropdownHeader.setAttribute("aria-expanded", "true"); + setTimeout(() => focusItem(0), 0); + } + return; + } + + const items = dropdownList.querySelectorAll("." + className + "-item"); + if (items.length === 0) return; + + switch (e.key) { + case "ArrowDown": + e.preventDefault(); + focusItem(currentFocusIndex + 1); + break; + case "ArrowUp": + e.preventDefault(); + focusItem(currentFocusIndex - 1); + break; + case "Enter": + e.preventDefault(); + if (currentFocusIndex >= 0 && currentFocusIndex < items.length) { + const selectedItem = items[currentFocusIndex] as HTMLElement; + const value = selectedItem.dataset.value; + if (value) { + const option = optionItems.find(opt => opt.value === value); + if (option) { + selectedOption = option; + handler(option.value); + updateHeader(); + + dropdownHeader.classList.remove(dropdownOpenedClass); + dropdownList.classList.remove(dropdownOpenedClass); + dropdownList.querySelectorAll("." + className + "-item").forEach(item => { + item.classList.remove(itemClassSelected); + item.setAttribute("aria-selected", "false"); + }); + selectedItem.classList.add(itemClassSelected); + selectedItem.setAttribute("aria-selected", "true"); + } + } + } + break; + case "Escape": + e.preventDefault(); + dropdownHeader.classList.remove(dropdownOpenedClass); + dropdownList.classList.remove(dropdownOpenedClass); + dropdownHeader.setAttribute("aria-expanded", "false"); + currentFocusIndex = -1; + break; + } + }; + + dropdownHeader.addEventListener("keydown", handleKeyDown); + dropdownList.addEventListener("keydown", handleKeyDown); + + // Add click outside handler + document.addEventListener("click", handleClickOutside); + + // Save handler reference for later removal + (dropdownElement as any)._handleClickOutside = handleClickOutside; + + // Method to set value programmatically + (dropdownElement as any).setValue = (value) => { + const optionsSource = options || []; + const optionItems = Array.isArray(optionsSource) ? optionsSource : optionsSource(); + const optionToSelect = optionItems.find(opt => opt.value === value); + if (optionToSelect) { + selectedOption = optionToSelect; + updateHeader(); + + // Update selected state in list + dropdownList.querySelectorAll("." + className + "-item").forEach(item => { + item.classList.remove(itemClassSelected); + item.setAttribute("aria-selected", "false"); + if ((item as any)?.dataset?.value === value) { + item.classList.add(itemClassSelected); + item.setAttribute("aria-selected", "true"); + } + }); + + // Call handler + // handler(value); + } else if (value === null || value === undefined) { + // Reset to placeholder + selectedOption = null; + updateHeader(); + + // Remove all selections + dropdownList.querySelectorAll("." + className + "-item").forEach(item => { + item.classList.remove(itemClassSelected); + item.setAttribute("aria-selected", "false"); + }); + } + }; + + // Method to get current value + (dropdownElement as any).getValue = () => { + return selectedOption ? selectedOption.value : null; + }; + + (dropdownElement as any).__updateSelect = () => { + updateTitle(); + updateHeader(); + updateOptions(); + }; + + dropdownContainer.appendChild(dropdownHeader); + dropdownContainer.appendChild(dropdownList); + dropdownElement.appendChild(dropdownContainer); + (dropdownElement as any).__updateSelect(); + + return dropdownElement; + } + + public static createActionDropdown( + options: Array<{value: string, text: string, title?: string, icon?: string}> | (() => Array<{value: string, text: string, title?: string, icon?: string}>), + isSelected: (option: {value: string, text: string, icon?: string}) => boolean, + handler: (value: string) => boolean, + title: string | Function, + className: string = "sa-action-dropdown", + showArrow = true + ): HTMLDivElement { + const dropdownOpenedClass = className + "--opened"; + const dropdownElement = document.createElement("div"); + dropdownElement.className = className; + + const titleText = !!title && (typeof title == "string" ? title : title()); + + const dropdownHeader = document.createElement("div"); + dropdownHeader.className = className + "-header"; + dropdownHeader.setAttribute("tabindex", "0"); + dropdownHeader.setAttribute("role", "button"); + dropdownHeader.setAttribute("aria-haspopup", "listbox"); + dropdownHeader.setAttribute("aria-expanded", "false"); + dropdownHeader.setAttribute("aria-label", titleText); + const itemClassSelected = className + "-item--selected"; + + const optionsSource = options || []; + let optionItems: Array = Array.isArray(optionsSource) ? optionsSource : optionsSource(); + const headerContent = document.createElement("div"); + headerContent.className = className + "-header-content"; + headerContent.innerHTML = ""; + + const headerText = document.createElement("span"); + headerText.className = className + "-title"; + headerText.textContent = titleText; + headerContent.appendChild(headerText); + dropdownHeader.appendChild(headerContent); + + if (showArrow) { + const arrowElement = document.createElement("div"); + arrowElement.className = className + "-arrow"; + arrowElement.appendChild(DocumentHelper.createSvgElement("chevrondown-24x24")); + dropdownHeader.appendChild(arrowElement); + } + + const dropdownList = document.createElement("ul"); + dropdownList.className = className + "-list"; + dropdownList.setAttribute("role", "listbox"); + dropdownList.innerHTML = ""; + const dropdownContainer = document.createElement("div"); + dropdownContainer.className = className + "-container"; + + let currentFocusIndex = -1; + + const hidePopup = () => { + dropdownHeader.classList.remove(dropdownOpenedClass); + dropdownList.classList.remove(dropdownOpenedClass); + dropdownHeader.setAttribute("aria-expanded", "false"); + currentFocusIndex = -1; + }; + + const focusItem = (index: number) => { + const items = dropdownList.querySelectorAll("." + className + "-item"); + if (items.length === 0) return; + + items.forEach(item => { + item.classList.remove(className + "-item--focused"); + }); + + if (index < 0) index = items.length - 1; + if (index >= items.length) index = 0; + + currentFocusIndex = index; + const itemToFocus = items[currentFocusIndex] as HTMLElement; + itemToFocus.classList.add(className + "-item--focused"); + itemToFocus.scrollIntoView({ block: "nearest" }); + }; + + const updateHeaderLabel = () => { + const titleText = !!title && (typeof title == "string" ? title : title()); + dropdownHeader.setAttribute("aria-label", titleText); + headerText.innerText = titleText; + // const selectedItems = optionItems.filter(option => isSelected(option)); + // if (selectedItems.length > 0) { + // const selectedTexts = selectedItems.map(item => item.text).join(", "); + // dropdownHeader.setAttribute("aria-label", `Selected: ${selectedTexts}`); + // } else { + // dropdownHeader.setAttribute("aria-label", title); + // } + }; + + const updateOptions = () => { + dropdownList.innerHTML = ""; + const optionsSource = options || []; + const optionItems = Array.isArray(optionsSource) ? optionsSource : optionsSource(); + optionItems.forEach((option, index) => { + const dropdownItem = document.createElement("li"); + dropdownItem.className = className + "-item"; + if (option.title) { + dropdownItem.title = option.title; + } + dropdownItem.dataset.value = option.value; + dropdownItem.setAttribute("role", "option"); + dropdownItem.setAttribute("tabindex", "-1"); + dropdownItem.id = `${className}-item-${option.value}`; + + if (option.icon) { + const iconContainer = document.createElement("div"); + iconContainer.className = className + "-icon"; + iconContainer.appendChild(DocumentHelper.createSvgElement(option.icon)); + dropdownItem.appendChild(iconContainer); + } + + const textSpan = document.createElement("span"); + textSpan.textContent = option.text; + dropdownItem.appendChild(textSpan); + + if (isSelected(option)) { + dropdownItem.classList.add(itemClassSelected); + dropdownItem.setAttribute("aria-selected", "true"); + } else { + dropdownItem.setAttribute("aria-selected", "false"); + } + + dropdownItem.addEventListener("click", (e) => { + if (handler(option.value)) { + hidePopup(); + } + e.preventDefault(); + e.stopPropagation(); + + if (isSelected(option)) { + dropdownItem.classList.add(itemClassSelected); + dropdownItem.setAttribute("aria-selected", "true"); + } else { + dropdownItem.classList.remove(itemClassSelected); + dropdownItem.setAttribute("aria-selected", "false"); + } + + updateHeaderLabel(); + }); + + dropdownList.appendChild(dropdownItem); + }); + }; + + const handleKeyDown = (e: KeyboardEvent) => { + if (!dropdownHeader.classList.contains(dropdownOpenedClass)) { + if (e.key === "Enter" || e.key === " " || e.key === "ArrowDown") { + e.preventDefault(); + dropdownHeader.classList.add(dropdownOpenedClass); + dropdownList.classList.add(dropdownOpenedClass); + dropdownHeader.setAttribute("aria-expanded", "true"); + } + return; + } + + const items = dropdownList.querySelectorAll("." + className + "-item"); + if (items.length === 0) return; + + switch (e.key) { + case "ArrowDown": + e.preventDefault(); + focusItem(currentFocusIndex + 1); + break; + case "ArrowUp": + e.preventDefault(); + focusItem(currentFocusIndex - 1); + break; + case "Enter": + case " ": + e.preventDefault(); + if (currentFocusIndex >= 0 && currentFocusIndex < items.length) { + const selectedItem = items[currentFocusIndex] as HTMLElement; + const value = selectedItem.dataset.value; + if (value) { + const option = optionItems.find(opt => opt.value === value); + if (option) { + if (handler(option.value)) { + hidePopup(); + } + + if (isSelected(option)) { + selectedItem.classList.add(itemClassSelected); + selectedItem.setAttribute("aria-selected", "true"); + } else { + selectedItem.classList.remove(itemClassSelected); + selectedItem.setAttribute("aria-selected", "false"); + } + + updateHeaderLabel(); + } + } + } + break; + case "Escape": + e.preventDefault(); + hidePopup(); + break; + } + }; + + const handleClickOutside = (event) => { + if (!dropdownElement.contains(event.target)) { + hidePopup(); + } + }; + + dropdownHeader.addEventListener("click", (e) => { + updateOptions(); + const isOpened = dropdownHeader.classList.toggle(dropdownOpenedClass); + dropdownList.classList.toggle(dropdownOpenedClass); + dropdownHeader.setAttribute("aria-expanded", isOpened ? "true" : "false"); + + if (!isOpened) { + currentFocusIndex = -1; + } + + e.preventDefault(); + e.stopPropagation(); + }); + + dropdownHeader.addEventListener("keydown", handleKeyDown); + dropdownList.addEventListener("keydown", handleKeyDown); + + document.addEventListener("click", handleClickOutside); + + (dropdownElement as any)._handleClickOutside = handleClickOutside; + + (dropdownElement as any).setValues = (values: string[]) => { + const optionsSource = options || []; + const optionItems = Array.isArray(optionsSource) ? optionsSource : optionsSource(); + + dropdownList.querySelectorAll("." + className + "-item").forEach(item => { + const itemValue = (item as any)?.dataset?.value; + if (itemValue && values.indexOf(itemValue) !== -1) { + item.classList.add(itemClassSelected); + item.setAttribute("aria-selected", "true"); + } else { + item.classList.remove(itemClassSelected); + item.setAttribute("aria-selected", "false"); + } + }); + + updateHeaderLabel(); + }; + + (dropdownElement as any).getValues = () => { + return optionItems.filter(option => isSelected(option)).map(option => option.value); + }; + + (dropdownElement as any).__updateSelect = () => { + updateOptions(); + updateHeaderLabel(); + }; + + dropdownContainer.appendChild(dropdownHeader); + dropdownContainer.appendChild(dropdownList); + dropdownElement.appendChild(dropdownContainer); + (dropdownElement as any).__updateSelect(); + + return dropdownElement; + } + + /** + * Destroys dropdown and removes all event handlers + * @param {HTMLElement} dropdownElement - Root dropdown element + */ + public static destroyDropdown(dropdownElement: any) { + if (dropdownElement && dropdownElement._handleClickOutside) { + document.removeEventListener("click", dropdownElement._handleClickOutside); + dropdownElement._handleClickOutside = null; + } + if (dropdownElement && dropdownElement.parentNode) { + dropdownElement.parentNode.removeChild(dropdownElement); + } + } + + // public static createButton( + // handler: (e: any) => void, + // text = "", + // className = "sa-toolbar__button" + // ) { + // const button = DocumentHelper.createElement("span", className, { + // innerText: text, + // onclick: handler, + // }); + // return button; + // } + public static createButton( - handler: (e: any) => void, + handler: (e:any) => void, text = "", - className = "sa-toolbar__button" - ) { - const button = DocumentHelper.createElement("span", className, { - innerText: text, - onclick: handler, + className = "sa-toolbar__button", + icon?: string + ): HTMLDivElement { + const buttonElement = document.createElement("div"); + buttonElement.className = className + (icon ? " " + className + "-with-icon" : ""); + buttonElement.setAttribute("role", "button"); + buttonElement.setAttribute("tabindex", "0"); + + if (icon) { + const svgElement = document.createElement("div"); + svgElement.className = className + "-icon"; + svgElement.appendChild(DocumentHelper.createSvgElement(icon)); + buttonElement.appendChild(svgElement); + } + const buttonText = document.createElement("span"); + buttonText.className = className + "-text"; + buttonText.textContent = text; + buttonElement.appendChild(buttonText); + + (buttonElement as any).setText = function(newText) { + buttonText.textContent = newText; + }; + + buttonElement.addEventListener("click", function(e) { + handler(e); + }); + + buttonElement.addEventListener("keydown", function(e) { + if (e.key === "Enter" || e.key === " ") { + e.preventDefault(); + handler(e); + } + }); + + return buttonElement; + } + + public static setStyles(element: HTMLElement, styles: Record): void { + if (!element || !styles) return; + + Object.keys(styles).forEach(property => { + element.style.setProperty(property, styles[property]); }); - return button; } public static createElement( @@ -90,11 +713,14 @@ export class DocumentHelper { return svgElem; } - public static createSvgButton(path: string): HTMLButtonElement { + public static createSvgButton(path: string, title?: string): HTMLButtonElement { const btn = ( DocumentHelper.createElement("button", "sa-table__svg-button") ); btn.appendChild(DocumentHelper.createSvgElement(path)); + if (title) { + btn.title = title; + } return btn; } @@ -156,6 +782,41 @@ export class DocumentHelper { ); return el; } + + public static createTextEditor(options: { showIcon?: boolean, placeholder?: string, className?: string, inputValue?: string, onchange?: (val) => void } = {}): HTMLElement { + const { + className = "sa-table-filter", + placeholder = localization.getString("filterPlaceholder"), + inputValue = "", + showIcon = true, + } = options; + + const editor = document.createElement("div"); + editor.className = className; + + if (showIcon) { + const iconContainer = DocumentHelper.createElement("div", className + "_icon"); + const searchIcon = DocumentHelper.createSvgElement("search-24x24"); + + iconContainer.appendChild(searchIcon); + editor.appendChild(iconContainer); + } + + const input = DocumentHelper.createElement("input", className + "_input", + { + placeholder: placeholder, + defaultValue: inputValue, + } + ); + input.onchange = (e) => { + if (!!options.onchange) { + options.onchange(input.value); + } + }; + + editor.appendChild(input); + return editor; + } } export var options = { diff --git a/src/utils/toggle.scss b/src/utils/toggle.scss new file mode 100644 index 000000000..16adb4a33 --- /dev/null +++ b/src/utils/toggle.scss @@ -0,0 +1,103 @@ +.sa-toggle-container { + display: flex; + gap: var(--sjs2-spacing-x100, 8px); + + @media screen and (max-width: 600px) { + width: 100%; + justify-content: end; + } +} + +.sa-toggle-element { + display: flex; + padding: var(--sjs2-spacing-x075, 6px); + width: calc(2 * var(--sjs2-size-x150, 12px) + var(--sjs2-spacing-x050, 4px)); + align-items: center; + gap: var(--sjs2-spacing-x050, 4px); + transition: background-color 0.3s ease; + + border-radius: var(--sjs2-radius-control-toggle, 9999px); + outline: var(--sjs2-border-width-default, 1px) solid var(--sjs2-color-control-toggle-false-default-border, #D4D4D4); + background: var(--sjs2-color-control-toggle-false-default-bg, rgba(28, 27, 32, 0.05)); + + /* sjs2/shadow/inner */ + box-shadow: var(--sjs2-shadow-size-inner-offset-x, 0) var(--sjs2-shadow-size-inner-offset-y, 0) var(--sjs2-shadow-size-inner-blur, 0) var(--sjs2-shadow-size-inner-spread, 1px) var(--sjs2-shadow-color-inner, #D4D4D4) inset; + + &:hover { + outline: var(--sjs2-border-width-default, 1px) solid var(--sjs2-color-control-toggle-false-hovered-border, #D4D4D4); + background: var(--sjs2-color-control-toggle-false-hovered-bg, rgba(28, 27, 32, 0.10)); + + .sa-toggle-handle { + outline: var(--ctr-toggle-button-thumb-border-width, 0) solid var(--sjs2-color-control-toggle-false-hovered-icon, rgba(28, 27, 32, 0.60)); + background: var(--sjs2-color-control-toggle-false-hovered-icon, rgba(28, 27, 32, 0.60)); + } + } + + &:focus { + outline: var(--sjs2-border-width-focused, 2px) solid var(--sjs2-color-control-toggle-false-focused-border, #19B394); + background: var(--sjs2-color-control-toggle-false-focused-bg, #F5F5F5); + + .sa-toggle-handle { + outline: var(--ctr-toggle-button-thumb-border-width, 0) solid var(--sjs2-color-control-toggle-false-focused-icon, rgba(28, 27, 32, 0.60)); + background: var(--sjs2-color-control-toggle-false-focused-icon, rgba(28, 27, 32, 0.60)); + } + } +} + +.sa-toggle-element.active { + outline: var(--sjs2-border-width-default, 1px) solid var(--sjs2-color-control-toggle-true-default-border, #19B394); + background: var(--sjs2-color-control-toggle-true-default-bg, #19B394); + + &:hover { + outline: var(--sjs2-border-width-default, 1px) solid var(--sjs2-color-control-toggle-true-hovered-border, #19B394); + background: var(--sjs2-color-control-toggle-true-hovered-bg, #15987E); + + .sa-toggle-handle { + background: var(--sjs2-color-control-toggle-true-hovered-icon, #FFF); + } + } + + &:focus { + outline: var(--sjs2-border-width-focused, 2px) solid var(--sjs2-color-control-toggle-true-focused-border, #19B394); + background: var(--sjs2-color-control-toggle-true-focused-bg, #FFF); + + .sa-toggle-handle { + background: var(--sjs2-color-control-toggle-true-focused-icon, #19B394); + } + + } +} + +.sa-toggle-handle { + display: flex; + width: var(--sjs2-size-x150, 12px); + height: var(--sjs2-size-x150, 12px); + justify-content: center; + align-items: center; + transition: transform 0.3s ease, background-color 0.3s ease; + + border-radius: var(--sjs2-radius-control-toggle-item, 9999px); + outline: var(--ctr-toggle-button-thumb-border-width, 0) solid var(--sjs2-color-control-toggle-false-default-icon, rgba(28, 27, 32, 0.60)); + background: var(--sjs2-color-control-toggle-false-default-icon, rgba(28, 27, 32, 0.60)); +} + +.sa-toggle-element.active .sa-toggle-handle { + background: var(--sjs2-color-control-toggle-true-default-icon, #FFF); + transform: translateX(calc(var(--sjs2-size-x150, 12px) + var(--sjs2-spacing-x050, 4px))); +} + +.sa-toggle-text { + flex: 1 0 0; + color: var(--sjs2-color-fg-basic-primary, #1C1B20); + + /* sjs2/typography/default */ + font-family: var(--sjs2-typography-font-family-default, "Open Sans"); + font-size: var(--sjs2-typography-font-size-default, 16px); + font-style: normal; + font-weight: 400; + line-height: var(--sjs2-typography-line-height-default, 24px); /* 150% */ + + @media screen and (max-width: 600px) { + flex: unset; + } +} diff --git a/src/utils/toggle.ts b/src/utils/toggle.ts new file mode 100644 index 000000000..13b0e5d0b --- /dev/null +++ b/src/utils/toggle.ts @@ -0,0 +1,74 @@ +import { DocumentHelper } from "."; + +import "./toggle.scss"; + +export class ToggleWidget { + private toggleElement: HTMLElement; + private isActive: boolean; + + public container: HTMLElement; + + constructor(private toggleHandler: (options: { isActive: boolean }) => void, private text?: string | Function, initialState = false) { + this.isActive = initialState; + this.createWidget(); + this.bindEvents(); + } + + get title(): string { + return !!this.text && (typeof this.text == "string" ? this.text : this.text()); + } + + createWidget() { + this.container = DocumentHelper.createElement("div", "sa-toggle-container"); + this.toggleElement = DocumentHelper.createElement("div", "sa-toggle-element"); + this.toggleElement.setAttribute("tabindex", "0"); + this.toggleElement.setAttribute("role", "switch"); + this.toggleElement.setAttribute("aria-checked", this.isActive + ""); + this.toggleElement.setAttribute("aria-label", this.title); + + const statusText = DocumentHelper.createElement("div", "sa-toggle-text"); + statusText.textContent = this.title; + + this.toggleElement.appendChild(DocumentHelper.createElement("div", "sa-toggle-handle")); + this.container.appendChild(this.toggleElement); + this.container.appendChild(statusText); + + this.updateView(); + } + + bindEvents() { + this.container.addEventListener("click", () => { + this.toggle(); + }); + + this.toggleElement.addEventListener("keydown", (e) => { + if (e.key === " " || e.key === "Enter") { + e.preventDefault(); + this.toggle(); + } + }); + } + + toggle() { + this.isActive = !this.isActive; + this.updateView(); + this.toggleHandler({ isActive: this.isActive }); + } + + updateView() { + if (this.isActive) { + this.toggleElement.classList.add("active"); + this.toggleElement.setAttribute("aria-checked", "true"); + } else { + this.toggleElement.classList.remove("active"); + this.toggleElement.setAttribute("aria-checked", "false"); + } + } + + setState(state) { + if (this.isActive !== state) { + this.isActive = state; + this.updateView(); + } + } +} \ No newline at end of file diff --git a/src/utils/utils.scss b/src/utils/utils.scss index 93c41d12d..85b303c0e 100644 --- a/src/utils/utils.scss +++ b/src/utils/utils.scss @@ -1,6 +1,11 @@ +@use "../globals" as *; +@forward "../globals"; + .sa-commercial { box-sizing: border-box; padding: var(--sjs2-spacing-static-x150, 12px) var(--sjs2-spacing-static-x600, 48px); + margin-top: calc(-1 * var(--sjs2-spacing-x300, 24px)); + margin-bottom: var(--sjs2-spacing-x300, 24px); justify-content: center; width: 100%; background: var(--sjs2-color-bg-brand-primary, #19B394); @@ -42,4 +47,422 @@ line-height: var(--sjs2-line-height-semantic-small, 16px); } } +} + + +// Dropdown +.sa-dropdown, +.sa-action-dropdown { + position: relative; + cursor: pointer; + user-select: none; + + color: var(--sjs2-color-fg-basic-primary, #1C1B20); + + /* sjs2/typography/default-strong */ + font-family: var(--sjs2-typography-font-family-default, "Open Sans"); + font-size: var(--sjs2-typography-font-size-default, 16px); + font-style: normal; + font-weight: 600; + line-height: var(--sjs2-typography-line-height-default, 24px); /* 150% */ +} + +.sa-action-dropdown:hover, +.sa-action-dropdown.sa-action-dropdown--opened { + border-radius: var(--sjs2-radius-control-action, 8px); + background: var(--sjs2-color-bg-positive-tertiary-dim, rgba(25, 179, 148, 0.10)); +} + +.sa-dropdown-header { + display: flex; + padding: var(--sjs2-layout-control-formbox-medium-vertical, 4px) var(--sjs2-layout-control-formbox-medium-horizontal, 4px); + align-items: flex-start; + gap: var(--sjs2-layout-control-formbox-medium-gap, 4px); + align-self: stretch; + + border-radius: var(--sjs2-radius-semantic-form, 8px); + margin: var(--sjs2-border-width-x100, 1px); + outline: var(--sjs2-border-width-x100, 1px) solid var(--sjs2-color-control-formbox-default-border, #D4D4D4); + background: var(--sjs2-color-control-formbox-default-bg, rgba(28, 27, 32, 0.05)); + + &:focus { + border-radius: var(--sjs2-radius-semantic-form, 8px); + background: var(--sjs2-color-control-formbox-focused-bg, #F5F5F5); + box-shadow: var(--sjs2-border-offset-x-form-focused, 0) var(--sjs2-border-offset-y-form-focused, 0) var(--sjs2-border-blur-form-focused, 0) var(--sjs2-border-spread-form-focused, 2px) var(--sjs2-color-control-formbox-focused-border, #19B394) inset; + outline: none; + } +} + +.sa-dropdown-arrow { + display: flex; + padding: var(--sjs2-layout-control-action-small-box-vertical, 8px) var(--sjs2-layout-control-action-small-box-horizontal, 8px); + justify-content: center; + align-items: center; + align-self: stretch; + border-radius: var(--sjs2-radius-semantic-form-item, 4px); + background: var(--sjs2-color-bg-neutral-tertiary, rgba(28, 27, 32, 0.00)); +} + +.sa-dropdown-arrow:hover { + background: var(--sjs2-color-bg-neutral-tertiary-dim, rgba(28, 27, 32, 0.05)); +} + +.sa-dropdown--opened .sa-dropdown-arrow { + background: var(--sjs2-color-bg-neutral-tertiary-dim, rgba(28, 27, 32, 0.05)); +} + +.sa-dropdown-arrow svg { + display: flex; + width: var(--sjs2-size-icon-medium, 24px); + height: var(--sjs2-size-icon-medium, 24px); + justify-content: center; + align-items: center; + + use { + fill: var(--sjs2-color-fg-basic-primary-alt, rgba(66, 65, 70, 1)); + } +} + +.sa-dropdown-container, +.sa-action-dropdown-container { + display: inline-block; +} + +.sa-dropdown__title { + padding: var(--sjs2-spacing-x150, 12px) var(--sjs2-size-x000, 0.001px) var(--sjs2-spacing-x150, 12px) var(--sjs2-size-x150, 12px); + margin-inline-end: var(--sjs2-spacing-static-x100, 8px); + overflow: hidden; + color: var(--sjs2-color-fg-basic-secondary, rgba(28, 27, 32, 0.60)); + text-overflow: ellipsis; + + /* sjs2/typography/default */ + font-family: var(--sjs2-typography-font-family-default, "Open Sans"); + font-size: var(--sjs2-typography-font-size-default, 16px); + font-style: normal; + font-weight: 400; + line-height: var(--sjs2-typography-line-height-default, 24px); /* 150% */ +} + +.sa-dropdown-list, +.sa-action-dropdown-list { + position: absolute; + // top: 100%; + // left: 0; + // right: 0; + min-width: 150px; + max-height: 50vh; + max-width: 80vw; + overflow-x: hidden; + overflow-y: auto; + border: var(--sjs2-border-width-x100, 1px) solid var(--sjs2-color-border-basic-secondary, #D4D4D4); + border-top: none; + border-radius: var(--sjs2-radius-container-drop, 16px); + background: var(--sjs2-color-utility-sheet, #FFF); + display: none; + z-index: 1000; + margin: 0; + list-style: none; + transition: all 0.3s; + + margin-top: 8px; + padding: var(--sjs2-layout-container-drop-vertical, 8px) var(--sjs2-layout-container-drop-horizontal, 8px); + + /* sjs2/shadow/large */ + box-shadow: var(--sjs2-shadow-size-large-offset-x, 0) var(--sjs2-shadow-size-large-offset-y, 6px) var(--sjs2-shadow-size-large-blur, 12px) var(--sjs2-shadow-size-large-spread, 4px) var(--sjs2-shadow-color-large, rgba(0, 76, 68, 0.10)); + + -webkit-font-smoothing: antialiased; + -webkit-tap-highlight-color: transparent; + + @-moz-document url-prefix() { + scrollbar-width: thin; + scrollbar-color: #00000026 transparent; + } + + &::-webkit-scrollbar { + width: 12px; + height: 12px; + background-color: transparent; + } + + &::-webkit-scrollbar-thumb { + border: 4px solid rgba(0, 0, 0, 0); + background-clip: padding-box; + border-radius: 1024px; + background-color: #00000026; + } + + &::-webkit-scrollbar-track { + background: transparent; + } + + &::-webkit-scrollbar-thumb:hover { + border: 2px solid rgba(0, 0, 0, 0); + background-color: #00000026; + } +} + +.sa-dropdown-list.sa-dropdown--opened { + display: block; +} + +.sa-action-dropdown-list.sa-action-dropdown--opened { + display: block; + border-radius: var(--sjs2-radius-container-drop, 16px); + border: var(--sjs2-border-width-x100, 1px) solid var(--sjs2-color-border-basic-secondary, #D4D4D4); + background: var(--sjs2-color-utility-sheet, #FFF); + + /* sjs2/border-effect/floating/default */ + box-shadow: var(--sjs2-border-offset-x-floating-default, 0) var(--sjs2-border-offset-y-floating-default, 6px) var(--sjs2-border-blur-floating-default, 12px) var(--sjs2-border-spread-floating-default, 4px) var(--sjs2-color-utility-shadow-floating-default, rgba(0, 76, 68, 0.20)); +} + +.sa-dropdown-item, +.sa-action-dropdown-item { + width: max-content; + min-width: calc(100% - 2 * var(--sjs2-size-x200, 16px)); + max-width: calc(100% - 2 * var(--sjs2-size-x200, 16px)); + padding: var(--sjs2-spacing-x150, 12px) var(--sjs2-size-x200, 16px); + cursor: pointer; + transition: all 0.3s; + display: flex; + align-items: center; + gap: var(--sjs2-spacing-x150, 12px); + border-radius: var(--sjs2-radius-control-drop-item, 8px); + color: var(--sjs2-color-fg-basic-primary, #1C1B20); + background: var(--sjs2-color-bg-brand-tertiary, rgba(25, 179, 148, 0.00)); + + /* sjs2/typography/default */ + font-family: $font-family; + font-size: var(--sjs2-typography-font-size-default, 16px); + font-style: normal; + font-weight: 400; + line-height: var(--sjs2-typography-line-height-default, 24px); /* 150% */ + + &:hover { + background-color: var(--sjs2-color-bg-brand-tertiary-dim, rgba(25, 179, 148, 0.10)); + + .sa-action-dropdown-icon { + border-radius: var(--sjs2-radius-control-checkbox, 4px); + background: var(--sjs2-color-control-check-false-hovered-bg, rgba(28, 27, 32, 0.10)); + box-shadow: var(--sjs2-border-offset-x-form-hovered, 0) var(--sjs2-border-offset-y-form-hovered, 0) var(--sjs2-border-blur-form-hovered, 0) var(--sjs2-border-spread-form-hovered, 1px) var(--sjs2-color-control-check-false-hovered-border, #D4D4D4) inset; + } + + &.sa-action-dropdown-item--selected .sa-action-dropdown-icon { + border-radius: var(--sjs2-radius-control-checkbox, 4px); + background: var(--sjs2-color-control-check-true-hovered-bg, #15987E); + box-shadow: var(--sjs2-border-offset-x-form-hovered, 0) var(--sjs2-border-offset-y-form-hovered, 0) var(--sjs2-border-blur-form-hovered, 0) var(--sjs2-border-spread-form-hovered, 1px) var(--sjs2-color-control-check-true-hovered-border, #15987E) inset; + } + } +} + +.sa-action-dropdown-item:focus, +.sa-action-dropdown-item--focused, +.sa-dropdown-item:focus, +.sa-dropdown-item--focused { + border-radius: var(--sjs2-radius-control-drop-item, 8px); + background: var(--sjs2-color-bg-brand-tertiary-dim, rgba(25, 179, 148, 0.10)); +} + +.sa-action-dropdown-item--selected .sa-action-dropdown-icon { + border-radius: var(--sjs2-radius-control-checkbox, 4px); + background: var(--sjs2-color-control-check-true-default-bg, #19B394); + box-shadow: var(--sjs2-border-offset-x-form-default, 0) var(--sjs2-border-offset-y-form-default, 0) var(--sjs2-border-blur-form-default, 0) var(--sjs2-border-spread-form-default, 1px) var(--sjs2-color-control-check-true-default-border, #19B394) inset; + + svg { + display: block; + } +} + +.sa-action-dropdown-icon { + width: var(--sjs2-size-icon-medium, 24px); + height: var(--sjs2-size-icon-medium, 24px); + min-width: var(--sjs2-size-icon-medium, 24px); + + border-radius: var(--sjs2-radius-control-checkbox, 4px); + background: var(--sjs2-color-control-check-false-default-bg, #F5F5F5); + box-shadow: var(--sjs2-border-offset-x-form-default, 0) var(--sjs2-border-offset-y-form-default, 0) var(--sjs2-border-blur-form-default, 0) var(--sjs2-border-spread-form-default, 1px) var(--sjs2-color-control-check-false-default-border, #D4D4D4) inset; + + svg { + display: none; + width: var(--sjs2-size-icon-medium, 24px); + height: var(--sjs2-size-icon-medium, 24px); + } + + use { + fill: var(--sjs2-color-control-check-true-default-icon, #FFF); + } +} + +.sa-dropdown-item.sa-dropdown-item--selected { + background-color: var(--sjs2-color-bg-brand-primary, #19B394); + color: var(--sjs2-color-fg-static-main-primary, #FFF); + + /* sjs2/typography/default-strong */ + font-family: $font-family; + font-size: var(--sjs2-typography-font-size-default, 16px); + font-style: normal; + font-weight: 600; + line-height: var(--sjs2-typography-line-height-default, 24px); /* 150% */ +} + +.sa-dropdown-placeholder { + overflow: hidden; + color: var(--sjs2-color-control-input-default-placeholder, rgba(28, 27, 32, 0.60)); + text-overflow: ellipsis; + + /* sjs2/typography/default */ + font-family: var(--sjs2-typography-font-family-default, "Open Sans"); + font-size: var(--sjs2-typography-font-size-default, 16px); + font-style: normal; + font-weight: 400; + line-height: var(--sjs2-typography-line-height-default, 24px); /* 150% */ +} + +.sa-dropdown-icon { + width: var(--sa-icon-size); + height: var(--sa-icon-size); + flex-shrink: 0; +} + +.sa-dropdown-header-icon { + width: var(--sa-icon-size); + height: var(--sa-icon-size); + margin-right: 8px; +} + +.sa-dropdown-header-content { + display: flex; + padding: var(--sjs2-layout-control-input-medium-content-vertical, 8px) var(--sjs2-layout-control-input-medium-content-horizontal, 12px); + align-items: flex-start; + flex: 1 0 0; +} + +.sa-dropdown-header-text { + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; + color: var(--sjs2-color-control-input-default-value, #1C1B20); + + /* sjs2/typography/default */ + font-family: $font-family; + font-size: var(--sjs2-typography-font-size-default, 16px); + font-style: normal; + font-weight: 400; + line-height: var(--sjs2-typography-line-height-default, 24px); /* 150% */ +} + +.sa-action-dropdown-header { + display: flex; + padding: var(--sjs2-layout-control-action-small-box-vertical, 8px) var(--sjs2-layout-control-action-small-box-horizontal, 8px); + justify-content: center; + align-items: center; + gap: var(--sjs2-layout-control-action-small-box-gap, 0); + border-radius: var(--sjs2-radius-control-action, 8px); + background: var(--sjs2-color-bg-positive-tertiary, rgba(25, 179, 148, 0.00)); + + &:focus-visible { + border-radius: var(--sjs2-radius-control-action, 8px); + outline: var(--sjs2-border-width-a11y, 4px) solid var(--sjs2-color-utility-a11y, rgba(102, 180, 252, 0.60)); + background: var(--sjs2-color-bg-positive-tertiary, rgba(25, 179, 148, 0.00)); + } +} + +.sa-action-dropdown-title { + padding: var(--sjs2-layout-control-action-small-label-vertical, 0) var(--sjs2-layout-control-action-small-label-horizontal, 6px); +} + +.sa-action-dropdown-arrow { + display: flex; + padding: var(--sjs2-layout-control-action-small-addon-vertical, 4px) var(--sjs2-layout-control-action-small-addon-horizontal, 4px); + justify-content: center; + align-items: center; +} + +.sa-action-dropdown-arrow svg { + display: flex; + width: 16px; + height: 16px; + justify-content: center; + align-items: center; + + use { + fill: var(--sjs2-color-project-accent-600, rgba(25, 179, 148, 1)); + } +} + +.sa-action-dropdown-header { + display: flex; + min-width: var(--sjs2-size-semantic-small, 40px); + padding: var(--sjs2-layout-control-action-small-box-vertical, 8px) var(--sjs2-layout-control-action-small-box-horizontal, 8px); + justify-content: center; + align-items: center; + gap: var(--sjs2-layout-control-action-small-box-gap, 0); +} + +.sa-button { + outline: none; + user-select: none; + cursor: pointer; + display: flex; + flex-shrink: 0; + min-width: var(--sjs2-size-semantic-small, 40px); + padding: var(--sjs2-layout-control-action-small-box-vertical, 8px) var(--sjs2-layout-control-action-small-box-horizontal, 8px); + justify-content: center; + align-items: center; + gap: var(--sjs2-layout-control-action-small-box-gap, 0); +} + +.sa-button-text { + display: flex; + flex: 1 0 auto; + padding: var(--sjs2-layout-control-action-small-label-vertical, 0) var(--sjs2-layout-control-action-small-label-horizontal, 6px); + justify-content: center; + align-items: center; +} + +.sa-button-brand-secondary { + border-radius: var(--sjs2-radius-control-button, 8px); + background: var(--sjs2-color-bg-brand-secondary, rgba(25, 179, 148, 0.10)); + color: var(--sjs2-color-fg-brand-primary, #19B394); + + &:hover { + background: var(--sjs2-color-bg-brand-secondary-dim, rgba(25, 179, 148, 0.15)); + } +} + +.sa-button-brand-tertiary { + border-radius: 8px; + background: var(--sjs2-color-bg-brand-tertiary, rgba(25, 179, 148, 0.00)); + color: var(--sjs2-color-fg-brand-primary, #19B394); + text-align: center; + + /* sjs2/typography/default-strong */ + font-family: var(--sjs2-typography-font-family-default, "Open Sans"); + font-size: var(--sjs2-typography-font-size-default, 16px); + font-style: normal; + font-weight: 600; + line-height: var(--sjs2-typography-line-height-default, 24px); /* 150% */ + + &:hover { + background: var(--sjs2-color-bg-brand-tertiary-dim, rgba(25, 179, 148, 0.10)); + } +} + +@media screen and (max-width: 600px) { + .sa-toolbar { + flex-direction: column; + align-items: flex-start; + } + + .sa-dropdown { + width: 100%; + } + + .sa-dropdown-container { + width: 100%; + } + + .sa-dropdown-list.sa-dropdown--opened { + min-width: calc(100% - var(--sjs2-layout-container-drop-horizontal, 8px) * 2); + max-width: calc(100% - var(--sjs2-layout-container-drop-horizontal, 8px) * 2); + } } \ No newline at end of file diff --git a/src/utils/utils.ts b/src/utils/utils.ts new file mode 100644 index 000000000..99ed6c076 --- /dev/null +++ b/src/utils/utils.ts @@ -0,0 +1,31 @@ +export function reverseAll(labels: string[], seriesLabels: string[], colors: string[], hasSeries: boolean, texts: any[][], datasets: any[][]) { + labels = [].concat(labels).reverse(); + seriesLabels = [].concat(seriesLabels).reverse(); + colors = [].concat(colors.slice(0, hasSeries ? seriesLabels.length : labels.length)).reverse(); + const ts = []; + texts.forEach(text => { + ts.push([].concat(text).reverse()); + }); + texts = ts; + const ds = []; + datasets.forEach(dataset => { + ds.push([].concat(dataset).reverse()); + }); + datasets = ds; + return { labels, seriesLabels, colors, texts, datasets }; +} + +export function removeUndefinedProperties(obj): void { + if (obj === null || obj === undefined || typeof obj !== "object") { + return; + } + Object.keys(obj).forEach(key => { + if(typeof obj[key] === "object") { + removeUndefinedProperties(obj[key]); + } + if(obj[key] === undefined) { + delete obj[key]; + } + }); + return; +} \ No newline at end of file diff --git a/src/visualizationComposite.ts b/src/visualizationComposite.ts index b2dc86588..edac09c01 100644 --- a/src/visualizationComposite.ts +++ b/src/visualizationComposite.ts @@ -7,9 +7,9 @@ export class VisualizationComposite extends VisualizationPanelDynamic { question: Question, data: Array<{ [index: string]: any }>, options?: Object, - name?: string + type?: string ) { - super(question, data, options, name || "composite"); + super(question, data, options, type || "composite"); } getQuestions(): Array { diff --git a/src/visualizationMatrixDropdown.ts b/src/visualizationMatrixDropdown.ts index 7b527cfc7..bbf887100 100644 --- a/src/visualizationMatrixDropdown.ts +++ b/src/visualizationMatrixDropdown.ts @@ -33,9 +33,9 @@ export class VisualizationMatrixDropdown extends VisualizerBase { question: QuestionMatrixDropdownModel, data: Array<{ [index: string]: any }>, options: { [index: string]: any } = {}, - name?: string + type?: string ) { - super(question, data, options, name || "matrixDropdown"); + super(question, data, options, type || "matrixDropdown"); this.loadingData = false; this._childOptions = Object.assign({}, options); this._childOptions.disableLocaleSwitch = true; @@ -96,13 +96,18 @@ export class VisualizationMatrixDropdown extends VisualizerBase { ); } + protected onThemeChanged(): void { + super.onThemeChanged(); + this._contentVisualizer.theme = this.theme; + } + destroyContent(container: HTMLElement) { this._contentVisualizer.clear(); super.destroyContent(this.contentContainer); } renderContent(container: HTMLElement): void { - this._contentVisualizer.render(container); + this._contentVisualizer.render(container, false); } destroy() { diff --git a/src/visualizationMatrixDynamic.ts b/src/visualizationMatrixDynamic.ts index 19f5d326a..85c4c55c3 100644 --- a/src/visualizationMatrixDynamic.ts +++ b/src/visualizationMatrixDynamic.ts @@ -7,9 +7,9 @@ export class VisualizationMatrixDynamic extends VisualizationPanelDynamic { question: Question, data: Array<{ [index: string]: any }>, options?: Object, - name?: string + type?: string ) { - super(question, data, options, name || "matrixDynamic"); + super(question, data, options, type || "matrixDynamic"); } getQuestions() { diff --git a/src/visualizationPanel.scss b/src/visualizationPanel.scss index 34db49e9d..bc18afbc1 100644 --- a/src/visualizationPanel.scss +++ b/src/visualizationPanel.scss @@ -1,8 +1,42 @@ @use "globals" as *; @use "./utils/utils.scss" as *; -.sa-panel__header { - margin: 0 1em; +.sa-panel__header, +.sa-pivot__header { + display: flex; + flex-direction: column; + + &.sa-toolbar--has-content { + padding: var(--sjs2-spacing-x200, 16px); + border-radius: var(--sjs2-radius-container-panel, 16px); + background: var(--sjs2-color-bg-basic-primary, #FFF); + box-shadow: var(--sjs2-border-offset-x-surface-default, 0) var(--sjs2-border-offset-y-surface-default, 0) var(--sjs2-border-blur-surface-default, 0) var(--sjs2-border-spread-surface-default, 1px) var(--sjs2-color-utility-shadow-surface-default, rgba(17, 16, 20, 0.10)); + gap: var(--sjs2-spacing-x200, 16px); + + } +} + +.sa-panel__header.sa-toolbar--has-content { + margin-inline: var(--sjs2-spacing-x300, 24px); + + @media screen and (max-width: 600px) { + margin-inline: var(--sjs2-spacing-x150, 12px); + } +} + +.sa-panel__header > .sa-toolbar { + min-height: 48px; + gap: var(--sjs2-spacing-x300, 24px); +} + +.sa-panel__content { + padding: var(--sjs2-spacing-x300, 24px); + width: calc(100% - 2 * var(--sjs2-spacing-x300, 24px)); + + @media screen and (max-width: 600px) { + padding: var(--sjs2-spacing-x150, 12px); + width: calc(100% - 2 * var(--sjs2-spacing-x150, 12px)); + } } .sa-grid { @@ -23,85 +57,216 @@ vertical-align: top; box-sizing: border-box; overflow: hidden; - padding: 1em; +} + +.sa-question__content { + padding: 0 var(--sjs2-spacing-x500, 40px) var(--sjs2-spacing-x500, 40px) var(--sjs2-spacing-x500, 40px); + + @media screen and (max-width: 600px) { + padding: var(--sjs2-spacing-x300, 24px) var(--sjs2-spacing-x150, 12px) var(--sjs2-spacing-x150, 12px) var(--sjs2-spacing-x150, 12px); + } } .sa-question-layouted { + overflow: visible; position: absolute; + width: calc(100% - var(--sjs2-spacing-x300, 24px) * 2); + margin-inline-start: var(--sjs2-spacing-x300, 24px); + margin-top: var(--sjs2-spacing-x300, 24px); + border-radius: var(--sjs2-radius-container-panel, 16px); + background: var(--sjs2-color-bg-basic-primary, #FFF); + box-shadow: var(--sjs2-border-offset-x-surface-default, 0) var(--sjs2-border-offset-y-surface-default, 0) var(--sjs2-border-blur-surface-default, 0) var(--sjs2-border-spread-surface-default, 1px) var(--sjs2-color-utility-shadow-surface-default, rgba(17, 16, 20, 0.10)); @media screen and (min-width: 1400px) { - width: calc(50% - 1px); + width: calc(50% - var(--sjs2-spacing-x300, 24px) * 1.5); + } + @media screen and (max-width: 600px) { + margin-inline-start: var(--sjs2-spacing-x150, 12px); + margin-top: var(--sjs2-spacing-x150, 12px); + width: calc(100% - var(--sjs2-spacing-x150, 12px) * 2); } } -.sa-question__content { - background-color: $background-color; - padding: 20px; -} .sa-question__title { - margin-left: 30px; - font-family: $font-family-secondary; - font-size: 18px; - font-weight: bold; - color: $text-color; margin: 0; - margin-bottom: 1em; + padding-bottom: var(--sjs2-spacing-x200, 16px); + color: var(--sjs2-color-fg-basic-primary, #1C1B20); + + /* sjs2/typography/default-strong */ + font-family: $font-family; + font-size: var(--sjs2-typography-font-size-default, 16px); + font-style: normal; + font-weight: 600; + line-height: var(--sjs2-typography-line-height-default, 24px); /* 150% */ + + @media screen and (max-width: 600px) { + padding-inline-end: 40px; + } } -.sa-question__title--draggable { +.sa-question__header--draggable { cursor: move; - &:after { - content: " "; - display: block; - float: right; - width: 15px; - height: 15px; - background-image: url("data:image/svg+xml,%3Csvg version='1.1' xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3E%3Cg%3E%3Cpolygon style='fill: %231ab394' points='13,5 12,6 13,7 9,7 9,3 10,4 11,3 8,0 5,3 6,4 7,3 7,7 3,7 4,6 3,5 0,8 3,11 4,10 3,9 7,9 7,13 6,12 5,13 8,16 11,13 10,12 9,13 9,9 13,9 12,10 13,11 16,8 '/%3E%3C/g%3E%3C/svg%3E "); +} + +.sa-question__drag-area { + display: flex; + flex-direction: column; + justify-content: center; + align-items: center; + min-height: var(--sjs2-spacing-x400, 32px); + + @media screen and (max-width: 600px) { + min-height: 0; } } -[dir="rtl"] .sa-question__title--draggable, [style*="direction: rtl"] .sa-question__title--draggable, [style*="direction:rtl"] .sa-question__title--draggable { - &:after { - float: left; +.sa-question__drag-area-icon { + cursor: move; + display: flex; + padding: var(--sjs2-spacing-x100, 8px); + align-items: center; + + svg { + display: flex; + width: var(--sjs2-size-x300, 24px); + height: var(--sjs2-size-x200, 16px); + flex-direction: column; + align-items: center; + } + + use { + fill: var(--sjs2-color-fg-basic-tertiary, rgba(28, 27, 32, 0.4)); + } +} + +.sa-question__hide-action { + position: absolute; + right: 8px; + top: 8px; + display: flex; + padding: var(--ctr-actionbar-button-padding-top-large-icon, 8px) var(--ctr-actionbar-button-padding-right-large-icon, 8px) var(--ctr-actionbar-button-padding-bottom-large-icon, 8px) var(--ctr-actionbar-button-padding-left-large-icon, 8px); + justify-content: center; + align-items: center; + gap: var(--ctr-actionbar-button-gap, 8px); + border-radius: var(--sjs2-radius-control-action-icon, 8px); + cursor: pointer; + + svg { + width: 24px; + height: 24px; + } + + use { + fill: var(--sjs2-color-fg-basic-tertiary, rgba(28, 27, 32, 0.4)); + } + + &:hover { + border-radius: var(--sjs2-radius-control-action-icon, 8px); + background: var(--sjs2-color-bg-neutral-tertiary-dim, rgba(28, 27, 32, 0.05)); + + use { + fill: var(--sjs2-color-fg-basic-primary-muted, rgba(66, 65, 70, 1)); + } + } + + &:focus-visible { + border-radius: var(--sjs2-radius-control-action-icon, 8px); + outline: var(--sjs2-border-width-a11y, 4px) solid var(--sjs2-color-utility-a11y, rgba(102, 180, 252, 0.60)); + background: var(--sjs2-color-bg-positive-tertiary, rgba(25, 179, 148, 0.00)); + } +} + +.sa-question:not(.sa-question-layouted) { + .sa-question__header { + position: relative; + } + + .sa-question__hide-action { + top: unset; + right: 0px; + bottom: -44px; + + @media screen and (max-width: 600px) { + top: 0; + bottom: unset; + } } } .sa-toolbar { - font-family: $font-family; - font-size: $root-font-size; - color: $text-color; - line-height: 34px; - margin-bottom: 25px; display: flex; flex-direction: row; flex-wrap: wrap; - gap: 10px; + column-gap: var(--sjs2-spacing-static-x100, 8px); + row-gap: var(--sjs2-spacing-static-x150, 12px); + align-items: center; + align-self: stretch; + user-select: none; } -.sa-toolbar.sa-toolbar > * { - display: inline-flex; - line-height: 1em; + +.sa-question__content .sa-toolbar--has-content { + padding-bottom: var(--sjs2-spacing-x200, 16px); } .sa-toolbar__button { - font-family: $font-family; - font-size: $root-font-size; - padding: 8px; - vertical-align: middle; + display: flex; + padding: var(--sjs2-layout-control-action-small-box-vertical, 8px) var(--sjs2-layout-control-action-small-box-horizontal, 8px); + justify-content: center; + align-items: center; + gap: var(--sjs2-layout-control-action-small-box-gap, 0); + border-radius: var(--sjs2-radius-control-action, 8px); + background: var(--sjs2-color-bg-brand-tertiary, rgba(25, 179, 148, 0.00)); cursor: pointer; - border: 1px solid transparent; - white-space: nowrap; - margin: 0 10px; +} - &:hover { - border-color: $border-color; - background-blend-mode: darken; - } - &:first-child { - margin-left: 0; +.sa-toolbar__button:hover { + background: var(--sjs2-color-bg-brand-tertiary-dim, rgba(25, 179, 148, 0.10)); +} + +.sa-toolbar__button:disabled { + opacity: var(--sjs2-opacity-disabled, 0.25); +} + +.sa-toolbar__button:focus-visible { + border-radius: var(--sjs2-radius-control-action, 8px); + outline: var(--sjs2-border-width-a11y, 4px) solid var(--sjs2-color-utility-a11y, rgba(102, 180, 252, 0.60)); + background: var(--sjs2-color-bg-brand-tertiary, rgba(25, 179, 148, 0.00)); +} + +.sa-toolbar__button--disabled, +.sa-toolbar__button--disabled:hover { + opacity: var(--sjs2-opacity-disabled, 0.25); + background: transparent; + cursor: default; + + .sa-toolbar__button-text { + color: var(--sjs2-color-fg-state-common-disabled, rgba(28, 27, 32, 0.40)); } - &:last-child { - margin-right: 0; +} + +.sa-toolbar__button-text { + color: var(--sjs2-color-fg-brand-primary, #19B394); + text-align: center; + padding: var(--sjs2-layout-control-action-small-label-vertical, 0) var(--sjs2-layout-control-action-small-label-horizontal, 8px); + + /* sjs2/typography/default-strong */ + font-family: $font-family; + font-size: var(--sjs2-typography-font-size-default, 16px); + font-style: normal; + font-weight: 600; + line-height: var(--sjs2-typography-line-height-default, 24px); /* 150% */ +} + +.sa-toolbar__button-icon { + display: flex; + width: var(--sjs2-size-x300, 24px); + height: var(--sjs2-size-x300, 24px); + justify-content: center; + align-items: center; + + use { + fill: var(--sjs2-color-project-accent-600, rgba(25, 179, 148, 1)); } } @@ -192,14 +357,45 @@ // EO custom select .sa-question__filter { - display: inline-block; - padding: 0 1em; + display: flex; + width: 100%; + align-items: center; + gap: var(--sjs2-spacing-x050, 4px); + + .sa-toolbar__button-with-icon { + display: flex; + padding: var(--sjs2-layout-control-action-x-small-box-vertical, 4px) var(--sjs2-layout-control-action-x-small-box-horizontal, 4px); + justify-content: center; + align-items: center; + } + + .sa-toolbar__button-icon { + width: var(--sjs2-size-icon-small, 16px); + height: var(--sjs2-size-icon-small, 16px); + padding: var(--sjs2-layout-control-action-x-small-icon-vertical, 4px) var(--sjs2-layout-control-action-x-small-icon-horizontal, 4px); + gap: 0; + + svg { + width: var(--sjs2-size-icon-small, 16px); + height: var(--sjs2-size-icon-small, 16px); + } + } + + .sa-toolbar__button-text { + display: none; + } } .sa-question__filter-text { - vertical-align: middle; - margin-top: 1px; - line-height: 32px; + color: var(--sjs2-color-fg-basic-primary, #1C1B20); + text-align: center; + + /* sjs2/typography/default */ + font-family: var(--sjs2-typography-font-family-default, "Open Sans"); + font-size: var(--sjs2-typography-font-size-default, 16px); + font-style: normal; + font-weight: 400; + line-height: var(--sjs2-typography-line-height-default, 24px); /* 150% */ } /* latin-ext */ diff --git a/src/visualizationPanel.ts b/src/visualizationPanel.ts index a8479ce4f..059ce8163 100644 --- a/src/visualizationPanel.ts +++ b/src/visualizationPanel.ts @@ -1,18 +1,19 @@ import { Event, Question, SurveyModel, surveyLocalization } from "survey-core"; import { IsTouch } from "survey-core"; -import { VisualizerBase } from "./visualizerBase"; +import { ICalculationResult, VisualizerBase } from "./visualizerBase"; import { SelectBase, IVisualizerWithSelection } from "./selectBase"; import { AlternativeVisualizersWrapper } from "./alternativeVizualizersWrapper"; import { DocumentHelper, createCommercialLicenseLink } from "./utils/index"; import { localization } from "./localizationManager"; import { IVisualizerPanelElement, IState, IPermission } from "./config"; import { FilterInfo } from "./filterInfo"; -import { LayoutEngine, MuuriLayoutEngine } from "./layoutEngine"; +import { LayoutEngine } from "./layout-engine"; import { DataProvider } from "./dataProvider"; import { svgTemplate } from "./svgbundle"; import { VisualizationManager } from "./visualizationManager"; -import "./visualizationPanel.scss"; import { VisualizationPanelDynamic } from "./visualizationPanelDynamic"; +import { DateRangeWidget, IDateRange, IDateRangeOptions, IDateRangeWidgetOptions } from "./utils/dateRangeWidget"; +import "./visualizationPanel.scss"; const questionElementClassName = "sa-question"; const questionLayoutedElementClassName = "sa-question-layouted"; @@ -292,8 +293,29 @@ export interface IVisualizationPanelOptions { * [View Demo](https://surveyjs.io/dashboard/examples/interactive-survey-data-dashboard/ (linkStyle)) */ export class VisualizationPanel extends VisualizerBase { + public static LayoutEngine: new (allowed: boolean, itemSelector: string, dragEnabled?: boolean) => LayoutEngine; public visualizers: Array = []; private renderedQuestionsCount: number = 0; + private static counter = 0; + private resetFilterButton: HTMLElement; + private _dateRangeWidget: DateRangeWidget; + + private static getVisualizerName() { + VisualizationPanel.counter++; + return "visualizer" + VisualizationPanel.counter; + } + + private updateResetFilterButtonDisabled() { + if(this.resetFilterButton) { + const buttonDisabledClass = "sa-toolbar__button--disabled"; + if(this.dataProvider.getFilters().length == 0) { + this.resetFilterButton.classList.add(buttonDisabledClass); + } else { + this.resetFilterButton.classList.remove(buttonDisabledClass); + } + } + } + constructor( protected questions: Array, data: Array<{ [index: string]: any }>, @@ -306,13 +328,14 @@ export class VisualizationPanel extends VisualizerBase { this._layoutEngine = options.layoutEngine || - new MuuriLayoutEngine( + VisualizationPanel.LayoutEngine && new VisualizationPanel.LayoutEngine( this.allowDynamicLayout, "." + questionLayoutedElementClassName, this.allowDragDrop ); - this._layoutEngine.onMoveCallback = (order: Array) => - this.reorderVisibleElements(order); + if(!!this._layoutEngine) { + this._layoutEngine.onMoveCallback = (order: Array) => this.reorderVisibleElements(order); + } this.showToolbar = isRoot; if (this.options.survey) { @@ -325,65 +348,48 @@ export class VisualizationPanel extends VisualizerBase { this.buildVisualizers(questions); - if (!this.haveCommercialLicense && this.isRoot) { - this.registerToolbarItem("commercialLicense", () => { - return createCommercialLicenseLink(); - }); - } + this.registerToolbarItem("addElement", (toolbar: HTMLDivElement) => { + if (this.allowHideQuestions) { + const allQuestions = this._elements.map((element) => { + return { + value: element.name, + text: element.displayName, + title: element.displayName, + icon: "check-24x24" + }; + }); + const selectWrapper = DocumentHelper.createActionDropdown( + allQuestions, + (option: any) => this.hiddenElements.length === 0 || this.hiddenElements.filter(el => el.name === option.value).length === 0, + (e: any) => { + if(!!e) { + const element = this.getElement(e); + if(!!element && element.isVisible) { + this.hideElement(e); + } else { + this.showElement(e); + } + return false; + } + }, + localization.getString("allQuestions") + ); + return selectWrapper; + } + return undefined; + }, "dropdown"); this._supportSelection = true; if(this.supportSelection !== false) { this.registerToolbarItem("resetFilter", () => { - return DocumentHelper.createButton(() => { + this.resetFilterButton = DocumentHelper.createButton(() => { this.resetFilter(); }, localization.getString("resetFilter")); - }, 900); + this.updateResetFilterButtonDisabled(); + return this.resetFilterButton; + }, "button", 900); } - this.registerToolbarItem("addElement", (toolbar: HTMLDivElement) => { - if (this.allowHideQuestions) { - let addElementSelector: HTMLElement = undefined; - const addElementSelectorUpdater = ( - panel: VisualizationPanel, - options: any - ) => { - const hiddenElements = this.hiddenElements; - const selectWrapper = DocumentHelper.createSelector( - [ - { - name: undefined, - displayName: localization.getString("addElement"), - }, - ] - .concat(hiddenElements) - .map((element) => { - return { - value: element.name, - text: element.displayName, - }; - }), - (option: any) => false, - (e: any) => { - this.showElement(e.target.value); - } - ); - if(addElementSelector) { - toolbar.replaceChild(selectWrapper, addElementSelector); - } - addElementSelector = selectWrapper; - - if (hiddenElements.length > 0) { - addElementSelector.style.display = undefined; - } else if(addElementSelector) { - addElementSelector.style.display = "none"; - } - }; - addElementSelectorUpdater(this, {}); - this.onVisibleElementsChanged.add(addElementSelectorUpdater); - return addElementSelector; - } - return undefined; - }); if (!this.options.disableLocaleSwitch && this.locales.length > 1) { const localeChoices = this.locales.map((element) => { return { @@ -396,15 +402,25 @@ export class VisualizationPanel extends VisualizerBase { // text: localization.getString("changeLocale"), // }); this.registerToolbarItem("changeLocale", () => { - return DocumentHelper.createSelector(localeChoices, + return DocumentHelper.createDropdown(localeChoices, (option: any) => !!option.value && (this.locale || surveyLocalization.defaultLocale) === option.value, (e: any) => { - var newLocale = e.target.value; + var newLocale = e; this.locale = newLocale; } ); - }); + }, "dropdown"); } + + // if(this.isRoot && !this.theme?.isAxisLabelFontLoaded()) { + // document.fonts.ready.then((fontFaceSet: FontFaceSet) => { + // setTimeout(() => { + // if (this.theme?.isAxisLabelFontLoaded()) { + // this.refresh(); + // } + // }, 100); + // }); + // } } public resetFilter(): void { @@ -417,6 +433,7 @@ export class VisualizationPanel extends VisualizerBase { visualizer.resetFilter(); } }); + this.updateResetFilterButtonDisabled(); } reorderVisibleElements(order: string[]): void { @@ -440,7 +457,7 @@ export class VisualizationPanel extends VisualizerBase { this.renderedQuestionsCount++; if (this.renderedQuestionsCount == this.visibleElements.length) { this.renderedQuestionsCount = 0; - this.layoutEngine.update(); + this.layoutEngine?.update(); this.afterRender(this.contentContainer); } }; @@ -476,7 +493,61 @@ export class VisualizationPanel extends VisualizerBase { this.onAlternativeVisualizerChanged.fire(sender, options); }; + private createHeaderElement(element: IVisualizerPanelRenderedElement) { + const headerElement = DocumentHelper.createElement("div"); + headerElement.className = "sa-question__header"; + + const dragAreaElement = DocumentHelper.createElement("div"); + dragAreaElement.className = "sa-question__drag-area"; + if (this.allowDynamicLayout && this.allowDragDrop) { + dragAreaElement.className = dragAreaElement.className + " sa-question__header--draggable"; + + const svgElement = document.createElement("div"); + svgElement.className = "sa-question__drag-area-icon"; + svgElement.appendChild(DocumentHelper.createSvgElement("draghorizontal-24x16")); + dragAreaElement.appendChild(svgElement); + } + + if (this.allowHideQuestions) { + const hideElement = document.createElement("div"); + hideElement.className = "sa-question__hide-action"; + hideElement.title = localization.getString("hideButton"); + hideElement.setAttribute("role", "button"); + hideElement.setAttribute("tabindex", "0"); + hideElement.appendChild(DocumentHelper.createSvgElement("close-16x16")); + dragAreaElement.appendChild(hideElement); + hideElement.addEventListener("click", (e) => { + setTimeout(() => this.hideElement(element.name), 0); + }); + hideElement.addEventListener("keydown", (e) => { + if (e.key === "Enter" || e.key === " ") { + e.preventDefault(); + this.hideElement(element.name); + } + }); + } + + const titleElement = DocumentHelper.createElement("h3"); + titleElement.innerText = element.displayName; + titleElement.id = "el_" + element.name; + titleElement.className = questionElementClassName + "__title"; + if (this.allowDynamicLayout && this.allowDragDrop) { + titleElement.className = + titleElement.className + + " " + + questionElementClassName + + "__title--draggable"; + } + + headerElement.appendChild(dragAreaElement); + headerElement.appendChild(titleElement); + return headerElement; + } + protected onDataChanged(): void { + if (this._dateRangeWidget) { + this.dataProvider.getCount().then(count => this._dateRangeWidget.updateAnswersCount(count)); + } } protected showElementCore(element: IVisualizerPanelRenderedElement, elementIndex = -1): void { @@ -489,7 +560,7 @@ export class VisualizationPanel extends VisualizerBase { if(elementIndex >= 0) { options = { index: elementIndex }; } - this.layoutEngine.add([questionElement], options); + this.layoutEngine?.add([questionElement], options); } public showElement(elementName: string) { @@ -502,7 +573,7 @@ export class VisualizationPanel extends VisualizerBase { protected hideElementCore(element: IVisualizerPanelRenderedElement) { element.isVisible = false; if (!!element.renderedElement) { - this.layoutEngine.remove([element.renderedElement]); + this.layoutEngine?.remove([element.renderedElement]); this.contentContainer.removeChild(element.renderedElement); element.renderedElement = undefined; } @@ -511,6 +582,10 @@ export class VisualizationPanel extends VisualizerBase { public hideElement(elementName: string) { const element = this.getElement(elementName); this.hideElementCore(element); + const visualizer = this.getVisualizer(elementName); + if(!!visualizer && !!visualizer.getChartAdapter()) { + visualizer.getChartAdapter().destroy(element.renderedElement); + } this.visibleElementsChanged(element, "REMOVED"); } @@ -602,14 +677,6 @@ export class VisualizationPanel extends VisualizerBase { return; } - if (this.allowHideQuestions) { - visualizer.registerToolbarItem("removeQuestion", () => { - return DocumentHelper.createButton(() => { - setTimeout(() => this.hideElement(question.name), 0); - }, localization.getString("hideButton")); - }, 1000); - } - if (this.allowMakeQuestionsPrivate) { visualizer.registerToolbarItem("makePrivatePublic", () => { const element = this.getElement(question.name); @@ -636,7 +703,7 @@ export class VisualizationPanel extends VisualizerBase { doPrivate, state ); - }); + }, "button"); } if (visualizer.supportSelection) { @@ -648,7 +715,7 @@ export class VisualizationPanel extends VisualizerBase { visualizer.registerToolbarItem("questionFilterInfo", () => { filterInfo.update(visualizerWithSelection.selection); return filterInfo.htmlElement; - }, 900); + }, "filter", 900); visualizerWithSelection.onDataItemSelected = ( selectedValue: any, @@ -698,7 +765,8 @@ export class VisualizationPanel extends VisualizerBase { }); this.visualizers.forEach(v => { v.options.seriesLabels = this.options.seriesLabels; - v.locale = newLocale; + v["setLocale"](newLocale); + v.clear(); }); this.stateChanged("locale", newLocale); } @@ -751,6 +819,10 @@ export class VisualizationPanel extends VisualizerBase { protected buildElements(questions: any[]): IVisualizerPanelElement[] { return (questions || []).map((question) => { question = Array.isArray(question) ? question[0] : question; + question = question.question || question; + if(!question.name) { + question.name = VisualizationPanel.getVisualizerName(); + } return { name: question.name, displayName: this.getTitle(question), @@ -933,6 +1005,8 @@ export class VisualizationPanel extends VisualizerBase { this.layout(); } + public onDatePeriodElementShown = new Event<(sender: VisualizationPanel, options: IDateRangeOptions) => any, VisualizationPanel, any>(); + public onPermissionsChangedCallback: any; protected renderPanelElement( @@ -946,42 +1020,61 @@ export class VisualizationPanel extends VisualizerBase { const questionElement = DocumentHelper.createElement("div"); questionElement.dataset.question = element.name; + questionElement.role = "group"; + questionElement.setAttribute("aria-labelledby", "el_" + element.name); !!container && container.appendChild(questionElement); const questionContent = DocumentHelper.createElement("div"); - const titleElement = DocumentHelper.createElement("h3"); const vizualizerElement = DocumentHelper.createElement("div"); - - titleElement.innerText = element.displayName; + const headerElement = this.createHeaderElement(element); questionElement.className = this.allowDynamicLayout ? questionElementClassName + " " + questionLayoutedElementClassName : questionElementClassName; - titleElement.className = questionElementClassName + "__title"; - if (this.allowDynamicLayout && this.allowDragDrop) { - titleElement.className = - titleElement.className + - " " + - questionElementClassName + - "__title--draggable"; - } questionContent.className = questionElementClassName + "__content"; - questionContent.style.backgroundColor = this.backgroundColor; + // questionContent.style.backgroundColor = this.backgroundColor; - questionContent.appendChild(titleElement); + questionContent.appendChild(headerElement); questionContent.appendChild(vizualizerElement); questionElement.appendChild(questionContent); - visualizer.render(vizualizerElement); + visualizer.render(vizualizerElement, false); element.renderedElement = questionElement; return questionElement; } + protected renderBanner(container: HTMLElement): void { + if (!this.haveCommercialLicense && this.isRoot) { + const banner = createCommercialLicenseLink(); + container.appendChild(banner); + } + super.renderBanner(container); + } + protected renderToolbar(container: HTMLElement) { container.className += " sa-panel__header"; super.renderToolbar(container); + + if(this.isRoot && this.options.datePeriodFieldName) { + const divider = DocumentHelper.createElement("div", "sa-horizontal-divider"); + const line = DocumentHelper.createElement("div", "sa-line"); + divider.appendChild(line); + container.appendChild(divider); + + const config = { + setDateRange: (dateRange: IDateRange): void => { + this.dataProvider.setSystemFilter(this.options.datePeriodFieldName, dateRange); + }, + onBeforeRender: (options: IDateRangeOptions) => { + this.onDatePeriodElementShown.fire(this, options); + } + }; + this._dateRangeWidget = new DateRangeWidget(config); + const dateRangeWidgetElement = this._dateRangeWidget.render(); + container.appendChild(dateRangeWidgetElement); + } } public renderContent(container: HTMLElement): void { @@ -991,12 +1084,12 @@ export class VisualizationPanel extends VisualizerBase { let questionElement = this.renderPanelElement(element, container); }); - this.layoutEngine.start(container); + this.layoutEngine?.start(container); // !!window && window.dispatchEvent(new UIEvent("resize")); } protected destroyContent(container: HTMLElement) { - this.layoutEngine.stop(); + this.layoutEngine?.stop(); super.destroyContent(container); } @@ -1012,7 +1105,7 @@ export class VisualizationPanel extends VisualizerBase { } public layout() { - this.layoutEngine.update(); + this.layoutEngine?.update(); } /** @@ -1036,6 +1129,7 @@ export class VisualizationPanel extends VisualizerBase { this.dataProvider.setFilter(this.dataPath, undefined); } } + this.updateResetFilterButtonDisabled(); } public getState(): IState { @@ -1120,8 +1214,18 @@ export class VisualizationPanel extends VisualizerBase { this.onPermissionsChangedCallback(this); } - protected getCalculatedValuesCore(): Array { - return []; + protected getCalculatedValuesCore(): ICalculationResult { + return { + data: [], + values: [] + }; + } + + protected onThemeChanged(): void { + super.onThemeChanged(); + this.visualizers.forEach(v => { + v.theme = this.theme; + }); } destroy() { diff --git a/src/visualizationPanelDynamic.ts b/src/visualizationPanelDynamic.ts index 3737bfab7..1df04cb98 100644 --- a/src/visualizationPanelDynamic.ts +++ b/src/visualizationPanelDynamic.ts @@ -9,9 +9,9 @@ export class VisualizationPanelDynamic extends VisualizerBase { question: Question, data: Array<{ [index: string]: any }>, options: { [index: string]: any } = {}, - name?: string + type?: string ) { - super(question, data, options, name || "panelDynamic"); + super(question, data, options, type || "panelDynamic"); this.loadingData = false; var options = Object.assign({}, options); options.allowHideQuestions = false; @@ -44,13 +44,18 @@ export class VisualizationPanelDynamic extends VisualizerBase { return paneldynamic.template.questions; } + protected onThemeChanged(): void { + super.onThemeChanged(); + this._contentVisualizer.theme = this.theme; + } + destroyContent(container: HTMLElement) { this._contentVisualizer.clear(); super.destroyContent(this.contentContainer); } renderContent(container: HTMLElement): void { - this._contentVisualizer.render(container); + this._contentVisualizer.render(container, false); } public destroy() { diff --git a/src/visualizerBase.scss b/src/visualizerBase.scss index 283ac307d..ddbcab212 100644 --- a/src/visualizerBase.scss +++ b/src/visualizerBase.scss @@ -1,27 +1,35 @@ @use "globals" as *; +.sa-visualizer-wrapper { + min-width: 450px; + padding-top: var(--sjs2-spacing-x300, 24px); + background: var(--sjs2-color-utility-surface-muted, rgba(28, 27, 32, 0.05)); +} + .sa-visualizer__toolbar { } .sa-visualizer__header { - font-family: $font-family-secondary; + font-family: $font-family; font-size: $root-font-size; } .sa-visualizer__content { font-family: $font-family; display: inline-block; - overflow: hidden; width: 100%; } .sa-visualizer__footer { margin-top: 10px; + display: flex; + flex-direction: column; + gap: 8px; } .sa-visualizer__footer-title { display: inline-block; - font-family: $font-family-secondary; + font-family: $font-family; font-size: $root-font-size; color: #404040; line-height: 34px; diff --git a/src/visualizerBase.ts b/src/visualizerBase.ts index 9a2dab49c..01d88ec73 100644 --- a/src/visualizerBase.ts +++ b/src/visualizerBase.ts @@ -1,10 +1,11 @@ -import { Question, QuestionCommentModel, Event, settings, hasLicense } from "survey-core"; +import { Question, QuestionCommentModel, Event, settings, hasLicense, Base } from "survey-core"; import { DataProvider, GetDataFn } from "./dataProvider"; import { VisualizerFactory } from "./visualizerFactory"; import { VisualizationManager } from "./visualizationManager"; import { DocumentHelper, createLoadingIndicator } from "./utils"; import { localization } from "./localizationManager"; import { defaultStatisticsCalculator } from "./statisticCalculators"; +import { DashboardTheme, IDashboardTheme } from "./theme"; import "./visualizerBase.scss"; @@ -15,6 +16,30 @@ export interface IChartAdapter { destroy(node: HTMLElement): void; } +export interface ICalculatedDataInfo { + dataPath?: string; + valueNames: Array; + seriesNames?: Array; + getLabel?(value: string): string; + getSeriesLabel?(series: string): string; +} +export declare type ICalculationResult = { + data: Array>, + values: Array, + series?: Array, +}; + +export interface IAnswersData { + datasets: Array>; + values: Array; + labels: Array; + colors: Array; + texts: Array>; + seriesLabels: Array; + labelsTitle?: string; + valuesTitle?: string; +} + export interface IDataInfo { name: string; // TODO - remove from this interface dataPath?: string; @@ -25,12 +50,14 @@ export interface IDataInfo { getSeriesLabels(): Array; } +type ToolbarItemType = "button" | "dropdown" | "filter"| "license"; + type ToolbarItemCreators = { [name: string]: { creator: (toolbar?: HTMLDivElement) => HTMLElement, - // type: ToolbarItemType, - order: number, - // groupIndex: number, + type: ToolbarItemType, + index: number, + groupIndex: number, }, }; @@ -76,10 +103,12 @@ export class VisualizerBase implements IDataInfo { public static suppressVisualizerStubRendering: boolean = false; public static chartAdapterType: any = undefined; + private _appliedTheme: DashboardTheme; + private _theme = new DashboardTheme(); private _showToolbar = true; private _footerVisualizer: VisualizerBase = undefined; private _dataProvider: DataProvider = undefined; - private _getDataCore: (dataInfo: IDataInfo) => number[][] = undefined + private _getDataCore: (dataInfo: IDataInfo) => ICalculationResult = undefined public labelTruncateLength: number = 27; protected haveCommercialLicense: boolean = false; protected renderResult: HTMLElement = undefined; @@ -212,11 +241,11 @@ export class VisualizerBase implements IDataInfo { * Returns the identifier of a visualized question. */ get name(): string { - return this.question.valueName || this.question.name; + return this.question.name || this.question.valueName; } get dataNames(): Array { - return [this.name]; + return [this.question.valueName || this.question.name]; } get dataPath(): string { @@ -301,6 +330,10 @@ export class VisualizerBase implements IDataInfo { return this.getValues(); } + public getChartAdapter(): IChartAdapter { + return this._chartAdapter; + } + /** * Registers a function used to create a toolbar item for this visualizer. * @@ -348,9 +381,11 @@ export class VisualizerBase implements IDataInfo { public registerToolbarItem( name: string, creator: (toolbar?: HTMLDivElement) => HTMLElement, - order = 100 + type: ToolbarItemType, + index: number = 100, + groupIndex: number = 0 ): void { - this.toolbarItemCreators[name] = { creator, order }; + this.toolbarItemCreators[name] = { creator, type, index, groupIndex }; } /** @@ -390,6 +425,17 @@ export class VisualizerBase implements IDataInfo { return this._type || "visualizer"; } + public get dataType(): string { + if(this.question) { + if(typeof this.question.getType == "function") { + return this.question.getType(); + } else if("dataType" in this.question) { + return this.question["dataType"]; + } + } + return undefined; + } + /** * @deprecated Use [`surveyData`](https://surveyjs.io/dashboard/documentation/api-reference/visualizationpanel#surveyData) instead. */ @@ -468,13 +514,52 @@ export class VisualizerBase implements IDataInfo { } } - protected createToolbarItems(toolbar: HTMLDivElement) { + public getSortedToolbarItemCreators(): Array { const toolbarItemCreators = this.getToolbarItemCreators(); - const sortedItems = Object.keys(toolbarItemCreators || {}) - .map(name => ({ name, ...toolbarItemCreators[name] })) - .sort((a, b) => a.order - b.order); - sortedItems.forEach((item) => { + const groupedItems: { [type: string]: Array<{ name: string, creator: (toolbar?: HTMLDivElement) => HTMLElement, type: ToolbarItemType, index: number, groupIndex: number }> } = {}; + + Object.keys(toolbarItemCreators).forEach((toolbarItemName) => { + const item = toolbarItemCreators[toolbarItemName]; + const type = item.type; + + if (!groupedItems[type]) { + groupedItems[type] = []; + } + + groupedItems[type].push({ + name: toolbarItemName, + ...item + }); + }); + + Object.keys(groupedItems).forEach((type) => { + groupedItems[type].sort((a, b) => { + const indexA = a.index || 0; + const indexB = b.index || 0; + return indexA - indexB; + }); + }); + + const sortedItems: Array<{ name: string, creator: (toolbar?: HTMLDivElement) => HTMLElement, type: ToolbarItemType, index: number, groupIndex: number }> = []; + + const sortedGroups = Object.keys(groupedItems).sort((typeA, typeB) => { + const groupA = groupedItems[typeA][0]?.groupIndex || 0; + const groupB = groupedItems[typeB][0]?.groupIndex || 0; + return groupA - groupB; + }); + + sortedGroups.forEach((type) => { + sortedItems.push(...groupedItems[type]); + }); + + return sortedItems; + } + + protected createToolbarItems(toolbar: HTMLDivElement) { + const toolbarItemCreators = this.getSortedToolbarItemCreators(); + + toolbarItemCreators.forEach((item) => { let toolbarItem = item.creator(toolbar); if (!!toolbarItem) { toolbar.appendChild(toolbarItem); @@ -486,6 +571,8 @@ export class VisualizerBase implements IDataInfo { return !!this.question ? this.question.correctAnswer : ""; } + protected renderBanner(container: HTMLElement) { } + protected destroyToolbar(container: HTMLElement) { container.innerHTML = ""; } @@ -496,7 +583,11 @@ export class VisualizerBase implements IDataInfo { DocumentHelper.createElement("div", "sa-toolbar") ); this.createToolbarItems(toolbar); - container.appendChild(toolbar); + + if(!!toolbar && !!toolbar.innerHTML) { + container.appendChild(toolbar); + container.classList.add("sa-toolbar--has-content"); + } } } @@ -511,8 +602,8 @@ export class VisualizerBase implements IDataInfo { protected destroyContent(container: HTMLElement) { if (!!this.options && typeof this.options.destroyContent === "function") { this.options.destroyContent(container, this); - } else if (this._chartAdapter) { - this._chartAdapter.destroy(container.children[0]); + } else if (this.getChartAdapter()) { + this.getChartAdapter().destroy(container.children[0]); } container.innerHTML = ""; } @@ -600,11 +691,11 @@ export class VisualizerBase implements IDataInfo { const visibilityButton = DocumentHelper.createButton(() => { if (footerContentElement.style.display === "none") { footerContentElement.style.display = "block"; - visibilityButton.innerText = localization.getString("hideButton"); + (visibilityButton as any).setText(localization.getString("hideButton")); this._footerIsCollapsed = false; } else { footerContentElement.style.display = "none"; - visibilityButton.innerText = localization.getString("showButton"); + (visibilityButton as any).setText(localization.getString("showButton")); this._footerIsCollapsed = true; } this.footerVisualizer.invokeOnUpdate(); @@ -613,7 +704,7 @@ export class VisualizerBase implements IDataInfo { container.appendChild(footerContentElement); - this.footerVisualizer.render(footerContentElement); + this.footerVisualizer.render(footerContentElement, false); } } @@ -621,12 +712,24 @@ export class VisualizerBase implements IDataInfo { * Renders the visualizer in a specified container. * @param targetElement An `HTMLElement` or an `id` of a page element in which you want to render the visualizer. */ - render(targetElement: HTMLElement | string) { + render(targetElement: HTMLElement | string, isRoot = true) { if (typeof targetElement === "string") { targetElement = document.getElementById(targetElement); } this.renderResult = targetElement; + if(isRoot && !this._appliedTheme) { + this._appliedTheme = this.theme; + this.onThemeChanged(); + } + if(this._appliedTheme) { + this._appliedTheme.applyThemeToElement(this.renderResult); + } + targetElement.className = "sa-visualizer"; + if (isRoot) { + targetElement.classList.add("sa-visualizer-wrapper"); + } + this.renderBanner(targetElement); this.toolbarContainer = DocumentHelper.createElement( "div", "sa-visualizer__toolbar" @@ -647,6 +750,7 @@ export class VisualizerBase implements IDataInfo { "div", "sa-visualizer__content" ); + this.contentContainer.role = "presentation"; targetElement.appendChild(this.contentContainer); this.renderContent(this.contentContainer); @@ -723,38 +827,72 @@ export class VisualizerBase implements IDataInfo { } getRandomColor() { - const colors = this.getColors(); + const colors = VisualizerBase.getColors(); return colors[Math.floor(Math.random() * colors.length)]; } - private _backgroundColor = "#f7f7f7"; + private _backgroundColor; get backgroundColor() { return this.getBackgroundColorCore(); } set backgroundColor(value) { this.setBackgroundColorCore(value); } protected getBackgroundColorCore() { - return this._backgroundColor; + return this._backgroundColor || this._theme.backgroundColor; } protected setBackgroundColorCore(color: string) { this._backgroundColor = color; if (this.footerVisualizer) this.footerVisualizer.backgroundColor = color; } + protected onThemeChanged(): void { + if (this.footerVisualizer) { + this.footerVisualizer.theme = this.theme; + } + } + + get theme() : DashboardTheme { + return this._theme; + } + set theme(theme: DashboardTheme) { + this._theme = theme; + this._appliedTheme = undefined; + this.onThemeChanged(); + } + + public applyTheme(theme: IDashboardTheme): void { + this.theme.setTheme(theme); + this._appliedTheme = this.theme; + if(this.renderResult) { + this._appliedTheme.applyThemeToElement(this.renderResult); + } + this.onThemeChanged(); + } + static customColors: string[] = []; private static colors = [ - "#86e1fb", - "#3999fb", + "#84CAD4", + "#3a99fb", "#ff6771", - "#1eb496", + "#1db496", "#ffc152", "#aba1ff", - "#7d8da5", - "#4ec46c", - "#cf37a6", - "#4e6198", + "#7d8ca5", + "#4fc46c", + "#e87bcb", + "#4e6198" + // "#86e1fb", + // "#3999fb", + // "#ff6771", + // "#1eb496", + // "#ffc152", + // "#aba1ff", + // "#7d8da5", + // "#4ec46c", + // "#cf37a6", + // "#4e6198", ]; - getColors(count = 10) { + static getColors(count = 10) { const colors = Array.isArray(VisualizerBase.customColors) && VisualizerBase.customColors.length > 0 @@ -795,9 +933,9 @@ export class VisualizerBase implements IDataInfo { return this.getCalculatedValuesCore(); } - private _calculationsCache: Array = undefined; + private _calculationsCache: ICalculationResult = undefined; - protected getCalculatedValuesCore(): Array { + protected getCalculatedValuesCore(): ICalculationResult { if (!!this._getDataCore) { return this._getDataCore(this); } @@ -811,17 +949,33 @@ export class VisualizerBase implements IDataInfo { contentContainer.appendChild(createLoadingIndicator()); } - public convertFromExternalData(externalCalculatedData: any): any[] { + public convertFromExternalData(externalCalculatedData: any): ICalculationResult { return externalCalculatedData; } + /** + * Returns object with all infotmation for data visualization: datasets, labels, colors, additional texts (percentage). + */ + public async getAnswersData(): Promise { + const calculatedValues = await this.getCalculatedValues(); + return { + datasets: calculatedValues.data, + // TODO: remove unused or add missing values + values: calculatedValues.values || this.getValues(), + labels: this.getLabels(), + colors: VisualizerBase.getColors(), + texts: calculatedValues.data, + seriesLabels: calculatedValues.series || this.getSeriesLabels() + }; + } + /** * Returns an array of calculated and visualized values. If a user applies a filter, the array is also filtered. * * To get an array of source survey results, use the [`surveyData`](https://surveyjs.io/dashboard/documentation/api-reference/visualizerbase#surveyData) property. */ - public getCalculatedValues(): Promise> { - return new Promise>((resolve, reject) => { + public getCalculatedValues(): Promise { + return new Promise((resolve, reject) => { if(this._calculationsCache !== undefined) { resolve(this._calculationsCache); } diff --git a/src/visualizerDescription.ts b/src/visualizerDescription.ts new file mode 100644 index 000000000..9c401a013 --- /dev/null +++ b/src/visualizerDescription.ts @@ -0,0 +1,11 @@ +import { Question } from "survey-core"; + +export interface IVisualizerDescription { + visualizerType: string; + chartType?: string; + question?: Question; + questionName?: string; + dataName?: string; + displayValueName?: string; + title?: string; +} \ No newline at end of file diff --git a/src/visualizerFactory.ts b/src/visualizerFactory.ts index 39488b819..072950fb1 100644 --- a/src/visualizerFactory.ts +++ b/src/visualizerFactory.ts @@ -1,6 +1,7 @@ import { Question, QuestionCompositeModel, QuestionCustomModel } from "survey-core"; import { VisualizerBase } from "./visualizerBase"; import { VisualizationManager } from "./visualizationManager"; +import { IVisualizerDescription } from "./visualizerDescription"; /** * An object that allows you to create individual visualizers without creating a [visualization panel](https://surveyjs.io/dashboard/documentation/api-reference/visualizationpanel). @@ -22,20 +23,48 @@ export class VisualizerFactory { * ``` * * If a question has more than one [registered](https://surveyjs.io/dashboard/documentation/api-reference/visualizationmanager#registerVisualizer) visualizer, users can switch between them using a drop-down menu. - * @param question A question for which to create a visualizer. + * @param description A question for which to create a visualizer. * @param data A data array with survey results to be visualized. * @param options An object with any custom properties you need within the visualizer. */ public static createVisualizer( - question: Question, + description: Question | IVisualizerDescription, data: Array<{ [index: string]: any }>, options?: { [index: string]: any } ): VisualizerBase { - let type = question.getType(); + let type: string; + let question: Question; let creators = []; - let questionForCreator: Question | Question[] = question; let optionsForCreator = Object.assign({}, options); + if("visualizerType" in description) { + type = description.visualizerType; + + if(!!description.chartType) { + optionsForCreator[description["name"]] = { + chartType: description.chartType, + allowChangeVisualizerType: false + }; + } + + question = description.question || { + name: description["name"], + valueName: description.dataName || description.questionName, + title: description.title, + displayValueName: description.displayValueName, + waitForQuestionIsReady: () => { + return new Promise((resolve) => resolve()); + } + }; + } else { + question = description; + if(description.displayValueName !== undefined) { + question.displayValueName = description.displayValueName; + } + type = question.getType(); + } + + let questionForCreator: Question | Question[] = question; if (type === "text" && (question).inputType) { creators = VisualizationManager.getVisualizersByType((question).inputType, type); } else { diff --git a/src/wordcloud/wordcloud.ts b/src/wordcloud/wordcloud.ts index 840b4fa29..a6ffe612e 100644 --- a/src/wordcloud/wordcloud.ts +++ b/src/wordcloud/wordcloud.ts @@ -1,5 +1,5 @@ import { Question, Event } from "survey-core"; -import { VisualizerBase } from "../visualizerBase"; +import { ICalculationResult, VisualizerBase } from "../visualizerBase"; import { VisualizationManager } from "../visualizationManager"; import { textHelper } from "./stopwords/index"; import { DocumentHelper } from "../utils"; @@ -27,11 +27,10 @@ export class WordCloudAdapter { } public async create(element: HTMLElement): Promise { - const data = await this.model.getCalculatedValues(); - const colors = this.model.getColors(); + const answersData = await this.model.getAnswersData(); - if (data.length === 0) { - const emptyTextNode = DocumentHelper.createElement("p", "", { + if (answersData.datasets.length === 0 || answersData.datasets[0].length === 0) { + var emptyTextNode = DocumentHelper.createElement("p", "", { innerText: localization.getString("noResults"), }); element.appendChild(emptyTextNode); @@ -44,8 +43,8 @@ export class WordCloudAdapter { }; WordCloudAdapter.onWordcloudCreating.fire(this.model, options); this._wordcloud = new WordCloudWidget(config); - this._wordcloud.colors = this.model.getColors(); - this._wordcloud.words = data; + this._wordcloud.colors = VisualizerBase.getColors(); + this._wordcloud.words = answersData.values.map((w, i) => [w, answersData.datasets[0][i]]); this._wordcloud.render(element); return this._wordcloud; } @@ -59,26 +58,32 @@ export class WordCloudAdapter { } export class WordCloud extends VisualizerBase { private _wordcloudAdapter: WordCloudAdapter; + private _values = []; constructor( question: Question, data: Array<{ [index: string]: any }>, options?: Object, - name?: string + type?: string ) { - super(question, data, options, name || "wordcloud"); + super(question, data, options, type || "wordcloud"); this._wordcloudAdapter = new WordCloudAdapter(this); } - public convertFromExternalData(externalCalculatedData: any): any[] { - const innerCalculatedData = []; - Object.keys(externalCalculatedData || []).forEach(word => { - innerCalculatedData.push([word, externalCalculatedData[word]]); - }); - return innerCalculatedData; + public convertFromExternalData(externalCalculatedData: any): ICalculationResult { + this._values = Object.keys(externalCalculatedData || {}); + + return { + data: [this._values.map(w => externalCalculatedData[w])], + values: this._values + }; } - protected getCalculatedValuesCore(): Array { + public getValues(): Array { + return this._values; + } + + protected getCalculatedValuesCore(): ICalculationResult { let result: { [key: string]: number } = {}; let stopWords: string[] = []; @@ -133,9 +138,11 @@ export class WordCloud extends VisualizerBase { } }); - return Object.keys(result).map((key) => { - return [key, result[key]]; - }); + this._values = Object.keys(result); + return { + data: [this._values.map(w => result[w])], + values: this._values + }; } protected destroyContent(container: HTMLElement) { diff --git a/tests/boolean.test.ts b/tests/boolean.test.ts index 460e0d8b0..3329c2457 100644 --- a/tests/boolean.test.ts +++ b/tests/boolean.test.ts @@ -34,7 +34,7 @@ test("getLabels method", () => { }); test("getCalculatedValues method", async () => { - expect(await boolean.getCalculatedValues()).toEqual([[3, 1]]); + expect((await boolean.getCalculatedValues()).data).toEqual([[3, 1]]); }); test("getCalculatedValues localized", async () => { @@ -60,7 +60,7 @@ test("getCalculatedValues localized", async () => { var secondResult = { "bool": false, "organization_type": "In-house" }; var test = [firstResult, secondResult]; boolean = new BooleanModel(survey.getQuestionByName("bool"), test); - expect(await boolean.getCalculatedValues()).toEqual([[1, 1]]); + expect((await boolean.getCalculatedValues()).data).toEqual([[1, 1]]); }); test("hasHeader and correct answer text", () => { @@ -92,6 +92,6 @@ test("convertFromExternalData", () => { false: 1 }; const calculatedData = (boolean as any).getCalculatedValuesCore(); - expect(calculatedData).toEqual([[3, 1]]); + expect(calculatedData.data).toEqual([[3, 1]]); expect(boolean.convertFromExternalData(externalCalculatedData)).toStrictEqual(calculatedData); }); diff --git a/tests/card.test.ts b/tests/card.test.ts new file mode 100644 index 000000000..98a431a8b --- /dev/null +++ b/tests/card.test.ts @@ -0,0 +1,17 @@ +import { VisualizationPanel } from "../src/visualizationPanel"; +export * from "../src/card"; + +test("Create visualizer by visualizerType", async () => { + const visualizerDefinition = { + visualizerType: "card", + dataName: "test", + displayValueName: "count", + title: "Total answers count" + }; + + const data = [{ test: 1 }, { test: 10 }, { test: 8 }, { test: 7 }, { test: 9 }, { test: 9 }, {}]; + let visPanel = new VisualizationPanel([visualizerDefinition], data, {}); + + expect(visPanel.visualizers.length).toEqual(1); + expect(visPanel.visualizers[0].type).toEqual(visualizerDefinition.visualizerType); +}); \ No newline at end of file diff --git a/tests/dataProvider.test.ts b/tests/dataProvider.test.ts index 7d5a44423..887fbc7b3 100644 --- a/tests/dataProvider.test.ts +++ b/tests/dataProvider.test.ts @@ -54,12 +54,12 @@ test("ctor/setFilter/reset/onDataChanged", () => { expect(callCount).toEqual(1); expect(dataProvider.data).toEqual(testData); - expect(defaultStatisticsCalculator(dataProvider.filteredData, q1testDataInfo)).toEqual([[2, 2, 0, 0]]); + expect(defaultStatisticsCalculator(dataProvider.filteredData, q1testDataInfo).data).toEqual([[2, 2, 0, 0]]); expect(callCount).toEqual(1); dataProvider.setFilter("q2", "item1"); expect(callCount).toEqual(2); - expect(defaultStatisticsCalculator(dataProvider.filteredData, q1testDataInfo)).toEqual([[1, 1, 0, 0]]); + expect(defaultStatisticsCalculator(dataProvider.filteredData, q1testDataInfo).data).toEqual([[1, 1, 0, 0]]); expect(callCount).toEqual(2); dataProvider.raiseDataChanged(); @@ -67,12 +67,12 @@ test("ctor/setFilter/reset/onDataChanged", () => { dataProvider.setFilter("q2", undefined); expect(callCount).toEqual(4); - expect(defaultStatisticsCalculator(dataProvider.filteredData, q1testDataInfo)).toEqual([[2, 2, 0, 0]]); + expect(defaultStatisticsCalculator(dataProvider.filteredData, q1testDataInfo).data).toEqual([[2, 2, 0, 0]]); expect(callCount).toEqual(4); dataProvider.setFilter("q3", "item2"); expect(callCount).toEqual(5); - expect(defaultStatisticsCalculator(dataProvider.filteredData, q1testDataInfo)).toEqual([[0, 1, 0, 0]]); + expect(defaultStatisticsCalculator(dataProvider.filteredData, q1testDataInfo).data).toEqual([[0, 1, 0, 0]]); expect(callCount).toEqual(5); }); @@ -103,7 +103,7 @@ test("getData for boolean question values - mock", () => { getLabels: () => ["true", "false"], getSeriesValues: () => [], getSeriesLabels: () => [], - }) + }).data ).toEqual([[3, 1]]); }); @@ -132,7 +132,7 @@ test("getData for select base question values", () => { getLabels: () => choices, getSeriesValues: () => [], getSeriesLabels: () => [], - }) + }).data ).toEqual([[2, 1, 0, 1, 0, 0]]); }); @@ -171,7 +171,7 @@ test("getData for matrix question values", () => { ], getSeriesValues: () => ["Lizol", "Harpic"], getSeriesLabels: () => ["Lizol", "Harpic"], - }) + }).data ).toEqual([ [1, 2, 0, 0, 0, 0], [1, 1, 1, 0, 0, 0], @@ -196,7 +196,7 @@ test("getData for matrix dropdown question values - pre-processed data", () => { getLabels: () => ["High Quality", "Natural", "Trustworthy"], getSeriesValues: () => ["Lizol", "Harpic"], getSeriesLabels: () => ["Lizol", "Harpic"], - }) + }).data ).toEqual([ [0, 2, 1], [1, 1, 1], @@ -209,7 +209,7 @@ test("getData for matrix dropdown question values - pre-processed data", () => { getLabels: () => ["1", "2", "3", "4", "5"], getSeriesValues: () => ["Lizol", "Harpic"], getSeriesLabels: () => ["Lizol", "Harpic"], - }) + }).data ).toEqual([ [1, 0, 2, 0, 0], [0, 0, 0, 2, 1], @@ -273,26 +273,26 @@ test("getData for matrix dropdown inner visualizers", async () => { expect(innerPanelVisualizer.dataPath).toBe("question2"); const column1Visualizer = innerPanelVisualizer["visualizers"][0]; expect(column1Visualizer.dataPath).toBe("question2"); - expect(await column1Visualizer.getCalculatedValues()).toEqual([ + expect((await column1Visualizer.getCalculatedValues()).data).toEqual([ [0, 2, 1].reverse(), [1, 1, 1].reverse(), ]); const column2Visualizer = innerPanelVisualizer["visualizers"][1]; expect(column2Visualizer.dataPath).toBe("question2"); - expect(await column2Visualizer.getCalculatedValues()).toEqual([ + expect((await column2Visualizer.getCalculatedValues()).data).toEqual([ [1, 0, 2, 0, 0].reverse(), [0, 0, 0, 2, 1].reverse(), ]); const dataProvider = new DataProvider(innerPanelVisualizer["data"]); expect( - defaultStatisticsCalculator(dataProvider.filteredData, innerPanelVisualizer["visualizers"][0]) + defaultStatisticsCalculator(dataProvider.filteredData, innerPanelVisualizer["visualizers"][0]).data ).toEqual([ [0, 2, 1].reverse(), [1, 1, 1].reverse(), ]); expect( - defaultStatisticsCalculator(dataProvider.filteredData, innerPanelVisualizer["visualizers"][1]) + defaultStatisticsCalculator(dataProvider.filteredData, innerPanelVisualizer["visualizers"][1]).data ).toEqual([ [1, 0, 2, 0, 0].reverse(), [0, 0, 0, 2, 1].reverse(), @@ -332,7 +332,7 @@ test("getData for matrix dropdown grouped", () => { getLabels: () => choices, getSeriesValues: () => rows, getSeriesLabels: () => rows, - }) + }).data ).toEqual([ [[1, 1, 1, 0, 0, 0]], [[1, 1, 1, 0, 0, 0]], @@ -379,7 +379,7 @@ test("filter data by matrix value", () => { { "Quality": { "affordable": "3", "better then others": "2", "does what it claims": "4", "easy to use": "3" }, "developer_count": "> 10", "organization_type": "Consulting" } ]); expect( - defaultStatisticsCalculator(dataProvider.filteredData, dataInfo) + defaultStatisticsCalculator(dataProvider.filteredData, dataInfo).data ).toEqual([ [1, 1, 0], ]); @@ -389,7 +389,7 @@ test("filter data by matrix value", () => { { "Quality": { "affordable": "1", "better then others": "1", "does what it claims": "1", "easy to use": "1" }, "developer_count": "3-5", "organization_type": "Custom" }, ]); expect( - defaultStatisticsCalculator(dataProvider.filteredData, dataInfo) + defaultStatisticsCalculator(dataProvider.filteredData, dataInfo).data ).toEqual([ [1, 0, 0], ]); @@ -400,7 +400,7 @@ test("filter data by matrix value", () => { { "Quality": { "affordable": "3", "better then others": "2", "does what it claims": "4", "easy to use": "3" }, "developer_count": "> 10", "organization_type": "Consulting" } ]); expect( - defaultStatisticsCalculator(dataProvider.filteredData, dataInfo) + defaultStatisticsCalculator(dataProvider.filteredData, dataInfo).data ).toEqual([ [1, 1, 0], ]); @@ -410,7 +410,7 @@ test("filter data by matrix value", () => { { "Quality": { "affordable": "3", "better then others": "2", "does what it claims": "4", "easy to use": "3" }, "developer_count": "> 10", "organization_type": "Consulting" } ]); expect( - defaultStatisticsCalculator(dataProvider.filteredData, dataInfo) + defaultStatisticsCalculator(dataProvider.filteredData, dataInfo).data ).toEqual([ [0, 1, 0], ]); @@ -455,7 +455,7 @@ test("filter data by matrix value - number and string", () => { { "Quality": { "affordable": "3", "better then others": "2", "does what it claims": "4", "easy to use": "3" }, "developer_count": "> 10", "organization_type": "Consulting" } ]); expect( - defaultStatisticsCalculator(dataProvider.filteredData, dataInfo) + defaultStatisticsCalculator(dataProvider.filteredData, dataInfo).data ).toEqual([ [1, 1, 0], ]); @@ -465,7 +465,7 @@ test("filter data by matrix value - number and string", () => { { "Quality": { "affordable": "3", "better then others": "2", "does what it claims": "4", "easy to use": "3" }, "developer_count": "> 10", "organization_type": "Consulting" } ]); expect( - defaultStatisticsCalculator(dataProvider.filteredData, dataInfo) + defaultStatisticsCalculator(dataProvider.filteredData, dataInfo).data ).toEqual([ [0, 1, 0], ]); @@ -491,7 +491,7 @@ test("filter data for matrix dropdown question column values - pre-processed dat getLabels: () => ["High Quality", "Natural", "Trustworthy"], getSeriesValues: () => ["Lizol", "Harpic"], getSeriesLabels: () => ["Lizol", "Harpic"], - }) + }).data ).toEqual([ [0, 2, 0], [0, 0, 0], @@ -504,7 +504,7 @@ test("filter data for matrix dropdown question column values - pre-processed dat getLabels: () => ["1", "2", "3", "4", "5"], getSeriesValues: () => ["Lizol", "Harpic"], getSeriesLabels: () => ["Lizol", "Harpic"], - }) + }).data ).toEqual([ [1, 0, 1, 0, 0], [0, 0, 0, 0, 0], @@ -577,7 +577,7 @@ test("getData for boolean question values + missing answers", () => { getLabels: () => ["true", "false", "missing"], getSeriesValues: () => [], getSeriesLabels: () => [], - }) + }).data ).toEqual([[3, 1, 2]]); }); @@ -609,7 +609,7 @@ test("getData for select base question values + missing answers", () => { getLabels: () => choices.concat(["missing"]), getSeriesValues: () => [], getSeriesLabels: () => [], - }) + }).data ).toEqual([[2, 1, 0, 1, 0, 0, 1]]); }); @@ -641,7 +641,7 @@ test("getData for select base question values with showCommentArea choices", () getLabels: () => choices.concat(["missing"]), getSeriesValues: () => [], getSeriesLabels: () => [], - }); + }).data; expect(result).toEqual([[1, 1, 1, 0, 0, 0, 0]]); }); @@ -664,7 +664,7 @@ test("getData for matrix & cellType is checkbox", () => { getLabels: () => ["1", "2", "3", "4", "5"], getSeriesValues: () => ["row1", "row2", "row3", "row4"], getSeriesLabels: () => ["row1", "row2", "row3", "row4"], - }); + }).data; expect(result[0]).toEqual([0, 1, 1, 1, 1]); expect(result[1]).toEqual([0, 0, 1, 1, 1]); expect(result[2]).toEqual([0, 0, 0, 1, 1]); @@ -704,3 +704,98 @@ test("fixDropdownData - matrixdropdown question - shouldn't change data twice", dataProvider.fixDropdownData(["question2"]); expect(dataProvider.data).toStrictEqual(expectedFixedData); }); + +test("system filter by date range", () => { + const data = [ + { date: "2021-10-13", age: 17 }, + { date: "2021-10-14", age: 17 }, + { date: "2021-10-15", age: 17 }, + { date: "2011-10-16", age: 30 }, + { date: "2011-10-16", age: 35 }, + { date: "2004-10-17", age: 40 }, + { date: "2004-10-17", age: 45 }, + { date: "2016-10-18", age: 25 }, + ]; + const dataProvider = new DataProvider(data); + + dataProvider.setSystemFilter("date", { start: Date.parse("2011-10-16"), end: Date.parse("2011-10-17") }); + + expect( + dataProvider.filteredData + ).toEqual([ + { date: "2011-10-16", age: 30 }, + { date: "2011-10-16", age: 35 }, + ]); + expect( + dataProvider.getFilters() + ).toEqual([{ "field": "date", "type": "=", "value": { "end": 1318809600000, "start": 1318723200000 } }]); + + dataProvider.setFilter("age", { start: 33, end: 37 }); + expect( + dataProvider.filteredData + ).toEqual([ + { date: "2011-10-16", age: 35 }, + ]); + expect( + dataProvider.getFilters() + ).toEqual([{ "field": "date", "type": "=", "value": { "end": 1318809600000, "start": 1318723200000 } }, { "field": "age", "type": "=", "value": { "end": 37, "start": 33 } }]); + + dataProvider.resetFilter(); + expect( + dataProvider.filteredData + ).toEqual([ + { date: "2011-10-16", age: 30 }, + { date: "2011-10-16", age: 35 }, + ]); + expect( + dataProvider.getFilters() + ).toEqual([{ "field": "date", "type": "=", "value": { "end": 1318809600000, "start": 1318723200000 } }]); + + dataProvider.resetSystemFilter(); + expect( + dataProvider.filteredData + ).toEqual(data); + expect( + dataProvider.getFilters() + ).toEqual([]); +}); + +test("filter by partially defined date range", () => { + const data = [ + { date: "2011-10-13", age: 17 }, + { date: "2011-10-14", age: 17 }, + { date: "2011-10-15", age: 17 }, + { date: "2011-10-16", age: 30 }, + { date: "2011-10-16", age: 35 }, + { date: "2011-10-17", age: 40 }, + { date: "2011-10-17", age: 45 }, + { date: "2011-10-18", age: 25 }, + ]; + const dataProvider = new DataProvider(data); + + dataProvider.setSystemFilter("date", { start: Date.parse("2011-10-16"), end: undefined }); + expect( + dataProvider.filteredData + ).toEqual([ + { date: "2011-10-16", age: 30 }, + { date: "2011-10-16", age: 35 }, + { date: "2011-10-17", age: 40 }, + { date: "2011-10-17", age: 45 }, + { date: "2011-10-18", age: 25 }, + ]); + + dataProvider.setSystemFilter("date", { start: undefined, end: Date.parse("2011-10-16") }); + expect( + dataProvider.filteredData + ).toEqual([ + { date: "2011-10-13", age: 17 }, + { date: "2011-10-14", age: 17 }, + { date: "2011-10-15", age: 17 }, + ]); + + dataProvider.setSystemFilter("date", { start: undefined, end: undefined }); + expect( + dataProvider.filteredData + ).toEqual(data); +}); + diff --git a/tests/histogram.test.ts b/tests/histogram.test.ts index 776a279a0..fe7610226 100644 --- a/tests/histogram.test.ts +++ b/tests/histogram.test.ts @@ -52,7 +52,7 @@ test("number default histogram", async () => { expect(number["valueType"]).toBe("number"); expect(histValues).toMatchObject([17, 19.3, 21.6, 23.9, 26.2, 28.5, 30.8, 33.1, 35.4, 37.7]); expect(histLabels).toMatchObject(["17-19.3", "19.3-21.6", "21.6-23.9", "23.9-26.2", "26.2-28.5", "28.5-30.8", "30.8-33.1", "33.1-35.4", "35.4-37.7", "37.7-40"]); - expect(histData).toMatchObject([[3, 0, 0, 1, 0, 2, 0, 0, 0, 2]]); + expect(histData.data).toMatchObject([[3, 0, 0, 1, 0, 2, 0, 0, 0, 2]]); expect(number["isSupportMissingAnswers"]()).toBeFalsy(); expect(number["isSupportAnswersOrder"]()).toBeTruthy(); @@ -86,7 +86,7 @@ test("date default histogram", async () => { "5/20/2018-1/31/2020", "1/31/2020-10/13/2021", ]); - expect(histData).toMatchObject([[2, 0, 0, 0, 2, 0, 0, 1, 0, 3]]); + expect(histData.data).toMatchObject([[2, 0, 0, 0, 2, 0, 0, 1, 0, 3]]); expect(date["isSupportMissingAnswers"]()).toBeFalsy(); }); @@ -139,7 +139,7 @@ test("date default intervals", async () => { "1/25/2020-1/28/2020", "1/28/2020-1/31/2020", ]); - expect(histData).toMatchObject([[3, 3, 3, 3, 3, 3, 3, 3, 3, 4]]); + expect(histData.data).toMatchObject([[3, 3, 3, 3, 3, 3, 3, 3, 3, 4]]); }); test("date empty data", async () => { @@ -158,7 +158,7 @@ test("date empty data", async () => { expect(histIntervals.length).toBe(0); expect(histValues).toMatchObject([]); - expect(histData).toMatchObject([[]]); + expect(histData.data).toMatchObject([[]]); }); test("number custom intervals", async () => { @@ -221,7 +221,7 @@ test("number custom intervals", async () => { 19, 70 ]); - expect(histData).toMatchObject([[ + expect(histData.data).toMatchObject([[ 12, 11, 5, @@ -261,7 +261,7 @@ test("number custom intervals for small result sets", async () => { 19, 70 ]); - expect(histData).toMatchObject([[0, 0, 3, 5, 0]]); + expect(histData.data).toMatchObject([[0, 0, 3, 5, 0]]); }); test("histogram series default algorithm data", async () => { @@ -309,7 +309,7 @@ test("histogram series default algorithm data", async () => { expect(number.getSeriesLabels()).toMatchObject(series); const chartData = await number.getCalculatedValues(); - expect(chartData).toMatchObject([ + expect(chartData.data).toMatchObject([ [1, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 1, 0, 0, 0, 0, 0, 0, 0], [1, 0, 0, 0, 0, 0, 0, 0, 0, 0], @@ -398,7 +398,7 @@ test("histogram series intervals data", async () => { }); const chartData = await number.getCalculatedValues(); - expect(chartData).toMatchObject([ + expect(chartData.data).toMatchObject([ [1, 0, 0, 1, 0, 0, 1, 0, 0, 0], [1, 0, 0, 0, 1, 0, 0, 1, 0, 0], [1, 0, 0, 0, 1, 0, 0, 0, 1, 0], @@ -476,7 +476,7 @@ test("histogram should use rate values", async () => { ]); expect(rating.getValues()).toEqual([1, 2, 3]); expect(rating.getLabels()).toEqual(["15 minutes", "30 minutes", "1 hour"]); - expect(await rating.getCalculatedValues()).toEqual([[0, 0, 1]]); + expect((await rating.getCalculatedValues()).data).toEqual([[0, 0, 1]]); }); test("histogram intervals alignment and rounding", () => { @@ -690,7 +690,7 @@ test("number histogram answers order", async () => { expect(histLabels).toMatchObject(["11.14-14.43", "14.43-17.71", "17.71-21", "21-24.29", "24.29-27.57", "27.57-30.86", "30.86-34.14", "34.14-37.43", "37.43-40.71", "40.71-44"]); const histData = await number.getCalculatedValues(); - expect(histData).toMatchObject([[5, 3, 0, 0, 0, 0, 1, 0, 0, 1]]); + expect(histData.data).toMatchObject([[5, 3, 0, 0, 0, 0, 1, 0, 0, 1]]); }); test("convertFromExternalData", () => { @@ -704,7 +704,7 @@ test("convertFromExternalData", () => { const externalCalculatedData = [3, 0, 0, 1, 0, 2, 0, 0, 0, 2]; const calculatedData = (histogram as any).getCalculatedValuesCore(); - expect(calculatedData).toEqual([[3, 0, 0, 1, 0, 2, 0, 0, 0, 2]]); + expect(calculatedData.data).toEqual([[3, 0, 0, 1, 0, 2, 0, 0, 0, 2]]); expect(histogram.convertFromExternalData(externalCalculatedData)).toStrictEqual(calculatedData); }); @@ -746,28 +746,18 @@ test("rating with rateValues with wrong order", () => { } ], }; - const retingData = [ - { - "q1": 5 - }, - { - "q1": 4 - }, - { - "q1": 2, - }, - { - "q1": 7, - }, - { - "q1": 3, - } + const ratingData = [ + { "q1": 5 }, + { "q1": 4 }, + { "q1": 2 }, + { "q1": 7 }, + { "q1": 3 } ]; - const histogram = new HistogramModel(question, retingData); + const histogram = new HistogramModel(question, ratingData); const externalCalculatedData = [0, 1, 1, 1, 1, 0, 1]; const calculatedData = (histogram as any).getCalculatedValuesCore(); - expect(calculatedData).toEqual([externalCalculatedData]); + expect(calculatedData.data).toEqual([externalCalculatedData]); expect(histogram.convertFromExternalData(externalCalculatedData)).toStrictEqual(calculatedData); }); @@ -812,7 +802,7 @@ test("getCalculatedValues", async () => { }); const chartData = await number.getCalculatedValues(); - expect(chartData).toMatchObject([ + expect(chartData.data).toMatchObject([ [1, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 1, 0, 0, 0, 0, 0, 0, 0], [1, 0, 0, 0, 0, 0, 0, 0, 0, 0], @@ -862,7 +852,7 @@ test("getCalculatedValues - 2 rows", async () => { }); const chartData = await number.getCalculatedValues(); - expect(chartData).toMatchObject([ + expect(chartData.data).toMatchObject([ [2, 0, 0, 0, 0, 0, 0, 0, 0, 1], [0, 0, 1, 0, 0, 0, 0, 1, 0, 0], ]); @@ -1095,7 +1085,7 @@ test("histogram date different intervals", async () => { date.intervalsMode = "years"; expect(date.intervalsMode).toBe("years"); expect(date.getLabels()).toEqual(["2009"]); - expect(((await date.getCalculatedValues())[0] as any).length).toEqual(1); + expect(((await date.getCalculatedValues()).data[0] as any).length).toEqual(1); date.intervalsMode = "quarters"; expect(date.intervalsMode).toBe("quarters"); @@ -1105,7 +1095,7 @@ test("histogram date different intervals", async () => { "III 2009", "IV 2009", ]); - expect(((await date.getCalculatedValues())[0] as any).length).toEqual(4); + expect(((await date.getCalculatedValues()).data[0] as any).length).toEqual(4); date.intervalsMode = "months"; expect(date.intervalsMode).toBe("months"); @@ -1123,7 +1113,7 @@ test("histogram date different intervals", async () => { "Nov 2009", "Dec 2009", ]); - expect(((await date.getCalculatedValues())[0] as any).length).toEqual(12); + expect(((await date.getCalculatedValues()).data[0] as any).length).toEqual(12); date.intervalsMode = "quarters"; expect(date.intervalsMode).toBe("quarters"); @@ -1133,7 +1123,7 @@ test("histogram date different intervals", async () => { "III 2009", "IV 2009", ]); - expect(((await date.getCalculatedValues())[0] as any).length).toEqual(4); + expect(((await date.getCalculatedValues()).data[0] as any).length).toEqual(4); }); test("getBestIntervalMode for date histogram", () => { @@ -1275,7 +1265,7 @@ test("histogram date auto intervals mode", async () => { "2008", "2009", ]); - expect(((await date.getCalculatedValues())[0] as any).length).toEqual(6); + expect(((await date.getCalculatedValues()).data[0] as any).length).toEqual(6); }); test("changeIntervalsMode and allowRunningTotals toolbar items for date histogram", () => { @@ -1310,12 +1300,12 @@ test("allowRunningTotals and showRunningTotals for date histogram", async () => date.intervalsMode = "default" as any; expect(date.allowChangeIntervals).toBeTruthy(); expect(date.showRunningTotals).toBeFalsy(); - expect(((await date.getCalculatedValues())[0] as any).length).toEqual(10); - expect((await date.getCalculatedValues())[0]).toEqual([2, 0, 0, 0, 2, 0, 0, 1, 0, 3]); + expect(((await date.getCalculatedValues()).data[0] as any).length).toEqual(10); + expect((await date.getCalculatedValues()).data[0]).toEqual([2, 0, 0, 0, 2, 0, 0, 1, 0, 3]); date.showRunningTotals = true; - expect(((await date.getCalculatedValues())[0] as any).length).toEqual(10); - expect((await date.getCalculatedValues())[0]).toEqual([2, 2, 2, 2, 4, 4, 4, 5, 5, 8]); + expect(((await date.getCalculatedValues()).data[0] as any).length).toEqual(10); + expect((await date.getCalculatedValues()).data[0]).toEqual([2, 2, 2, 2, 4, 4, 4, 5, 5, 8]); }); test("getAnswersData with showGrouped set to true", async () => { @@ -1477,20 +1467,20 @@ test("aggregateDataNames for date histogram", async () => { expect(date.allowChangeIntervals).toBeTruthy(); expect(date.showRunningTotals).toBeFalsy(); expect(date.aggregateDataName).toBe(""); - expect(((await date.getCalculatedValues())[0] as any).length).toEqual(10); - expect((await date.getCalculatedValues())[0]).toEqual([2, 0, 0, 0, 2, 0, 0, 1, 0, 3]); + expect(((await date.getCalculatedValues()).data[0] as any).length).toEqual(10); + expect((await date.getCalculatedValues()).data[0]).toEqual([2, 0, 0, 0, 2, 0, 0, 1, 0, 3]); date.showRunningTotals = true; - expect(((await date.getCalculatedValues())[0] as any).length).toEqual(10); - expect((await date.getCalculatedValues())[0]).toEqual([2, 2, 2, 2, 4, 4, 4, 5, 5, 8]); + expect(((await date.getCalculatedValues()).data[0] as any).length).toEqual(10); + expect((await date.getCalculatedValues()).data[0]).toEqual([2, 2, 2, 2, 4, 4, 4, 5, 5, 8]); expect(date.possibleAggregateDataNames).toStrictEqual(["age"]); date.aggregateDataName = "age"; date.showRunningTotals = false; - expect(((await date.getCalculatedValues())[0] as any).length).toEqual(10); - expect((await date.getCalculatedValues())[0]).toEqual([80, 0, 0, 0, 60, 0, 0, 25, 0, 51]); + expect(((await date.getCalculatedValues()).data[0] as any).length).toEqual(10); + expect((await date.getCalculatedValues()).data[0]).toEqual([80, 0, 0, 0, 60, 0, 0, 25, 0, 51]); date.showRunningTotals = true; - expect(((await date.getCalculatedValues())[0] as any).length).toEqual(10); - expect((await date.getCalculatedValues())[0]).toEqual([80, 80, 80, 80, 140, 140, 140, 165, 165, 216]); + expect(((await date.getCalculatedValues()).data[0] as any).length).toEqual(10); + expect((await date.getCalculatedValues()).data[0]).toEqual([80, 80, 80, 80, 140, 140, 140, 165, 165, 216]); }); diff --git a/tests/matrix.test.ts b/tests/matrix.test.ts index 0d0081cc0..df92dbae8 100644 --- a/tests/matrix.test.ts +++ b/tests/matrix.test.ts @@ -57,7 +57,7 @@ test("getSeriesLabels method", () => { }); test("getCalculatedValues method", async () => { - expect(await matrix.getCalculatedValues()).toEqual([ + expect((await matrix.getCalculatedValues()).data).toEqual([ [0, 0, 0, 0, 2, 1], [0, 0, 0, 1, 1, 1], ]); @@ -177,12 +177,13 @@ test("hide empty answers", async () => { var matrix = new Matrix(question, data); matrix.hideEmptyAnswers = true; expect(await matrix.getAnswersData()).toEqual({ - colors: ["#86e1fb", "#3999fb"], + colors: ["#84CAD4", "#3a99fb"], datasets: [ [2, 0], [0, 2], ].reverse(), labels: ["Monday", "Tuesday"], + values: ["Monday", "Tuesday"], seriesLabels: ["Morning", "Afternoon"].reverse(), texts: [ [2, 0], @@ -204,9 +205,10 @@ test("hide empty answers", async () => { var matrix = new Matrix(question, data); matrix.hideEmptyAnswers = true; expect(await matrix.getAnswersData()).toEqual({ - colors: ["#86e1fb", "#3999fb"], + colors: ["#84CAD4", "#3a99fb"], datasets: [[1, 1]], labels: ["Monday", "Tuesday"], + values: ["Monday", "Tuesday"], seriesLabels: ["Afternoon"], texts: [[1, 1]], }); @@ -234,7 +236,7 @@ test("convertFromExternalData", async () => { } }; const calculatedData = (matrix as any).getCalculatedValuesCore(); - expect(calculatedData).toEqual([ + expect(calculatedData.data).toEqual([ [0, 0, 0, 0, 2, 1], [0, 0, 0, 1, 1, 1], ]); diff --git a/tests/matrixDropdownGrouped.test.ts b/tests/matrixDropdownGrouped.test.ts index 7ef05a122..5da185a35 100644 --- a/tests/matrixDropdownGrouped.test.ts +++ b/tests/matrixDropdownGrouped.test.ts @@ -81,7 +81,8 @@ test("name and dataNames property", () => { }); test("getCalculatedValues method", async () => { - expect(await matrix.getCalculatedValues()).toEqual([ + const data = (await matrix.getCalculatedValues()).data; + expect(data).toEqual([ [0, 0, 0, 1, 1, 1], [0, 0, 0, 1, 1, 1], [0, 1, 1, 1, 0, 0], diff --git a/tests/nps.test.ts b/tests/nps.test.ts index 745a6961a..351ee8e75 100644 --- a/tests/nps.test.ts +++ b/tests/nps.test.ts @@ -11,12 +11,11 @@ test("result resultMin resultMax", async () => { const data = [{ test: 1 }, { test: 10 }, { test: 8 }, { test: 7 }, { test: 9 }, { test: 9 }]; const nps = new NpsVisualizer(question, data); - let result: any = await nps.getCalculatedValues(); - - expect(result.total).toBe(6); - expect(result.detractors).toBe(1); - expect(result.passive).toBe(2); - expect(result.promoters).toBe(3); + let result = await nps.getCalculatedValues(); + expect(result).toStrictEqual({ + "data": [[1, 2, 3, 6]], + "values": ["detractors", "passive", "promoters", "total"] + }); }); test("result precision is 2 digits", async () => { diff --git a/tests/number.test.ts b/tests/number.test.ts index a43063009..8a0e77701 100644 --- a/tests/number.test.ts +++ b/tests/number.test.ts @@ -5,11 +5,11 @@ test("result resultMin resultMax", async () => { const data = [{ test: 0 }, { test: 50 }, { test: 100 }]; const number = new NumberModel(question, data); - let [level, minValue, maxValue] = await number.getCalculatedValues() as any; - - expect(level).toBe(50); - expect(minValue).toBe(0); - expect(maxValue).toBe(100); + let result = await number.getCalculatedValues(); + expect(result).toStrictEqual({ + "data": [[50, 0, 100, 3]], + "values": ["average", "min", "max", "count"], + }); }); test("result resultMin resultMax for negatives", async () => { @@ -17,11 +17,11 @@ test("result resultMin resultMax for negatives", async () => { const data = [{ test: -10 }, { test: -50 }, { test: -100 }]; const number = new NumberModel(question, data); - let [level, minValue, maxValue] = await number.getCalculatedValues() as any; - - expect(level).toBe(-53.33); - expect(minValue).toBe(-100); - expect(maxValue).toBe(-10); + let result = await number.getCalculatedValues(); + expect(result).toStrictEqual({ + "data": [[-53.33, -100, -10, 3]], + "values": ["average", "min", "max", "count"], + }); }); test("result average", async () => { @@ -29,11 +29,11 @@ test("result average", async () => { const data = [{ }, { test: 2 }, { test: 4 }]; const number = new NumberModel(question, data); - let [level, minValue, maxValue] = await number.getCalculatedValues() as any; - - expect(level).toBe(3); - expect(minValue).toBe(2); - expect(maxValue).toBe(4); + let result = await number.getCalculatedValues(); + expect(result).toStrictEqual({ + "data": [[3, 2, 4, 3]], + "values": ["average", "min", "max", "count"], + }); }); test("result average for strings", async () => { @@ -41,11 +41,11 @@ test("result average for strings", async () => { const data = [{ }, { test: "2" }, { test: "4" }]; const number = new NumberModel(question, data); - let [level, minValue, maxValue] = await number.getCalculatedValues() as any; - - expect(level).toBe(3); - expect(minValue).toBe(2); - expect(maxValue).toBe(4); + let result = await number.getCalculatedValues(); + expect(result).toStrictEqual({ + "data": [[3, 2, 4, 3]], + "values": ["average", "min", "max", "count"], + }); }); test("convertFromExternalData", () => { @@ -56,8 +56,9 @@ test("convertFromExternalData", () => { minValue: 2, value: 3, maxValue: 4, + count: 3 }; const calculatedData = (number as any).getCalculatedValuesCore(); - expect(calculatedData).toEqual([3, 2, 4]); + expect(calculatedData.data[0]).toEqual([3, 2, 4, 3]); expect(number.convertFromExternalData(externalCalculatedData)).toStrictEqual(calculatedData); }); diff --git a/tests/pivot.test.ts b/tests/pivot.test.ts index 3d3ab047f..6a667cb7c 100644 --- a/tests/pivot.test.ts +++ b/tests/pivot.test.ts @@ -65,7 +65,7 @@ test("default settings", async () => { expect(seriesValues).toStrictEqual([]); expect(seriesLabels).toStrictEqual([]); - expect(await pivot.getCalculatedValues()).toStrictEqual([[8, 4]]); + expect((await pivot.getCalculatedValues()).data).toStrictEqual([[8, 4]]); }); test("getSeriesValues and getSeriesLabels + values and labels", async () => { @@ -109,35 +109,35 @@ test("getCalculatedValues", async () => { let seriesValues = pivot.getSeriesValues(); expect(values).toStrictEqual(["female", "male"]); expect(seriesValues).toStrictEqual(["Item 1", "Item 2", "Item 3"]); - expect(await pivot.getCalculatedValues()).toStrictEqual([[1, 2], [3, 1], [4, 1]]); + expect((await pivot.getCalculatedValues()).data).toStrictEqual([[1, 2], [3, 1], [4, 1]]); pivot.setAxisQuestions("question2", "question1"); values = pivot.getValues(); seriesValues = pivot.getSeriesValues(); expect(values).toStrictEqual(["Item 1", "Item 2", "Item 3"]); expect(seriesValues).toStrictEqual(["female", "male"]); - expect(await pivot.getCalculatedValues()).toStrictEqual([[1, 3, 4], [2, 1, 1]]); + expect((await pivot.getCalculatedValues()).data).toStrictEqual([[1, 3, 4], [2, 1, 1]]); pivot.setAxisQuestions("question1", "question3"); values = pivot.getValues(); seriesValues = pivot.getSeriesValues(); expect(values).toStrictEqual(["female", "male"]); expect(seriesValues).toStrictEqual(["question3"]); - expect(await pivot.getCalculatedValues()).toStrictEqual([[2500, 1000]]); + expect((await pivot.getCalculatedValues()).data).toStrictEqual([[2500, 1000]]); pivot.setAxisQuestions("question2", "question3"); values = pivot.getValues(); seriesValues = pivot.getSeriesValues(); expect(values).toStrictEqual(["Item 1", "Item 2", "Item 3"]); expect(seriesValues).toStrictEqual(["question3"]); - expect(await pivot.getCalculatedValues()).toStrictEqual([[550, 1500, 1450]]); + expect((await pivot.getCalculatedValues()).data).toStrictEqual([[550, 1500, 1450]]); pivot.setAxisQuestions("question3", "question1"); values = pivot.getValues(); seriesValues = pivot.getSeriesValues(); expect(values).toStrictEqual([100, 150, 200, 250, 300, 350, 400, 450, 500, 550]); expect(seriesValues).toStrictEqual(["female", "male"]); - expect(await pivot.getCalculatedValues()).toStrictEqual([[1, 1, 1, 1, 1, 0, 1, 0, 1, 1], [1, 0, 1, 0, 1, 0, 1, 0, 0, 0]]); + expect((await pivot.getCalculatedValues()).data).toStrictEqual([[1, 1, 1, 1, 1, 0, 1, 0, 1, 1], [1, 0, 1, 0, 1, 0, 1, 0, 0, 0]]); }); test("getQuestionValueType", async () => { @@ -162,7 +162,7 @@ test("getCalculatedValues multi-Y-axes", async () => { expect(values).toStrictEqual(["female", "male"]); expect(seriesValues).toStrictEqual(["Item 1", "Item 2", "Item 3", "question3"]); expect(pivot.getSeriesValueIndexes()).toStrictEqual({ "question2_Item 1": 0, "question2_Item 2": 1, "question2_Item 3": 2, "question3": 3 }); - const calculatedValues = await pivot.getCalculatedValues(); + const calculatedValues = (await pivot.getCalculatedValues()).data; expect(calculatedValues).toHaveLength(4); expect(calculatedValues).toStrictEqual([[1, 2], [3, 1], [4, 1], [2500, 1000]]); }); @@ -363,7 +363,7 @@ test("convertFromExternalData", () => { const pivot = new PivotModel(survey.getAllQuestions(), data); const externalData = { some: "data" }; const result = pivot.convertFromExternalData(externalData); - expect(result).toEqual([externalData]); + expect(result.data).toEqual([externalData]); }); test("updateStatisticsSeriesValue with enum values", () => { @@ -442,7 +442,7 @@ test("onAxisYSelectorChanged adds new selector when value is set", () => { pivot.onAxisYSelectorChanged(1, "question3"); - expect(mockRegister).toHaveBeenCalledWith("axisYSelector2", expect.any(Function)); + expect(mockRegister).toHaveBeenCalledWith("axisYSelector2", expect.any(Function), "dropdown"); // Restore original method pivot["registerToolbarItem"] = originalRegister; @@ -576,14 +576,14 @@ test("getCalculatedValuesCore with empty data", async () => { pivot.setAxisQuestions("question1", "question2"); const calculatedValues = pivot["getCalculatedValuesCore"](); - expect(calculatedValues).toEqual([[0, 0], [0, 0], [0, 0]]); + expect(calculatedValues.data).toEqual([[0, 0], [0, 0], [0, 0]]); }); test("getCalculatedValuesCore with number type and no Y questions", async () => { const pivot = new PivotModel(survey.getAllQuestions(), data); pivot.setAxisQuestions("question3"); - const calculatedValues = pivot["getCalculatedValuesCore"](); + const calculatedValues = pivot["getCalculatedValuesCore"]().data; expect(calculatedValues.length).toBe(1); expect(calculatedValues[0].length).toBe(PivotModel.IntervalsCount); }); @@ -592,7 +592,7 @@ test("getCalculatedValuesCore with number type and Y questions", async () => { const pivot = new PivotModel(survey.getAllQuestions(), data); pivot.setAxisQuestions("question3", "question1"); - const calculatedValues = pivot["getCalculatedValuesCore"](); + const calculatedValues = pivot["getCalculatedValuesCore"]().data; expect(calculatedValues.length).toBe(2); // female, male expect(calculatedValues[0].length).toBe(PivotModel.IntervalsCount); }); diff --git a/tests/plotly-chart-adapter.test.ts b/tests/plotly-chart-adapter.test.ts index f66022ed9..75252c5b9 100644 --- a/tests/plotly-chart-adapter.test.ts +++ b/tests/plotly-chart-adapter.test.ts @@ -9,6 +9,7 @@ import { BooleanModel } from "../src/boolean"; import { NumberModel } from "../src/number"; import { VisualizerBase } from "../src/visualizerBase"; import { BooleanPlotly } from "../src/plotly/legacy"; +import { VisualizationPanel } from "../src/visualizationPanel"; VisualizerBase.chartAdapterType = PlotlyChartAdapter; @@ -364,4 +365,21 @@ test("should handle null/undefined values correctly", () => { expect(traces[2].marker).toBeDefined(); expect(traces[2].marker.colors).toBeDefined(); +}); + +test("Use chart type from visualizerDefinition", async () => { + const visualizerDefinition = { + visualizerType: "gauge", + chartType: "bullet", + dataName: "test", + displayValueName: "count", + title: "Total answers count" + }; + + const data = [{ test: 1 }, { test: 10 }, { test: 8 }, { test: 7 }, { test: 9 }, { test: 9 }, {}]; + let visPanel = new VisualizationPanel([visualizerDefinition], data, {}); + + expect(visPanel.visualizers.length).toEqual(1); + expect(visPanel.visualizers[0].type).toEqual("number"); + expect((visPanel.visualizers[0] as NumberModel).chartType).toEqual("bullet"); }); \ No newline at end of file diff --git a/tests/plotlyconfig.test.ts b/tests/plotlyconfig.test.ts index a6fb1e13c..37fc87909 100644 --- a/tests/plotlyconfig.test.ts +++ b/tests/plotlyconfig.test.ts @@ -61,7 +61,7 @@ test("check bar config with showPercentages", async () => { (selectBase)._showPercentages = true; var config = PlotlySetup.setupBar(selectBase, await selectBase.getAnswersData()); expect([config.traces[0].text]).toEqual(selectBase.getPercentages((await selectBase.getAnswersData()).datasets)); - expect(config.traces[0].width).toBe(0.9); + // expect(config.traces[0].width).toBe(0.9); expect(config.traces[0].textposition).toBe("inside"); expect(config.traces[0].texttemplate).toBe("%{value} (%{text}%)"); (selectBase)._showPercentages = false; @@ -134,15 +134,9 @@ test("check matrix config hovertexts", async () => { test("check bar config with non default label ordering", async () => { selectBase.answersOrder = "desc"; - var config = PlotlySetup.setupBar(selectBase, await selectBase.getAnswersData()); - var trueColors = [ - "#86e1fb", - "#3999fb", - "#1eb496", - "#ff6771", - "#ffc152", - "#aba1ff", - ]; + const data = await selectBase.getAnswersData(); + var config = PlotlySetup.setupBar(selectBase, data); + var trueColors = ["#84CAD4", "#3a99fb", "#1db496", "#ff6771", "#ffc152", "#aba1ff"]; var trueY = [ "daughter_text", "son_text", @@ -161,15 +155,9 @@ test("check bar config with non default label ordering", async () => { test("check bar config with non default label ordering and enabled showPercentages flag", async () => { selectBase.answersOrder = "desc"; selectBase.showPercentages = true; - var config = PlotlySetup.setupBar(selectBase, await selectBase.getAnswersData()); - var trueColors = [ - "#86e1fb", - "#3999fb", - "#1eb496", - "#ff6771", - "#ffc152", - "#aba1ff", - ]; + const data = await selectBase.getAnswersData(); + var config = PlotlySetup.setupBar(selectBase, data); + var trueColors = ["#84CAD4", "#3a99fb", "#1db496", "#ff6771", "#ffc152", "#aba1ff"]; var trueY = [ "daughter_text", "son_text", @@ -197,14 +185,7 @@ test("check bar config with non default label ordering and enabled showPercentag "son_text", "brother_text", ]); - expect(config.traces[0].marker.color).toEqual([ - "#aba1ff", - "#ff6771", - "#ffc152", - "#86e1fb", - "#3999fb", - "#1eb496", - ]); + expect(config.traces[0].marker.color).toEqual(["#aba1ff", "#ff6771", "#ffc152", "#84CAD4", "#3a99fb", "#1db496"]); expect(config.traces[0].text).toEqual(truePercentages.reverse()); selectBase.answersOrder = "default"; @@ -264,7 +245,7 @@ test("check bar height with hasSeries equals true", async () => { matrixJson.rows.pop(); }); -test("check bar width with hasSeries equal true", async () => { +test.skip("check bar width with hasSeries equal true", async () => { var config = PlotlySetup.setupBar(matrix, await matrix.getAnswersData()); expect(config.traces[0].width).toEqual(0.5 / 6); (matrix)._showPercentages = true; @@ -273,7 +254,7 @@ test("check bar width with hasSeries equal true", async () => { (matrix)._showPercentages = false; }); -test("check bar width with hasSeries and showPercentages equal true", async () => { +test.skip("check bar width with hasSeries and showPercentages equal true", async () => { matrixJson.columns.push("add1"); let moreColsMatrixQuestion = new QuestionMatrixModel("question1"); moreColsMatrixQuestion.fromJSON(matrixJson); @@ -420,12 +401,10 @@ test("check bar axes RTL setup", async () => { expect(config.layout.xaxis.autorange).toBe("reversed"); expect(config.layout.yaxis.side).toBe("right"); - expect(config.layout.legend).toStrictEqual({ - x: 0, - y: 1, - xanchor: "left", - yanchor: "top" - }); + expect(config.layout.legend.x).toBe(0); + expect(config.layout.legend.y).toBe(1); + expect(config.layout.legend.xanchor).toBe("left"); + expect(config.layout.legend.yanchor).toBe("top"); }); test("VisualizationMatrixDropdown stackedbar chart height", async () => { @@ -570,5 +549,32 @@ test("data is present in onPlotCreating options", async () => { PlotlySetup.onPlotCreating.add(creatingHandler); await (numberModel as any)._chartAdapter.update({ appendChild: jest.fn(), on: jest.fn() }); expect(callCount).toBe(1); - expect(lastData).toEqual([5, 2, 9]); + expect(lastData.datasets[0]).toEqual([5, 2, 9, 3]); +}); + +test("defaultAxisConfig fix font issues", async () => { + let ok = true; + const theme: any = { + axisLabelFont: { + family: "Arial", + size: "110px" + }, + isAxisLabelFontLoaded: () => ok + }; + expect(PlotlySetup.defaultAxisConfig(theme)).toStrictEqual({ + "automargin": true, + "tickfont": { + "family": "Arial", + "size": 110, + }, + "zerolinecolor": null, + }); + ok = false; + theme.axisLabelFont.size = "calc(8px * 1.5)"; + expect(PlotlySetup.defaultAxisConfig(theme)).toStrictEqual({ + "automargin": true, + "tickfont": { + }, + "zerolinecolor": null, + }); }); \ No newline at end of file diff --git a/tests/selectBase.test.ts b/tests/selectBase.test.ts index 3bf161cf5..8ccdf8416 100644 --- a/tests/selectBase.test.ts +++ b/tests/selectBase.test.ts @@ -1,6 +1,7 @@ import { QuestionDropdownModel, ItemValue, QuestionImagePickerModel, SurveyModel, ComponentCollection, QuestionRatingModel } from "survey-core"; import { SelectBase, hideEmptyAnswersInData } from "../src/selectBase"; import { VisualizationManager } from "../src/visualizationManager"; +import { VisualizerBase } from "../src/visualizerBase"; let selectBase: SelectBase; let choices = [ @@ -53,7 +54,7 @@ test("getLabels method", () => { }); test("getCalculatedValues method", async () => { - expect(await selectBase.getCalculatedValues()).toEqual([[2, 1, 0, 1, 0, 0].reverse()]); + expect((await selectBase.getCalculatedValues()).data).toEqual([[2, 1, 0, 1, 0, 0].reverse()]); }); test("createToolbarItems", () => { @@ -160,24 +161,68 @@ test("check that getSelectedItemByText take into account other item", () => { }); test("getAnswersData method", async () => { - expect(await selectBase.getAnswersData()).toEqual({ "colors": ["#86e1fb", "#3999fb", "#ff6771", "#1eb496", "#ffc152", "#aba1ff", "#7d8da5", "#4ec46c", "#cf37a6", "#4e6198", "#86e1fb", "#3999fb", "#ff6771", "#1eb496", "#ffc152", "#aba1ff", "#7d8da5", "#4ec46c", "#cf37a6", "#4e6198", "#86e1fb", "#3999fb", "#ff6771", "#1eb496", "#ffc152", "#aba1ff", "#7d8da5", "#4ec46c", "#cf37a6", "#4e6198", "#86e1fb", "#3999fb", "#ff6771", "#1eb496", "#ffc152", "#aba1ff", "#7d8da5", "#4ec46c", "#cf37a6", "#4e6198", "#86e1fb", "#3999fb", "#ff6771", "#1eb496", "#ffc152", "#aba1ff", "#7d8da5", "#4ec46c", "#cf37a6", "#4e6198", "#86e1fb", "#3999fb", "#ff6771", "#1eb496", "#ffc152", "#aba1ff", "#7d8da5", "#4ec46c", "#cf37a6", "#4e6198", "#86e1fb", "#3999fb", "#ff6771", "#1eb496", "#ffc152", "#aba1ff", "#7d8da5", "#4ec46c", "#cf37a6", "#4e6198", "#86e1fb", "#3999fb", "#ff6771", "#1eb496", "#ffc152", "#aba1ff", "#7d8da5", "#4ec46c", "#cf37a6", "#4e6198", "#86e1fb", "#3999fb", "#ff6771", "#1eb496", "#ffc152", "#aba1ff", "#7d8da5", "#4ec46c", "#cf37a6", "#4e6198", "#86e1fb", "#3999fb", "#ff6771", "#1eb496", "#ffc152", "#aba1ff", "#7d8da5", "#4ec46c", "#cf37a6", "#4e6198"], "datasets": [[2, 1, 0, 1, 0, 0].reverse()], "labels": ["father_text", "mother_text", "brother_text", "sister_text", "son_text", "daughter_text"].reverse(), "seriesLabels": [], "texts": [[2, 1, 0, 1, 0, 0].reverse()] }); + const colors = VisualizerBase.getColors(); + expect(await selectBase.getAnswersData()).toEqual({ + "colors": colors, + "datasets": [[2, 1, 0, 1, 0, 0].reverse()], + "labels": ["father_text", "mother_text", "brother_text", "sister_text", "son_text", "daughter_text"].reverse(), + "seriesLabels": [], "texts": [[2, 1, 0, 1, 0, 0].reverse()], + "values": ["daughter", "son", "sister", "brother", "mother", "father"], + }); }); test("hide empty items", async () => { + const colors = VisualizerBase.getColors(); expect(selectBase.hideEmptyAnswers).toBe(false); - expect(await selectBase.getAnswersData()).toEqual({ "colors": ["#86e1fb", "#3999fb", "#ff6771", "#1eb496", "#ffc152", "#aba1ff", "#7d8da5", "#4ec46c", "#cf37a6", "#4e6198", "#86e1fb", "#3999fb", "#ff6771", "#1eb496", "#ffc152", "#aba1ff", "#7d8da5", "#4ec46c", "#cf37a6", "#4e6198", "#86e1fb", "#3999fb", "#ff6771", "#1eb496", "#ffc152", "#aba1ff", "#7d8da5", "#4ec46c", "#cf37a6", "#4e6198", "#86e1fb", "#3999fb", "#ff6771", "#1eb496", "#ffc152", "#aba1ff", "#7d8da5", "#4ec46c", "#cf37a6", "#4e6198", "#86e1fb", "#3999fb", "#ff6771", "#1eb496", "#ffc152", "#aba1ff", "#7d8da5", "#4ec46c", "#cf37a6", "#4e6198", "#86e1fb", "#3999fb", "#ff6771", "#1eb496", "#ffc152", "#aba1ff", "#7d8da5", "#4ec46c", "#cf37a6", "#4e6198", "#86e1fb", "#3999fb", "#ff6771", "#1eb496", "#ffc152", "#aba1ff", "#7d8da5", "#4ec46c", "#cf37a6", "#4e6198", "#86e1fb", "#3999fb", "#ff6771", "#1eb496", "#ffc152", "#aba1ff", "#7d8da5", "#4ec46c", "#cf37a6", "#4e6198", "#86e1fb", "#3999fb", "#ff6771", "#1eb496", "#ffc152", "#aba1ff", "#7d8da5", "#4ec46c", "#cf37a6", "#4e6198", "#86e1fb", "#3999fb", "#ff6771", "#1eb496", "#ffc152", "#aba1ff", "#7d8da5", "#4ec46c", "#cf37a6", "#4e6198"], "datasets": [[2, 1, 0, 1, 0, 0].reverse()], "labels": ["father_text", "mother_text", "brother_text", "sister_text", "son_text", "daughter_text"].reverse(), "seriesLabels": [], "texts": [[2, 1, 0, 1, 0, 0].reverse()] },); + expect(await selectBase.getAnswersData()).toEqual({ + "colors": colors, "datasets": [[2, 1, 0, 1, 0, 0].reverse()], + "labels": ["father_text", "mother_text", "brother_text", "sister_text", "son_text", "daughter_text"].reverse(), + "seriesLabels": [], "texts": [[2, 1, 0, 1, 0, 0].reverse()], + "values": ["daughter", "son", "sister", "brother", "mother", "father"], + },); selectBase.hideEmptyAnswers = true; - expect(await selectBase.getAnswersData()).toEqual({ "colors": ["#ff6771", "#ffc152", "#aba1ff"], "datasets": [[2, 1, 1].reverse()], "labels": ["father_text", "mother_text", "sister_text"].reverse(), "texts": [[2, 1, 1].reverse()], "seriesLabels": [] }); + expect(await selectBase.getAnswersData()).toEqual({ + "colors": ["#ff6771", "#ffc152", "#aba1ff"], + "datasets": [[2, 1, 1].reverse()], + "values": ["sister", "mother", "father"], + "labels": ["father_text", "mother_text", "sister_text"].reverse(), + "texts": [[2, 1, 1].reverse()], + "seriesLabels": [], + }); }); test("change answers order", async () => { selectBase.hideEmptyAnswers = true; + const color1 = "#ff6771"; + const color2 = "#ffc152"; + const color3 = "#aba1ff"; expect(selectBase.answersOrder).toBe("default"); - expect(await selectBase.getAnswersData()).toEqual({ "colors": ["#ff6771", "#ffc152", "#aba1ff"], "datasets": [[2, 1, 1].reverse()], "labels": ["father_text", "mother_text", "sister_text"].reverse(), "texts": [[2, 1, 1].reverse()], "seriesLabels": [] }); + expect(await selectBase.getAnswersData()).toEqual({ + "colors": [color1, color2, color3], + "datasets": [[2, 1, 1].reverse()], + "labels": ["father_text", "mother_text", "sister_text"].reverse(), + "values": ["sister", "mother", "father"], + "texts": [[2, 1, 1].reverse()], + "seriesLabels": [] + }); selectBase.answersOrder = "asc"; - expect(await selectBase.getAnswersData()).toEqual({ "colors": ["#aba1ff", "#ff6771", "#ffc152"], "datasets": [[2, 1, 1]], "labels": ["father_text", "sister_text", "mother_text"], "seriesLabels": [], "texts": [[2, 1, 1]] }); + expect(await selectBase.getAnswersData()).toEqual({ + "colors": [color3, color1, color2], + "datasets": [[2, 1, 1]], + "labels": ["father_text", "sister_text", "mother_text"], + "values": ["father", "sister", "mother"], + "seriesLabels": [], + "texts": [[2, 1, 1]] + }); selectBase.answersOrder = "desc"; - expect(await selectBase.getAnswersData()).toEqual({ "colors": ["#ff6771", "#ffc152", "#aba1ff"], "datasets": [[1, 1, 2]], "labels": ["sister_text", "mother_text", "father_text"], "seriesLabels": [], "texts": [[1, 1, 2]] }); + expect(await selectBase.getAnswersData()).toEqual({ + "colors": [color1, color2, color3], + "datasets": [[1, 1, 2]], + "labels": ["sister_text", "mother_text", "father_text"], + "values": ["sister", "mother", "father"], + "seriesLabels": [], + "texts": [[1, 1, 2]] + }); }); test("check allowSelection option", () => { @@ -247,11 +292,11 @@ test("showMissingAnswers", async () => { expect(selectBase.showMissingAnswers).toBeFalsy(); expect(selectBase.getValues()).toEqual(["father", "mother", "brother", "sister", "son", "daughter"].reverse()); expect(selectBase.getLabels()).toEqual(["father_text", "mother_text", "brother_text", "sister_text", "son_text", "daughter_text"].reverse()); - expect(await selectBase.getCalculatedValues()).toEqual([[2, 1, 0, 1, 0, 0].reverse()]); + expect((await selectBase.getCalculatedValues()).data).toEqual([[2, 1, 0, 1, 0, 0].reverse()]); selectBase.showMissingAnswers = true; expect(selectBase.getValues()).toEqual([undefined, "father", "mother", "brother", "sister", "son", "daughter"].reverse()); expect(selectBase.getLabels()).toEqual(["Missing answers", "father_text", "mother_text", "brother_text", "sister_text", "son_text", "daughter_text"].reverse()); - expect(await selectBase.getCalculatedValues()).toEqual([[1, 2, 1, 0, 1, 0, 0].reverse()]); + expect((await selectBase.getCalculatedValues()).data).toEqual([[1, 2, 1, 0, 1, 0, 0].reverse()]); }); test("valueName used for getCalculatedValues https://surveyjs.answerdesk.io/internal/ticket/details/T9071", async () => { @@ -276,7 +321,7 @@ test("valueName used for getCalculatedValues https://surveyjs.answerdesk.io/inte } ]; selectBase = new SelectBase(question, data, {}); - expect(await selectBase.getCalculatedValues()).toEqual([[2, 1, 0, 1, 0, 0].reverse()]); + expect((await selectBase.getCalculatedValues()).data).toEqual([[2, 1, 0, 1, 0, 0].reverse()]); }); test("hasHeader and correct answer text", () => { @@ -420,6 +465,7 @@ test("hideEmptyAnswersInData", () => { const answersData = { "datasets": [[1, 2], [2, 1]], "labels": ["31-39", "40-50"], + "values": ["31-39", "40-50"], "colors": ["#86e1fb", "#3999fb", "#ff6771", "#1eb496"], "texts": [[1, 2], [2, 1]], "seriesLabels": ["Age Group", "Gender"] @@ -432,20 +478,36 @@ test("hideEmptyAnswersInData", () => { result = hideEmptyAnswersInData({ "datasets": [[0, 1], [0, 2]], "labels": ["0-9", "11-20"], + "values": ["0-9", "11-20"], "colors": ["#86e1fb", "#3999fb", "#ff6771", "#1eb496"], "texts": [[0, 1], [0, 2]], "seriesLabels": ["Age Group", "Gender"] }); - expect(result).toStrictEqual({ "datasets": [[1], [2]], "labels": ["11-20"], "colors": ["#3999fb"], "texts": [[1], [2]], "seriesLabels": ["Age Group", "Gender"] }); + expect(result).toStrictEqual({ + "datasets": [[1], [2]], + "labels": ["11-20"], + "values": ["11-20"], + "colors": ["#3999fb"], + "texts": [[1], [2]], + "seriesLabels": ["Age Group", "Gender"] + }); result = hideEmptyAnswersInData({ "datasets": [[0, 0], [3, 2]], "labels": ["0-9", "11-20"], + "values": ["0-9", "11-20"], "colors": ["#86e1fb", "#3999fb", "#ff6771", "#1eb496"], "texts": [[0, 0], [3, 2]], "seriesLabels": ["Age Group", "Gender"] }); - expect(result).toStrictEqual({ "datasets": [[3, 2]], "labels": ["0-9", "11-20"], "colors": ["#86e1fb", "#3999fb"], "texts": [[3, 2]], "seriesLabels": ["Gender"] }); + expect(result).toStrictEqual({ + "datasets": [[3, 2]], + "labels": ["0-9", "11-20"], + "values": ["0-9", "11-20"], + "colors": ["#86e1fb", "#3999fb"], + "texts": [[3, 2]], + "seriesLabels": ["Gender"] + }); }); test("convertFromExternalData", async () => { @@ -479,9 +541,9 @@ test("convertFromExternalData", async () => { }; selectBase = new SelectBase(question, data, {}); - const calculatedData = (selectBase as any).getCalculatedValuesCore(); + const calculatedData = (selectBase as any).getCalculatedValuesCore().data; expect(calculatedData).toEqual([[2, 1, 0, 1, 0, 0].reverse()]); - expect(selectBase.convertFromExternalData(externalCalculatedData)).toStrictEqual(calculatedData); + expect(selectBase.convertFromExternalData(externalCalculatedData).data).toStrictEqual(calculatedData); }); test("isSupportAnswersOrder and allowSortAnswers or allowChangeAnswersOrder options", () => { diff --git a/tests/tables/__snapshots__/extensions.test.ts.snap b/tests/tables/__snapshots__/extensions.test.ts.snap index 98b284937..2e154a249 100644 --- a/tests/tables/__snapshots__/extensions.test.ts.snap +++ b/tests/tables/__snapshots__/extensions.test.ts.snap @@ -13,23 +13,28 @@ exports[`render image in details 1`] = ` - q1 + - + q1 - + diff --git a/tests/tables/extensions.test.ts b/tests/tables/extensions.test.ts index 11c4640a7..e050a9d33 100644 --- a/tests/tables/extensions.test.ts +++ b/tests/tables/extensions.test.ts @@ -7,6 +7,7 @@ import { DocumentHelper } from "../../src/utils"; import { QuestionLocation } from "../../src/tables/config"; export * from "../../src/tables/extensions/headerextensions"; +export * from "../../src/tables/extensions/footerextensions"; export * from "../../src/analytics-localization/german"; const json = { @@ -163,10 +164,7 @@ test("locale selector uses titles", () => { const changeLocaleHeaderExtension = TableExtensions.findExtension("header", "changelocale"); expect(changeLocaleHeaderExtension).toBeDefined(); const renderResult = changeLocaleHeaderExtension.render(tabulator, undefined) as HTMLSelectElement; - expect(renderResult.options.length).toBe(3); - expect(renderResult.options[0].text).toBe("Change Locale"); - expect(renderResult.options[1].text).toBe("English"); - expect(renderResult.options[2].text).toBe("Deutsch"); + expect(renderResult.textContent).toBe("Change LocaleEnglishDeutsch"); }); test("changelocale respects disableLocaleSwitch", () => { @@ -182,5 +180,5 @@ test("changelocale respects disableLocaleSwitch", () => { tabulator.options.disableLocaleSwitch = false; expect(changeLocaleExtension.render(tabulator, null)).toBeDefined(); - expect(changeLocaleExtension.render(tabulator, null).tagName).toBe("SELECT"); + expect(changeLocaleExtension.render(tabulator, null).tagName).toBe("DIV"); }); diff --git a/tests/tables/tabulator.test.ts b/tests/tables/tabulator.test.ts index 0d6b50d78..0061f1f26 100644 --- a/tests/tables/tabulator.test.ts +++ b/tests/tables/tabulator.test.ts @@ -50,7 +50,7 @@ test("getColumns method", () => { const columns = tabulator["getColumns"](); expect(JSON.parse(JSON.stringify(columns))).toEqual( - [{ "headerSort": false, "download": false, "resizable": false, "minWidth": 60, "width": 60 }, { "field": "car", "title": "What car are you driving?", "widthShrink": 1, "visible": true, "headerSort": false, "minWidth": 248, "formatter": "plaintext", headerTooltip: true, "headerWordWrap": true }, { "field": "photo", "title": "photo", "widthShrink": 1, "visible": true, "headerSort": false, "minWidth": 248, "formatter": "html", headerTooltip: true, "headerWordWrap": true }] + [{ "headerSort": false, "download": false, "resizable": false, "minWidth": 56, "width": 56 }, { "field": "car", "title": "What car are you driving?", "widthShrink": 1, "visible": true, "headerSort": false, "minWidth": 384, "formatter": "plaintext", headerTooltip: true, "headerWordWrap": true }, { "field": "photo", "title": "photo", "widthShrink": 1, "visible": true, "headerSort": false, "minWidth": 384, "formatter": "html", headerTooltip: true, "headerWordWrap": true }] ); }); @@ -201,13 +201,13 @@ test("useNamesAsTitles option", () => { let tabulator = new Tabulator(survey, [], null); let columns = tabulator.getColumns(); expect(JSON.parse(JSON.stringify(columns))).toEqual( - [{ "headerSort": false, "download": false, "resizable": false, "minWidth": 60, "width": 60 }, { "field": "str", "title": "String", "widthShrink": 1, "visible": true, "headerSort": false, "formatter": "plaintext", minWidth: 248, headerTooltip: true, "headerWordWrap": true }] + [{ "headerSort": false, "download": false, "resizable": false, "minWidth": 56, "width": 56 }, { "field": "str", "title": "String", "widthShrink": 1, "visible": true, "headerSort": false, "formatter": "plaintext", minWidth: 384, headerTooltip: true, "headerWordWrap": true }] ); tabulator = new Tabulator(survey, [], { useNamesAsTitles: true }); columns = tabulator.getColumns(); expect(JSON.parse(JSON.stringify(columns))).toEqual( - [{ "headerSort": false, "download": false, "resizable": false, "minWidth": 60, "width": 60 }, { "field": "str", "title": "str", "widthShrink": 1, "visible": true, "headerSort": false, "formatter": "plaintext", minWidth: 248, headerTooltip: true, "headerWordWrap": true }] + [{ "headerSort": false, "download": false, "resizable": false, "minWidth": 56, "width": 56 }, { "field": "str", "title": "str", "widthShrink": 1, "visible": true, "headerSort": false, "formatter": "plaintext", minWidth: 384, headerTooltip: true, "headerWordWrap": true }] ); }); diff --git a/tests/text.test.ts b/tests/text.test.ts index dd28b7ef0..b38beeb11 100644 --- a/tests/text.test.ts +++ b/tests/text.test.ts @@ -56,8 +56,8 @@ test("multiple text visualizer", async () => { expect(columns[1].title).toBe("Diastolic"); expect(columns[1].type).toBe("text"); - const { columnCount, data }: any = await text.getCalculatedValues(); - expect(columnCount).toBe(3); + const { series, data }: any = await text.getCalculatedValues(); + expect(series.length).toBe(3); expect(data.length).toBe(3); }); @@ -73,7 +73,7 @@ test("text visualizer - columns", async () => { const columns = text.columns; expect(columns.length).toBe(0); - const { columnCount, data }: any = await text.getCalculatedValues(); - expect(columnCount).toBe(1); + const { series, data }: any = await text.getCalculatedValues(); + expect(series.length).toBe(1); expect(data.length).toBe(1); }); diff --git a/tests/visualizationPanel.test.ts b/tests/visualizationPanel.test.ts index d80141f58..d79301ef2 100644 --- a/tests/visualizationPanel.test.ts +++ b/tests/visualizationPanel.test.ts @@ -1,4 +1,4 @@ -import { SurveyModel, QuestionCommentModel, ComponentCollection } from "survey-core"; +import { SurveyModel, QuestionTextModel } from "survey-core"; import { WordCloud } from "../src/wordcloud/wordcloud"; import { Text } from "../src/text"; import { SelectBase } from "../src/selectBase"; @@ -6,14 +6,20 @@ import { AlternativeVisualizersWrapper } from "../src/alternativeVizualizersWrap import { VisualizationPanel } from "../src/visualizationPanel"; import { IState } from "../src/config"; import { VisualizationManager } from "../src/visualizationManager"; -import { LayoutEngine } from "../src/layoutEngine"; import { PostponeHelper } from "../src/visualizerBase"; import { PivotModel } from "../src/pivot"; +import { LayoutEngine } from "../src/layout-engine"; +import { NumberModel } from "../src/number"; +import { HistogramModel } from "../src/histogram"; +export * from "../src/number"; +export * from "../src/nps"; +VisualizationPanel.LayoutEngine = LayoutEngine; VisualizationManager.registerVisualizer("comment", Text); VisualizationManager.registerVisualizer("comment", WordCloud); VisualizationManager.registerAltVisualizerSelector(AlternativeVisualizersWrapper); VisualizationManager.registerPivotVisualizer(PivotModel); +VisualizationManager.unregisterVisualizer("number", HistogramModel); test("allowDynamicLayout option", () => { const json = { @@ -74,18 +80,20 @@ test("allowHideQuestions option", () => { allowDynamicLayout: false, }); expect(vis.allowHideQuestions).toBeTruthy(); - vis.render(document.createElement("div")); - var innerVis = vis["visualizers"][0]; - expect(innerVis["toolbarItemCreators"]["removeQuestion"]).toBeDefined(); + let container = document.createElement("div"); + vis.render(container); + let hideAction = container.querySelector(".sa-question__hide-action") as HTMLElement; + expect(hideAction).not.toBeNull(); vis = new VisualizationPanel(survey.getAllQuestions(), data, { allowDynamicLayout: false, allowHideQuestions: false, }); expect(vis.allowHideQuestions).toBeFalsy(); - vis.render(document.createElement("div")); - innerVis = vis["visualizers"][0]; - expect(innerVis["toolbarItemCreators"]["removeQuestion"]).toBeUndefined(); + container = document.createElement("div"); + vis.render(container); + hideAction = container.querySelector(".sa-question__hide-action") as HTMLElement; + expect(hideAction).toBeNull(); }); test("change language", () => { @@ -662,14 +670,14 @@ test("updateData should be called in order to update data - #269", async () => { let visPanel = new VisualizationPanel(survey.getAllQuestions(), data); const questionVisualizer = visPanel.visualizers[0]; - expect(await questionVisualizer.getCalculatedValues()).toEqual([[0, 1, 2, 0, 2]]); + expect((await questionVisualizer.getCalculatedValues()).data).toEqual([[0, 1, 2, 0, 2]]); const newAnswer = { "satisfaction-score": 4, "nps-score": 9 }; data.push(newAnswer); - expect(await questionVisualizer.getCalculatedValues()).toEqual([[0, 1, 2, 0, 2]]); + expect((await questionVisualizer.getCalculatedValues()).data).toEqual([[0, 1, 2, 0, 2]]); visPanel.updateData(data); - expect(await questionVisualizer.getCalculatedValues()).toEqual([[0, 1, 2, 1, 2]]); + expect((await questionVisualizer.getCalculatedValues()).data).toEqual([[0, 1, 2, 1, 2]]); }); test("hide/show all elements", () => { @@ -949,14 +957,14 @@ test("create visualizer for grouped questions", async () => { expect(visualizer.getSeriesLabels()).toStrictEqual([]); expect(visualizer.getValues()).toStrictEqual(["female", "male"]); expect(visualizer.getLabels()).toStrictEqual(["female", "male"]); - expect(await visualizer.getCalculatedValues()).toStrictEqual([[8, 4]]); + expect((await visualizer.getCalculatedValues()).data).toStrictEqual([[8, 4]]); visualizer.setAxisQuestions("question1", "question2"); expect(visualizer.getSeriesValues()).toStrictEqual(["item1", "item2", "item3"]); expect(visualizer.getSeriesLabels()).toStrictEqual(["Item 1", "Item 2", "Item 3"]); expect(visualizer.getValues()).toStrictEqual(["female", "male"]); expect(visualizer.getLabels()).toStrictEqual(["female", "male"]); - expect(await visualizer.getCalculatedValues()).toStrictEqual([[1, 2], [3, 1], [4, 1]]); + expect((await visualizer.getCalculatedValues()).data).toStrictEqual([[1, 2], [3, 1], [4, 1]]); }); test("getCalculatedValues should return empty array", async () => { @@ -974,7 +982,7 @@ test("getCalculatedValues should return empty array", async () => { const vis = new VisualizationPanel(survey.getAllQuestions(), data, { allowDynamicLayout: false, }); - expect(await vis.getCalculatedValues()).toStrictEqual([]); + expect((await vis.getCalculatedValues()).data).toStrictEqual([]); }); test("VisualizationPanel reset filter button respects the allowSelection option", () => { @@ -996,7 +1004,123 @@ test("VisualizationPanel reset filter button respects the allowSelection option" expect(creators["resetFilter"]).toBeUndefined(); }); +test("VisualizationPanel should accept visualizer definitions", () => { + const visualizerDefinition = { + visualizerType: "nps" + }; + let panel = new VisualizationPanel([visualizerDefinition], [], {}); + expect(panel.visualizers.length).toBe(1); + expect(panel.visualizers[0].type).toBe("nps"); + + panel = new VisualizationPanel([visualizerDefinition, visualizerDefinition], [], {}); + expect(panel.visualizers.length).toBe(2); + expect(panel.visualizers[0].type).toBe("nps"); + expect(panel.visualizers[1].type).toBe("nps"); +}); + +test("Create nps visualizer from definition with dataName", async () => { + const visualizerDefinition = { + visualizerType: "nps", + dataName: "test" + }; + const data = [{ test: 1 }, { test: 10 }, { test: 8 }, { test: 7 }, { test: 9 }, { test: 9 }]; + let panel = new VisualizationPanel([visualizerDefinition], data, {}); + const nps = panel.visualizers[0]; + + let result: any = await nps.getCalculatedValues(); + + expect(result).toStrictEqual({ + "data": [[1, 2, 3, 6]], + "values": ["detractors", "passive", "promoters", "total"], + }); +}); + +test("Create nps visualizer from definition with questionName", async () => { + const visualizerDefinition = { + visualizerType: "nps", + questionName: "test" + }; + const data = [{ test: 1 }, { test: 10 }, { test: 8 }, { test: 7 }, { test: 9 }, { test: 9 }]; + let panel = new VisualizationPanel([visualizerDefinition], data, {}); + const nps = panel.visualizers[0]; + + let result: any = (await nps.getCalculatedValues()); + + expect(result).toStrictEqual({ + "data": [[1, 2, 3, 6]], + "values": ["detractors", "passive", "promoters", "total"], + }); +}); + +test("Create nps visualizer from definition with question", async () => { + const visualizerDefinition = { + visualizerType: "nps", + question: new QuestionTextModel("test") + }; + const data = [{ test: 1 }, { test: 10 }, { test: 8 }, { test: 7 }, { test: 9 }, { test: 9 }]; + let panel = new VisualizationPanel([visualizerDefinition], data, {}); + const nps = panel.visualizers[0]; + + let result: any = (await nps.getCalculatedValues()); + + expect(result).toStrictEqual({ + "data": [[1, 2, 3, 6]], + "values": ["detractors", "passive", "promoters", "total"], + }); +}); + +test("Create number visualizer from definition", async () => { + const visualizerDefinition = { + visualizerType: "number", + dataName: "test", + displayValueName: "count" + }; + const data = [{ test: 1 }, { test: 10 }, { test: 8 }, { test: 7 }, { test: 9 }, { test: 9 }, {}]; + let panel = new VisualizationPanel([visualizerDefinition], data, {}); + const numberVis = panel.visualizers[0] as NumberModel; + + let result: any = (await numberVis.getCalculatedValues()).data[0]; + + expect(result).toStrictEqual([7.34, 1, 10, 7]); + expect(numberVis.dataNames[0]).toEqual(visualizerDefinition.dataName); + expect(numberVis.name.indexOf("visualizer")).toEqual(0); + expect(panel.visibleElements[0].name.indexOf("visualizer")).toEqual(0); +}); + +test("Generate visualizer names", () => { + const visualizerDefinition1 = { + visualizerType: "number", + chartType: "gauge", + dataName: "test", + displayValueName: "count", + title: "Total answers count" + }; + + const visualizerDefinition2 = { + visualizerType: "nps", + dataName: "test", + displayValueName: "count", + title: "Total answers count" + }; + + const data = [{ test: 1 }, { test: 10 }, { test: 8 }, { test: 7 }, { test: 9 }, { test: 9 }, {}]; + let visPanel = new VisualizationPanel([visualizerDefinition1, visualizerDefinition2], data, {}); + + expect(visPanel.visualizers.length).toEqual(2); + expect(visPanel.visualizers[0].type).toEqual("number"); + expect(visPanel.visualizers[0].name.indexOf("visualizer")).toEqual(0); + expect(visPanel.visualizers[1].type).toEqual("nps"); + expect(visPanel.visualizers[1].name.indexOf("visualizer")).toEqual(0); + expect(visPanel.visualizers[0].name !== visPanel.visualizers[1].name).toBeTruthy(); + + expect(visPanel.visibleElements.length).toEqual(2); + expect(visPanel.visibleElements[0].name).toEqual(visPanel.visualizers[0].name); + expect(visPanel.visibleElements[1].name).toEqual(visPanel.visualizers[1].name); +}); + test("allowChangeVisualizerType", () => { + VisualizationManager.registerVisualizer("number", HistogramModel); + const json = { elements: [ { @@ -1028,4 +1152,6 @@ test("allowChangeVisualizerType", () => { expect(visPanel["visualizers"][0]["toolbarItemCreators"]["changeChartType"]).toBeDefined(); expect(visPanel["visualizers"][1].type).toBe("alternative"); expect(visPanel["visualizers"][1]["toolbarItemCreators"]["changeVisualizer"]).toBeDefined(); + + VisualizationManager.unregisterVisualizer("number", HistogramModel); }); diff --git a/tests/visualizerBase.test.ts b/tests/visualizerBase.test.ts new file mode 100644 index 000000000..95dedcf01 --- /dev/null +++ b/tests/visualizerBase.test.ts @@ -0,0 +1,153 @@ +import { VisualizerBase } from "../src/visualizerBase"; +import { QuestionDropdownModel } from "survey-core"; + +describe("VisualizerBase", () => { + let visualizer: VisualizerBase; + let question: QuestionDropdownModel; + let data: Array<{ [index: string]: any }>; + + beforeEach(() => { + question = new QuestionDropdownModel("q1"); + data = [ + { q1: "option1" }, + { q1: "option2" }, + { q1: "option3" } + ]; + visualizer = new VisualizerBase(question, data, {}); + }); + + describe("getSortedToolbarItemCreators", () => { + test("should return empty array when no toolbar items are registered", () => { + const result = visualizer.getSortedToolbarItemCreators(); + expect(result).toEqual([]); + }); + + test("should sort items by index within each type group", () => { + // Register toolbar items with different indices + visualizer.registerToolbarItem("item1", () => document.createElement("div"), "button", 3, 0); + visualizer.registerToolbarItem("item2", () => document.createElement("div"), "button", 1, 0); + visualizer.registerToolbarItem("item3", () => document.createElement("div"), "button", 2, 0); + + const result = visualizer.getSortedToolbarItemCreators(); + + expect(result).toHaveLength(3); + expect(result[0].name).toBe("item2"); // index 1 + expect(result[1].name).toBe("item3"); // index 2 + expect(result[2].name).toBe("item1"); // index 3 + }); + + test("should sort groups by groupIndex", () => { + // Register items in different groups with different group indices + visualizer.registerToolbarItem("group1_item1", () => document.createElement("div"), "button", 1, 2); + visualizer.registerToolbarItem("group0_item1", () => document.createElement("div"), "dropdown", 1, 0); + visualizer.registerToolbarItem("group1_item2", () => document.createElement("div"), "button", 2, 2); + visualizer.registerToolbarItem("group0_item2", () => document.createElement("div"), "dropdown", 2, 0); + + const result = visualizer.getSortedToolbarItemCreators(); + + expect(result).toHaveLength(4); + // First group (groupIndex 0) should come first + expect(result[0].type).toBe("dropdown"); + expect(result[1].type).toBe("dropdown"); + // Second group (groupIndex 2) should come second + expect(result[2].type).toBe("button"); + expect(result[3].type).toBe("button"); + }); + + test("should combine onGetToolbarItemCreators with registered items", () => { + // Register items directly + visualizer.registerToolbarItem("direct_item", () => document.createElement("div"), "button", 1, 0); + + // Set onGetToolbarItemCreators function + visualizer.onGetToolbarItemCreators = () => ({ + "dynamic_item": { + creator: () => document.createElement("div"), + type: "dropdown" as const, + index: 2, + groupIndex: 0 + } + }); + + const result = visualizer.getSortedToolbarItemCreators(); + + expect(result).toHaveLength(2); + expect(result[0].name).toBe("direct_item"); // index 1 + expect(result[1].name).toBe("dynamic_item"); // index 2 + }); + + test("should handle items with default index and groupIndex values", () => { + // Register items without specifying index and groupIndex (should use defaults) + visualizer.registerToolbarItem("default_item1", () => document.createElement("div"), "button"); + visualizer.registerToolbarItem("default_item2", () => document.createElement("div"), "filter"); + + const result = visualizer.getSortedToolbarItemCreators(); + + expect(result).toHaveLength(2); + expect(result[0].type).toBe("button"); // groupIndex 0 (default) + expect(result[1].type).toBe("filter"); // groupIndex 0 (default) + }); + + test("should maintain correct structure of returned items", () => { + const creator = () => document.createElement("div"); + visualizer.registerToolbarItem("test_item", creator, "button", 1, 2); + + const result = visualizer.getSortedToolbarItemCreators(); + + expect(result).toHaveLength(1); + expect(result[0]).toEqual({ + name: "test_item", + creator: creator, + type: "button", + index: 1, + groupIndex: 2 + }); + }); + + test("should handle multiple item types with complex sorting", () => { + // Register items with various types, indices, and group indices + visualizer.registerToolbarItem("filter1", () => document.createElement("div"), "filter", 1, 0); + visualizer.registerToolbarItem("button1", () => document.createElement("div"), "button", 3, 1); + visualizer.registerToolbarItem("dropdown1", () => document.createElement("div"), "dropdown", 2, 0); + visualizer.registerToolbarItem("filter2", () => document.createElement("div"), "filter", 4, 0); + visualizer.registerToolbarItem("button2", () => document.createElement("div"), "button", 1, 1); + visualizer.registerToolbarItem("license1", () => document.createElement("div"), "license", 1, 2); + + const result = visualizer.getSortedToolbarItemCreators(); + + expect(result).toHaveLength(6); + + // Check that groups are sorted by groupIndex + const groupTypes = result.map(item => item.type); + expect(groupTypes).toEqual(["filter", "filter", "dropdown", "button", "button", "license"]); + + // Check that items within each group are sorted by index + const filterItems = result.filter(item => item.type === "filter"); + expect(filterItems[0].name).toBe("filter1"); // index 1 + expect(filterItems[1].name).toBe("filter2"); // index 4 + + const buttonItems = result.filter(item => item.type === "button"); + expect(buttonItems[0].name).toBe("button2"); // index 1 + expect(buttonItems[1].name).toBe("button1"); // index 3 + }); + + test("should handle empty onGetToolbarItemCreators", () => { + visualizer.onGetToolbarItemCreators = () => ({}); + visualizer.registerToolbarItem("test_item", () => document.createElement("div"), "button", 1, 0); + + const result = visualizer.getSortedToolbarItemCreators(); + + expect(result).toHaveLength(1); + expect(result[0].name).toBe("test_item"); + }); + + test("should handle undefined onGetToolbarItemCreators", () => { + visualizer.onGetToolbarItemCreators = undefined; + visualizer.registerToolbarItem("test_item", () => document.createElement("div"), "button", 1, 0); + + const result = visualizer.getSortedToolbarItemCreators(); + + expect(result).toHaveLength(1); + expect(result[0].name).toBe("test_item"); + }); + }); +}); \ No newline at end of file diff --git a/tests/vizualizerBase.test.ts b/tests/vizualizerBase.test.ts index 9afbbaf70..130b0008c 100644 --- a/tests/vizualizerBase.test.ts +++ b/tests/vizualizerBase.test.ts @@ -2,22 +2,11 @@ import { VisualizerBase, IDataInfo } from "../src/visualizerBase"; import { QuestionDropdownModel, SurveyModel } from "survey-core"; test("custom colors", () => { - expect(new VisualizerBase(null, null).getColors(1)).toEqual([ - "#86e1fb", - "#3999fb", - "#ff6771", - "#1eb496", - "#ffc152", - "#aba1ff", - "#7d8da5", - "#4ec46c", - "#cf37a6", - "#4e6198", - ]); + expect(VisualizerBase.getColors(1)).toEqual(VisualizerBase["colors"]); VisualizerBase.customColors = ["red", "green", "blue"]; - expect(new VisualizerBase(null, null).getColors(2)).toEqual([ + expect(VisualizerBase.getColors(2)).toEqual([ "red", "green", "blue", @@ -79,7 +68,8 @@ test("Use valueName for data https://surveyjs.answerdesk.io/internal/ticket/deta expect(visualizer.name).toEqual("q1"); question.valueName = "q1value"; - expect(visualizer.name).toEqual("q1value"); + expect(visualizer.name).toEqual("q1"); + expect(visualizer.dataNames[0]).toEqual("q1value"); }); test("options.labelTruncateLength", () => { @@ -134,7 +124,7 @@ test("VisualizerBase supportSelection and allowSelection option", () => { vis = new VisualizerBase(q, [], { allowSelection: true }); expect(vis.supportSelection).toBe(false); - vis = new VisualizerBase(q, [], { allowSelection: false }); + vis = new VisualizerBase(q, [], { allowSelection: false }); expect(vis.supportSelection).toBe(false); }); diff --git a/tests/wordcloud.test.ts b/tests/wordcloud.test.ts index 79a4b2e5c..39dca8cd9 100644 --- a/tests/wordcloud.test.ts +++ b/tests/wordcloud.test.ts @@ -7,13 +7,12 @@ test("remove stopwords and clean punktuation", async () => { { q1: "The Thimes!" }, { q1: "mega, (mega) Super answer." }, ]); - var data = await wc.getCalculatedValues(); - expect(Object.keys(data).length).toEqual(4); - expect(data.filter((d) => d[0] === "The").length).toEqual(0); - expect(data.filter((d) => d[0] === "mega").length).toEqual(1); - expect(data.filter((d) => d[0] === "mega")[0][0]).toEqual("mega"); - expect(data.filter((d) => d[0] === "mega")[0][1]).toEqual(2); - expect(data[0][0]).toEqual("thimes"); + var data = (await wc.getCalculatedValues()); + + expect(data).toEqual({ + data: [[1, 2, 1, 1]], + values: ["thimes", "mega", "super", "answer"], + }); }); test("WordCloudWidget constructor", () => { @@ -56,10 +55,10 @@ test("getCalculatedValues keeps umlauts", async () => { { q1: "Gro\u00DFmutter" }, { q1: "Gro\u00DFmutter" }, ]); - var data = await wc.getCalculatedValues(); - expect(Object.keys(data).length).toEqual(1); - expect(data[0][0]).toBe("gro\u00DFmutter"); - expect(data[0][1]).toBe(2); + var data = (await wc.getCalculatedValues()); + expect(data.values.length).toEqual(1); + expect(data.values[0]).toBe("gro\u00DFmutter"); + expect(data.data[0][0]).toBe(2); }); test("convertFromExternalData", () => { @@ -74,11 +73,9 @@ test("convertFromExternalData", () => { "two2": 1, }; const calculatedData = (wc as any).getCalculatedValuesCore(); - expect(calculatedData).toEqual([ - ["großmutter", 2], - ["string", 2], - ["one1", 1], - ["two2", 1], - ]); + expect(calculatedData).toEqual({ + data: [[2, 2, 1, 1]], + values: ["großmutter", "string", "one1", "two2"], + }); expect(wc.convertFromExternalData(externalCalculatedData)).toStrictEqual(calculatedData); }); diff --git a/tsconfig.summary.core.json b/tsconfig.summary.core.json deleted file mode 100644 index 38f3cef84..000000000 --- a/tsconfig.summary.core.json +++ /dev/null @@ -1,25 +0,0 @@ -{ - "compilerOptions": { - "target": "es5", - "module": "es2015", - "lib": [ - "DOM", - "ES5", - "ES2015.Promise", - "es6" - ], - "sourceMap": false, - "noImplicitAny": false, - "importHelpers": false, - "experimentalDecorators": true, - "moduleResolution": "node", - "allowSyntheticDefaultImports": true, - "declaration": true, - "emitDeclarationOnly": true, - "skipLibCheck": true, - "outDir": "build/survey-analytics.types/" - }, - "include": [ - "src/entries/summary.core.ts" - ] -} \ No newline at end of file diff --git a/tsconfig.summary.json b/tsconfig.summary.json deleted file mode 100644 index b5708a357..000000000 --- a/tsconfig.summary.json +++ /dev/null @@ -1,25 +0,0 @@ -{ - "compilerOptions": { - "target": "es5", - "module": "es2015", - "lib": [ - "DOM", - "ES5", - "ES2015.Promise", - "es6" - ], - "sourceMap": false, - "noImplicitAny": false, - "importHelpers": false, - "experimentalDecorators": true, - "moduleResolution": "node", - "allowSyntheticDefaultImports": true, - "declaration": true, - "emitDeclarationOnly": true, - "skipLibCheck": true, - "outDir": "build/survey-analytics.types/" - }, - "include": [ - "src/entries/summary.ts" - ] -} \ No newline at end of file diff --git a/tsconfig.tabulator.json b/tsconfig.tabulator.json deleted file mode 100644 index 05c09ea2f..000000000 --- a/tsconfig.tabulator.json +++ /dev/null @@ -1,25 +0,0 @@ -{ - "compilerOptions": { - "target": "es5", - "module": "es2015", - "lib": [ - "DOM", - "ES5", - "ES2015.Promise", - "es6" - ], - "sourceMap": false, - "noImplicitAny": false, - "importHelpers": false, - "experimentalDecorators": true, - "moduleResolution": "node", - "allowSyntheticDefaultImports": true, - "declaration": true, - "emitDeclarationOnly": true, - "skipLibCheck": true, - "outDir": "build/survey-analytics-tabulator.types/" - }, - "include": [ - "src/entries/tabulator.ts" - ] -} \ No newline at end of file diff --git a/tsconfig.types.apexcharts.json b/tsconfig.types.apexcharts.json new file mode 100644 index 000000000..c929cf779 --- /dev/null +++ b/tsconfig.types.apexcharts.json @@ -0,0 +1,9 @@ +{ + "extends": "./tsconfig.types.json", + "compilerOptions": { + "outDir": "build/survey-analytics-apexcharts.types/" + }, + "include": [ + "src/entries/apexcharts.ts" + ] +} diff --git a/tsconfig.types.plotly.json b/tsconfig.types.plotly.json new file mode 100644 index 000000000..219b2673b --- /dev/null +++ b/tsconfig.types.plotly.json @@ -0,0 +1,9 @@ +{ + "extends": "./tsconfig.types.json", + "compilerOptions": { + "outDir": "build/survey-analytics-plotly.types/" + }, + "include": [ + "src/entries/plotly.ts" + ] +} diff --git a/tsconfig.types.summary.core.json b/tsconfig.types.summary.core.json new file mode 100644 index 000000000..cace2ed3d --- /dev/null +++ b/tsconfig.types.summary.core.json @@ -0,0 +1,6 @@ +{ + "extends": "./tsconfig.types.json", + "include": [ + "src/entries/summary.core.ts" + ] +} diff --git a/tsconfig.types.summary.json b/tsconfig.types.summary.json new file mode 100644 index 000000000..d2b4fea66 --- /dev/null +++ b/tsconfig.types.summary.json @@ -0,0 +1,6 @@ +{ + "extends": "./tsconfig.types.json", + "include": [ + "src/entries/summary.ts" + ] +} diff --git a/tsconfig.types.tabulator.json b/tsconfig.types.tabulator.json new file mode 100644 index 000000000..7d85a693d --- /dev/null +++ b/tsconfig.types.tabulator.json @@ -0,0 +1,9 @@ +{ + "extends": "./tsconfig.types.json", + "compilerOptions": { + "outDir": "build/survey-analytics-tabulator.types/" + }, + "include": [ + "src/entries/tabulator.ts" + ] +} diff --git a/webpack.config.js b/webpack.config.js index 94a76708c..dce2cd800 100644 --- a/webpack.config.js +++ b/webpack.config.js @@ -38,6 +38,66 @@ PascalCaseNamePlugin.prototype.apply = function (compiler) { }); }; +function SuppressJsForFontlessChunksPlugin(options) { } +SuppressJsForFontlessChunksPlugin.prototype.apply = function (compiler) { + // compiler.hooks.emit.tap('SuppressJsForFontlessChunksPlugin', (compilation) => { + // for (const chunk of compilation.chunks) { + // if (chunk.name && chunk.name.includes('fontless')) { + // const files = [...chunk.files]; // Create a copy to avoid modification during iteration + // for (const file of files) { + // console.log(file); + // if (file.includes('.js')) { + // delete compilation.assets[file]; + // chunk.files = chunk.files.filter(f => f !== file); + // } + // } + // } + // } + // }); + + // First pass: remove from compilation in emit phase + compiler.hooks.emit.tap('SuppressJsForFontlessChunksPlugin', (compilation) => { + for (const chunk of compilation.chunks) { + if (chunk.name && chunk.name.includes('fontless')) { + const files = [...chunk.files]; + for (const file of files) { + if (file.endsWith('.js') || file.includes('.js.')) { + delete compilation.assets[file]; + chunk.files = chunk.files.filter(f => f !== file); + } + } + } + } + }); + + // Second pass: clean up any remaining files after emit + compiler.hooks.done.tap('SuppressJsForFontlessChunksPlugin', (stats) => { + const fs = require('fs'); + const path = require('path'); + const outputPath = stats.compilation.outputOptions.path; + + if (!outputPath) return; + + for (const chunk of stats.compilation.chunks) { + if (chunk.name && chunk.name.includes('fontless')) { + const jsFilePatterns = ['.js', '.js.']; + const files = fs.readdirSync(outputPath).filter(file => + file.includes(chunk.name) && jsFilePatterns.some(pattern => file.includes(pattern)) + ); + + for (const file of files) { + try { + fs.unlinkSync(path.join(outputPath, file)); + console.log(`Cleaned up: ${file}`); + } catch (err) { + console.warn(`Could not delete ${file}:`, err.message); + } + } + } + } + }); +} + const today = new Date(); const year = today.getFullYear(); @@ -84,6 +144,16 @@ function getPercentageHandler(emitNonSourceFiles, buildPath) { "import": "./fesm/survey.analytics.tabulator.mjs", "require": "./survey.analytics.tabulator.js" }, + "./survey.analytics.apexcharts": { + "types": "./survey.analytics.apexcharts.d.ts", + "import": "./fesm/survey.analytics.apexcharts.mjs", + "require": "./survey.analytics.apexcharts.js" + }, + "./survey.analytics.plotly": { + "types": "./survey.analytics.plotly.d.ts", + "import": "./fesm/survey.analytics.plotly.mjs", + "require": "./survey.analytics.plotly.js" + }, } packageJson.module = "fesm/survey.analytics.mjs"; fs.writeFileSync( @@ -111,6 +181,10 @@ module.exports = function (options) { ), "survey.analytics": path.resolve(__dirname, "./src/entries/summary"), "survey.analytics.core": path.resolve(__dirname, "./src/entries/summary.core"), + "survey.analytics.apexcharts": path.resolve(__dirname, "./src/entries/apexcharts"), + "survey.analytics.apexcharts.fontless": path.resolve(__dirname, "./src/entries/apexcharts.fontless"), + "survey.analytics.plotly": path.resolve(__dirname, "./src/entries/plotly"), + "survey.analytics.plotly.fontless": path.resolve(__dirname, "./src/entries/plotly.fontless"), "survey.analytics.mongo": path.resolve(__dirname, "./src/entries/mongo"), }, resolve: { @@ -193,6 +267,12 @@ module.exports = function (options) { commonjs: "tabulator-tables", amd: "tabulator-tables", }, + "apexcharts": { + root: "ApexCharts", + commonjs2: "apexcharts", + commonjs: "apexcharts", + amd: "apexcharts", + }, "mongodb": { root: "MongoDB", commonjs2: "mongodb", @@ -214,6 +294,7 @@ module.exports = function (options) { new webpack.BannerPlugin({ banner: banner, }), + new SuppressJsForFontlessChunksPlugin(), ], devServer: { static: {