diff options
author | Robert Jaros <rjaros@finn.pl> | 2019-03-10 14:12:00 +0100 |
---|---|---|
committer | Robert Jaros <rjaros@finn.pl> | 2019-03-10 14:12:00 +0100 |
commit | c1b79ad6549ce8dc3a2398fa1e4a8b34b09eecea (patch) | |
tree | 9244923c93b6f17d8f58cb94c4a83a2619a42469 | |
parent | c13d0441dddf31ef019333fd16378b3fc56003a4 (diff) | |
download | kvision-c1b79ad6549ce8dc3a2398fa1e4a8b34b09eecea.tar.gz kvision-c1b79ad6549ce8dc3a2398fa1e4a8b34b09eecea.tar.bz2 kvision-c1b79ad6549ce8dc3a2398fa1e4a8b34b09eecea.zip |
New module with support for drawing charts based on chart.js library.
14 files changed, 2154 insertions, 1 deletions
@@ -7,6 +7,14 @@ KVision - object oriented Web UI framework for Kotlin/JS. KVision core classes. This includes base interfaces for all components, CSS enums (for colors, borders, backgrounds, fonts, text and position) and the main Widget class. +# Package pl.treksoft.kvision.chart + +Full-featured chart component based on chart.js library. + +# Package pl.treksoft.kvision.chart.js + +Kotlin bindings for chart.js API. + # Package pl.treksoft.kvision.data Base component and container class with data binding support for observable data model. diff --git a/build.gradle b/build.gradle index c2610971..ce6e62e1 100644 --- a/build.gradle +++ b/build.gradle @@ -167,6 +167,7 @@ dokka { 'kvision-modules/kvision-upload/src/main/kotlin', 'kvision-modules/kvision-handlebars/src/main/kotlin', 'kvision-modules/kvision-i18n/src/main/kotlin', + 'kvision-modules/kvision-chart/src/main/kotlin', 'kvision-modules/kvision-remote/src/main/kotlin', 'kvision-modules/kvision-select-remote/src/main/kotlin', 'kvision-modules/kvision-common/src/main/kotlin', diff --git a/kvision-modules/kvision-chart/build.gradle b/kvision-modules/kvision-chart/build.gradle new file mode 100644 index 00000000..4d4ba4df --- /dev/null +++ b/kvision-modules/kvision-chart/build.gradle @@ -0,0 +1,12 @@ +apply from: "../shared.gradle" + +kotlinFrontend { + + npm { + dependency("chart.js", "2.7.3") + devDependency("karma", "3.1.4") + devDependency("karma-chrome-launcher", "2.2.0") + devDependency("qunit", "2.8.0") + } + +} diff --git a/kvision-modules/kvision-chart/package.json.d/project.info b/kvision-modules/kvision-chart/package.json.d/project.info new file mode 100644 index 00000000..4b4a6303 --- /dev/null +++ b/kvision-modules/kvision-chart/package.json.d/project.info @@ -0,0 +1,3 @@ +{ + "description": "KVision Chart module" +} diff --git a/kvision-modules/kvision-chart/src/main/kotlin/pl/treksoft/kvision/KVManagerChart.kt b/kvision-modules/kvision-chart/src/main/kotlin/pl/treksoft/kvision/KVManagerChart.kt new file mode 100644 index 00000000..73a0f2b9 --- /dev/null +++ b/kvision-modules/kvision-chart/src/main/kotlin/pl/treksoft/kvision/KVManagerChart.kt @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2017-present Robert Jaros + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ +package pl.treksoft.kvision + +internal val kVManagerChartInit = KVManagerChart.init() + +/** + * Internal singleton object which initializes and configures KVision Chart module. + */ +@Suppress("EmptyCatchBlock", "TooGenericExceptionCaught") +internal object KVManagerChart { + fun init() {} + + private val chart = try { + require("chart.js/dist/Chart.bundle.min.js") + } catch (e: Throwable) { + } + +} diff --git a/kvision-modules/kvision-chart/src/main/kotlin/pl/treksoft/kvision/chart/Chart.kt b/kvision-modules/kvision-chart/src/main/kotlin/pl/treksoft/kvision/chart/Chart.kt new file mode 100644 index 00000000..4681d9c4 --- /dev/null +++ b/kvision-modules/kvision-chart/src/main/kotlin/pl/treksoft/kvision/chart/Chart.kt @@ -0,0 +1,129 @@ +/* + * Copyright (c) 2017-present Robert Jaros + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ +package pl.treksoft.kvision.chart + +import com.github.snabbdom.VNode +import pl.treksoft.kvision.chart.js.Chart.ChartConfiguration +import pl.treksoft.kvision.core.Container +import pl.treksoft.kvision.core.Widget + +/** + * Chart component. + * + * @constructor + * @param configuration chart configuration + * @param chartWidth chart width in pixels + * @param chartHeight chart height in pixels + * @param classes a set of CSS class names + */ +open class Chart( + configuration: Configuration, + chartWidth: Int? = null, + chartHeight: Int? = null, + classes: Set<String> = setOf() +) : Widget(classes) { + + /** + * Chart configuration. + */ + var configuration + get() = chartCanvas.configuration + set(value) { + chartCanvas.configuration = value + } + + internal val chartCanvas: ChartCanvas = ChartCanvas(chartWidth, chartHeight, configuration) + + override fun render(): VNode { + return render("div", arrayOf(chartCanvas.renderVNode())) + } + + /** + * Returns chart configuration in the form of native JS object. + */ + open fun getNativeConfig(): ChartConfiguration? { + return chartCanvas.getNativeConfig() + } + + /** + * Resets the chart. + */ + open fun reset() { + chartCanvas.reset() + } + + /** + * Renders the chart. + * @param duration animation duration + * @param lazy if true, the animation can be interrupted by other animations + */ + open fun render(duration: Int? = null, lazy: Boolean = false) { + chartCanvas.render(duration, lazy) + } + + /** + * Stops the animation. + */ + open fun stop() { + chartCanvas.stop() + } + + /** + * Resizes the chart to the size of the container. + */ + open fun resizeChart() { + chartCanvas.resizeChart() + } + + /** + * Clears the chart. + */ + open fun clearChart() { + chartCanvas.clearChart() + } + + /** + * Returns a base64 encoded string of the chart in its current state. + */ + open fun toBase64Image(): String? { + return chartCanvas.toBase64Image() + } + + companion object { + /** + * DSL builder extension function. + * + * It takes the same parameters as the constructor of the built component. + */ + fun Container.chart( + configuration: Configuration, + chartWidth: Int? = null, + chartHeight: Int? = null, + classes: Set<String> = setOf(), + init: (Chart.() -> Unit)? = null + ): Chart { + val chart = Chart(configuration, chartWidth, chartHeight, classes).apply { init?.invoke(this) } + this.add(chart) + return chart + } + } +} diff --git a/kvision-modules/kvision-chart/src/main/kotlin/pl/treksoft/kvision/chart/ChartCanvas.kt b/kvision-modules/kvision-chart/src/main/kotlin/pl/treksoft/kvision/chart/ChartCanvas.kt new file mode 100644 index 00000000..09b68633 --- /dev/null +++ b/kvision-modules/kvision-chart/src/main/kotlin/pl/treksoft/kvision/chart/ChartCanvas.kt @@ -0,0 +1,94 @@ +/* + * Copyright (c) 2017-present Robert Jaros + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ +package pl.treksoft.kvision.chart + +import com.github.snabbdom.VNode +import pl.treksoft.kvision.chart.js.Chart.ChartConfiguration +import pl.treksoft.kvision.html.Canvas +import pl.treksoft.kvision.i18n.I18n +import pl.treksoft.kvision.chart.js.Chart as JsChart + +internal class ChartCanvas( + canvasWidth: Int? = null, + canvasHeight: Int? = null, + configuration: Configuration, + classes: Set<String> = setOf() +) : + Canvas(canvasWidth, canvasHeight, classes) { + + var configuration: Configuration = configuration + set(value) { + field = value + jsChart?.config = value.toJs(this::translate) + jsChart?.update() + } + + private var jsChart: JsChart? = null + + override fun render(): VNode { + if (lastLanguage != null && lastLanguage != I18n.language) { + jsChart?.config = configuration.toJs(this::translate) + jsChart?.update() + } + return render("canvas") + } + + override fun afterInsert(node: VNode) { + super.afterInsert(node) + jsChart = + JsChart(this.context2D, configuration.toJs(this::translate)) + } + + override fun afterDestroy() { + jsChart?.destroy() + jsChart = null + } + + fun getNativeConfig(): ChartConfiguration? { + return jsChart?.config + } + + fun reset() { + jsChart?.reset() + } + + fun render(duration: Int? = null, lazy: Boolean = false) { + jsChart?.render(duration, lazy) + } + + fun stop() { + jsChart?.stop() + } + + fun resizeChart() { + jsChart?.resize() + } + + fun clearChart() { + jsChart?.clear() + } + + fun toBase64Image(): String? { + return jsChart?.toBase64Image() + } + +} diff --git a/kvision-modules/kvision-chart/src/main/kotlin/pl/treksoft/kvision/chart/Configuration.kt b/kvision-modules/kvision-chart/src/main/kotlin/pl/treksoft/kvision/chart/Configuration.kt new file mode 100644 index 00000000..7b1cddd6 --- /dev/null +++ b/kvision-modules/kvision-chart/src/main/kotlin/pl/treksoft/kvision/chart/Configuration.kt @@ -0,0 +1,919 @@ +/* + * Copyright (c) 2017-present Robert Jaros + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ +@file:Suppress("TooManyFunctions") + +package pl.treksoft.kvision.chart + +import org.w3c.dom.events.MouseEvent +import pl.treksoft.kvision.chart.js.Chart +import pl.treksoft.kvision.core.Color +import pl.treksoft.kvision.core.FontStyle +import pl.treksoft.kvision.utils.obj + + +/** + * Chart types. + */ +enum class ChartType(internal val type: String) { + LINE("line"), + BAR("bar"), + HORIZONTALBAR("horizontalBar"), + RADAR("radar"), + DOUGHNUT("doughnut"), + PIE("pie"), + POLARAREA("polarArea"), + BUBBLE("bubble"), + SCATTER("scatter") +} + +/** + * Chart interaction modes. + */ +enum class InteractionMode(internal val mode: String) { + POINT("point"), + NEAREST("nearest"), + INDEX("index"), + DATASET("dataset"), + X("x"), + Y("y") +} + +/** + * Chart animation easings. + */ +enum class Eeasing(internal val mode: String) { + LINEAR("linear"), + EASEINQUAD("easeInQuad"), + EASEOUTQUAD("easeOutQuad"), + EASEINOUTQUAD("easeInOutQuad"), + EASEINCUBIC("easeInCubic"), + EASEOUTCUBIC("easeOutCubic"), + EASEINOUTCUBIC("easeInOutCubic"), + EASEINQUART("easeInQuart"), + EASEOUTQUART("easeOutQuart"), + EASEINOUTQUART("easeInOutQuart"), + EASEINQUINT("easeInQuint"), + EASEOUTQUINT("easeOutQuint"), + EASEINOUTQUINT("easeInOutQuint"), + EASEINSINE("easeInSine"), + EASEOUTSINE("easeOutSine"), + EASEINOUTSINE("easeInOutSine"), + EASEINEXPO("easeInExpo"), + EASEOUTEXPO("easeOutExpo"), + EASEINOUTEXPO("easeInOutExpo"), + EASEINCIRC("easeInCirc"), + EASEOUTCIRC("easeOutCirc"), + EASEINOUTCIRC("easeInOutCirc"), + EASEINELASTIC("easeInElastic"), + EASEOUTELASTIC("easeOutElastic"), + EASEINOUTELASTIC("easeInOutElastic"), + EASEINBACK("easeInBack"), + EASEOUTBACK("easeOutBack"), + EASEINOUTBACK("easeInOutBack"), + EASEINBOUNCE("easeInBounce"), + EASEOUTBOUNCE("easeOutBounce"), + EASEINOUTBOUNCE("easeInOutBounce") +} + +/** + * Chart objects positions. + */ +enum class Position(internal val position: String) { + TOP("top"), + LEFT("left"), + RIGHT("right"), + BOTTOM("bottom") +} + +/** + * Chart tooltip positions. + */ +enum class TooltipPosition(internal val mode: String) { + AVERAGE("average"), + NEAREST("nearest") +} + +/** + * Chart point styles. + */ +enum class PointStyle(internal val style: String) { + CIRCLE("circle"), + CROSS("cross"), + CROSSROT("crossRot"), + DASH("dash"), + LINE("line"), + RECT("rect"), + RECTROUNDED("rectRounded"), + RECTROT("rectRot"), + START("star"), + TRIANGLE("triangle") +} + +/** + * Chart interpolation modes. + */ +enum class InterpolationMode(internal val mode: String) { + DEFAULT("default"), + MONOTONE("monotone") +} + +/** + * Chart scales. + */ +enum class ScalesType(internal val type: String) { + CATEGORY("category"), + LINEAR("linear"), + LOGARITHMIC("logarithmic"), + TIME("time"), + RADIALLINEAR("radialLinear") +} + +/** + * Canvas line end point styles. + */ +enum class LineCap(internal val mode: String) { + BUTT("butt"), + ROUND("round"), + SQUARE("square") +} + +/** + * Canvas line join styles. + */ +enum class LineJoin(internal val mode: String) { + BEVEL("bevel"), + ROUND("round"), + MITER("miter") +} + +/** + * Chart hover options. + */ +data class HoverOptions( + val mode: InteractionMode = InteractionMode.NEAREST, + val animationDuration: Int = 400, + val intersect: Boolean = true, + val axis: String = "x" +) + +/** + * An extension function to convert configuration class to JS object. + */ +fun HoverOptions.toJs(): dynamic { + return obj { + this.mode = mode.mode + this.animationDuration = animationDuration + this.intersect = intersect + this.axis = axis + } +} + +/** + * Chart animation options. + */ +data class AnimationOptions( + val duration: Int = 1000, + var easing: Eeasing = Eeasing.EASEOUTQUART, + val onProgress: ((obj: Chart.ChartAnimationObject) -> Unit)? = null, + val onComplete: ((obj: Chart.ChartAnimationObject) -> Unit)? = null +) + +/** + * An extension function to convert configuration class to JS object. + */ +fun AnimationOptions.toJs(): dynamic { + return obj { + this.duration = duration + this.easing = easing.mode + if (onProgress != null) this.onProgress = onProgress + if (onComplete != null) this.onComplete = onComplete + } +} + +/** + * Chart layout padding options. + */ +data class LayoutPaddingObject( + val top: Int? = null, + val right: Int? = null, + val bottom: Int? = null, + val left: Int? = null +) + +/** + * An extension function to convert configuration class to JS object. + */ +fun LayoutPaddingObject.toJs(): dynamic { + return obj { + if (top != null) this.top = top + if (right != null) this.right = right + if (bottom != null) this.bottom = bottom + if (left != null) this.left = left + } +} + +/** + * Chart layout options. + */ +data class LayoutOptions(val padding: LayoutPaddingObject) + +/** + * An extension function to convert configuration class to JS object. + */ +fun LayoutOptions.toJs(): dynamic { + return obj { + this.padding = padding.toJs() + } +} + +/** + * Chart legend label options. + */ +data class LegendLabelOptions( + val boxWidth: Int = 40, + val fontSize: Int = 12, + val fontStyle: FontStyle? = null, + val fontColor: Color? = null, + val fontFamily: String? = null, + val padding: Int = 10, + val generateLabels: ((chart: Any) -> Any)? = null, + val filter: ((legendItem: Chart.ChartLegendLabelItem, data: Chart.ChartData) -> Any)? = null, + val usePointStyle: Boolean = false +) + +/** + * An extension function to convert configuration class to JS object. + */ +fun LegendLabelOptions.toJs(): dynamic { + return obj { + this.boxWidth = boxWidth + this.fontSize = fontSize + if (fontStyle != null) this.fontStyle = fontStyle.name + if (fontColor != null) this.fontColor = fontColor.asString() + if (fontFamily != null) this.fontFamily = fontFamily + this.padding = padding + if (generateLabels != null) this.generateLabels = generateLabels + if (filter != null) this.filter = filter + this.usePointStyle = usePointStyle + } +} + +/** + * Chart legend options. + */ +data class LegendOptions( + val display: Boolean = true, + val position: Position = Position.TOP, + val fullWidth: Boolean = true, + val reverse: Boolean = false, + val onClick: ((event: MouseEvent, legendItem: Chart.ChartLegendLabelItem) -> Unit)? = null, + val onHover: ((event: MouseEvent, legendItem: Chart.ChartLegendLabelItem) -> Unit)? = null, + val labels: LegendLabelOptions? = null +) + +/** + * An extension function to convert configuration class to JS object. + */ +fun LegendOptions.toJs(): dynamic { + return obj { + this.display = display + this.position = position.position + this.fullWidth = fullWidth + this.reverse = reverse + if (onClick != null) this.onClick = onClick + if (onHover != null) this.onHover = onHover + if (labels != null) this.labels = labels.toJs() + } +} + +/** + * Chart title options. + */ +data class TitleOptions( + val display: Boolean = false, + val position: Position = Position.TOP, + val fontSize: Int = 12, + val fontStyle: FontStyle? = null, + val fontColor: Color? = null, + val fontFamily: String? = null, + val padding: Int = 10, + val lineHeight: String? = null, + val text: List<String>? = null +) + +/** + * An extension function to convert configuration class to JS object. + */ +fun TitleOptions.toJs(i18nTranslator: (String) -> (String)): dynamic { + return obj { + this.display = display + this.position = position.position + this.fontSize = fontSize + if (fontStyle != null) this.fontStyle = fontStyle.name + if (fontColor != null) this.fontColor = fontColor.asString() + if (fontFamily != null) this.fontFamily = fontFamily + this.padding = padding + if (lineHeight != null) this.lineHeight = lineHeight + if (text != null) this.text = text.map(i18nTranslator).toTypedArray() + } +} + +/** + * Chart tooltips callbacks. + */ +data class TooltipCallback( + val beforeTitle: ((item: Array<Chart.ChartTooltipItem>, data: Chart.ChartData) -> dynamic)? = null, + val title: ((item: Array<Chart.ChartTooltipItem>, data: Chart.ChartData) -> dynamic)? = null, + val afterTitle: ((item: Array<Chart.ChartTooltipItem>, data: Chart.ChartData) -> dynamic)? = null, + val beforeBody: ((item: Array<Chart.ChartTooltipItem>, data: Chart.ChartData) -> dynamic)? = null, + val beforeLabel: ((tooltipItem: Chart.ChartTooltipItem, data: Chart.ChartData) -> dynamic)? = null, + val label: ((tooltipItem: Chart.ChartTooltipItem, data: Chart.ChartData) -> dynamic)? = null, + val labelColor: ((tooltipItem: Chart.ChartTooltipItem, chart: Chart) -> Chart.ChartTooltipLabelColor)? = null, + val labelTextColor: ((tooltipItem: Chart.ChartTooltipItem, chart: Chart) -> String)? = null, + val afterLabel: ((tooltipItem: Chart.ChartTooltipItem, data: Chart.ChartData) -> dynamic)? = null, + val afterBody: ((item: Array<Chart.ChartTooltipItem>, data: Chart.ChartData) -> dynamic)? = null, + val beforeFooter: ((item: Array<Chart.ChartTooltipItem>, data: Chart.ChartData) -> dynamic)? = null, + val footer: ((item: Array<Chart.ChartTooltipItem>, data: Chart.ChartData) -> dynamic)? = null, + val afterFooter: ((item: Array<Chart.ChartTooltipItem>, data: Chart.ChartData) -> dynamic)? = null +) + +/** + * An extension function to convert configuration class to JS object. + */ +@Suppress("ComplexMethod") +fun TooltipCallback.toJs(): dynamic { + return obj { + if (beforeTitle != null) this.beforeTitle = beforeTitle + if (title != null) this.title = title + if (afterTitle != null) this.afterTitle = afterTitle + if (beforeBody != null) this.beforeBody = beforeBody + if (beforeLabel != null) this.beforeLabel = beforeLabel + if (label != null) this.label = label + if (labelColor != null) this.labelColor = labelColor + if (labelTextColor != null) this.labelTextColor = labelTextColor + if (afterLabel != null) this.afterLabel = afterLabel + if (afterBody != null) this.afterBody = afterBody + if (beforeFooter != null) this.beforeFooter = beforeFooter + if (footer != null) this.footer = footer + if (afterFooter != null) this.afterFooter = afterFooter + } +} + +/** + * Chart tooltip options. + */ +data class TooltipOptions( + val enabled: Boolean = true, + val custom: ((a: Any) -> Unit)? = null, + val mode: InteractionMode = InteractionMode.NEAREST, + val intersect: Boolean = true, + val position: TooltipPosition = TooltipPosition.AVERAGE, + val callbacks: TooltipCallback? = null, + val filter: ((item: Chart.ChartTooltipItem, data: Chart.ChartData) -> Boolean)? = null, + val itemSort: ((itemA: Chart.ChartTooltipItem, itemB: Chart.ChartTooltipItem) -> Number)? = null, + val backgroundColor: Color? = null, + val titleFontSize: Int = 12, + val titleFontStyle: FontStyle? = null, + val titleFontColor: Color? = null, + val titleFontFamily: String? = null, + val titleSpacing: Int = 2, + val titleMarginBottom: Int = 6, + val bodyFontSize: Int = 12, + val bodyFontStyle: FontStyle? = null, + val bodyFontColor: Color? = null, + val bodyFontFamily: String? = null, + val bodySpacing: Int = 2, + val footerFontSize: Int = 12, + val footerFontStyle: FontStyle? = null, + val footerFontColor: Color? = null, + val footerFontFamily: String? = null, + val footerSpacing: Int = 2, + val footerMarginTop: Int = 6, + val xPadding: Int = 6, + val yPadding: Int = 6, + val caretPadding: Int = 2, + val caretSize: Int = 5, + val cornerRadius: Int = 6, + val multiKeyBackground: Color? = null, + val displayColors: Boolean = true, + val borderColor: Color? = null, + val borderWidth: Int = 0 +) + +/** + * An extension function to convert configuration class to JS object. + */ +@Suppress("ComplexMethod") +fun TooltipOptions.toJs(): dynamic { + return obj { + this.enabled = enabled + if (custom != null) this.custom = custom + this.mode = mode.mode + this.intersect = intersect + this.position = position.mode + if (callbacks != null) this.callbacks = callbacks.toJs() + if (filter != null) this.filter = filter + if (itemSort != null) this.itemSort = itemSort + if (backgroundColor != null) this.backgroundColor = backgroundColor.asString() + this.titleFontSize = titleFontSize + if (titleFontStyle != null) this.titleFontStyle = titleFontStyle.name + if (titleFontColor != null) this.titleFontColor = titleFontColor.asString() + if (titleFontFamily != null) this.titleFontFamily = titleFontFamily + this.titleSpacing = titleSpacing + this.titleMarginBottom = titleMarginBottom + this.bodyFontSize = bodyFontSize + if (bodyFontStyle != null) this.bodyFontStyle = bodyFontStyle.name + if (bodyFontColor != null) this.bodyFontColor = bodyFontColor.asString() + if (bodyFontFamily != null) this.bodyFontFamily = bodyFontFamily + this.bodySpacing = bodySpacing + this.footerFontSize = footerFontSize + if (footerFontStyle != null) this.footerFontStyle = footerFontStyle.name + if (footerFontColor != null) this.footerFontColor = footerFontColor.asString() + if (footerFontFamily != null) this.footerFontFamily = footerFontFamily + this.footerSpacing = footerSpacing + this.footerMarginTop = footerMarginTop + this.xPadding = xPadding + this.yPadding = yPadding + this.caretPadding = caretPadding + this.caretSize = caretSize + this.cornerRadius = cornerRadius + if (multiKeyBackground != null) this.multiKeyBackground = multiKeyBackground.asString() + this.displayColors = displayColors + if (borderColor != null) this.borderColor = borderColor.asString() + this.borderWidth = borderWidth + } +} + +/** + * Chart point options. + */ +data class PointOptions( + val radius: Int = 3, + val pointStyle: PointStyle = PointStyle.CIRCLE, + val backgroundColor: Color? = null, + val borderWidth: Int = 1, + val borderColor: Color? = null, + val hitRadius: Int = 1, + val hoverRadius: Int = 4, + val hoverBorderWidth: Int = 1 +) + +/** + * An extension function to convert configuration class to JS object. + */ +fun PointOptions.toJs(): dynamic { + return obj { + this.radius = radius + this.pointStyle = pointStyle.style + if (backgroundColor != null) this.backgroundColor = backgroundColor.asString() + this.borderWidth = borderWidth + if (borderColor != null) this.borderColor = borderColor.asString() + this.hitRadius = hitRadius + this.hoverRadius = hoverRadius + this.hoverBorderWidth = hoverBorderWidth + } +} + +/** + * Chart line options. + */ +data class LineOptions( + val cubicInterpolationMode: InterpolationMode = InterpolationMode.DEFAULT, + val tension: Double = 0.2, + val backgroundColor: Color? = null, + val borderWidth: Int = 1, + val borderColor: Color? = null, + val borderCapStyle: LineCap? = null, + val borderDash: List<Any>? = null, + val borderDashOffset: Int = 0, + val borderJoinStyle: LineJoin? = null, + val capBezierPoints: Boolean = true, + val fill: Boolean = true, + val stepped: Boolean = false +) + +/** + * An extension function to convert configuration class to JS object. + */ +fun LineOptions.toJs(): dynamic { + return obj { + this.cubicInterpolationMode = cubicInterpolationMode.mode + this.tension = tension + if (backgroundColor != null) this.backgroundColor = backgroundColor.asString() + this.borderWidth = borderWidth + if (borderColor != null) this.borderColor = borderColor.asString() + if (borderCapStyle != null) this.borderCapStyle = borderCapStyle.mode + if (borderDash != null) this.borderDash = borderDash.toTypedArray() + this.borderDashOffset = borderDashOffset + if (borderJoinStyle != null) this.borderJoinStyle = borderJoinStyle.mode + this.capBezierPoints = capBezierPoints + this.fill = fill + this.stepped = stepped + } +} + +/** + * Chart arc options. + */ +data class ArcOptions( + val backgroundColor: Color? = null, + val borderColor: Color? = null, + val borderWidth: Int = 2 +) + +/** + * An extension function to convert configuration class to JS object. + */ +fun ArcOptions.toJs(): dynamic { + return obj { + if (backgroundColor != null) this.backgroundColor = backgroundColor.asString() + if (borderColor != null) this.borderColor = borderColor.asString() + this.borderWidth = borderWidth + } +} + +/** + * Chart rectangle options. + */ +data class RectangleOptions( + val backgroundColor: Color? = null, + val borderColor: Color? = null, + val borderWidth: Int = 0, + val borderSkipped: Position = Position.BOTTOM +) + +/** + * An extension function to convert configuration class to JS object. + */ +fun RectangleOptions.toJs(): dynamic { + return obj { + if (backgroundColor != null) this.backgroundColor = backgroundColor.asString() + if (borderColor != null) this.borderColor = borderColor.asString() + this.borderWidth = borderWidth + this.borderSkipped = borderSkipped.position + } +} + +/** + * Chart elements options. + */ +data class ElementsOptions( + val point: PointOptions? = null, + val line: LineOptions? = null, + val arc: ArcOptions? = null, + val rectangle: RectangleOptions? = null +) + +/** + * An extension function to convert configuration class to JS object. + */ +fun ElementsOptions.toJs(): dynamic { + return obj { + if (point != null) this.point = point.toJs() + if (line != null) this.line = line.toJs() + if (arc != null) this.arc = arc.toJs() + if (rectangle != null) this.rectangle = rectangle.toJs() + } +} + +/** + * Chart grid line options. + */ +data class GridLineOptions( + val display: Boolean = true, + val color: Color? = null, + val borderDash: List<Int>? = null, + val borderDashOffset: Int = 0, + val lineWidth: Int = 1, + val drawBorder: Boolean = true, + val drawOnChartArea: Boolean = true, + val drawTicks: Boolean = true, + val tickMarkLength: Int = 10, + val zeroLineWidth: Int = 1, + val zeroLineColor: Color? = null, + val zeroLineBorderDash: List<Int>? = null, + val zeroLineBorderDashOffset: Int = 0, + val offsetGridLines: Boolean = false +) + +/** + * An extension function to convert configuration class to JS object. + */ +fun GridLineOptions.toJs(): dynamic { + return obj { + this.display = display + if (color != null) this.color = color.asString() + if (borderDash != null) this.borderDash = borderDash.toTypedArray() + this.borderDashOffset = borderDashOffset + this.lineWidth = lineWidth + this.drawBorder = drawBorder + this.drawOnChartArea = drawOnChartArea + this.drawTicks = drawTicks + this.tickMarkLength = tickMarkLength + this.zeroLineWidth = zeroLineWidth + if (zeroLineColor != null) this.zeroLineColor = zeroLineColor.asString() + if (zeroLineBorderDash != null) this.zeroLineBorderDash = zeroLineBorderDash.toTypedArray() + this.zeroLineBorderDashOffset = zeroLineBorderDashOffset + this.offsetGridLines = offsetGridLines + } +} + +/** + * Chart scale title options. + */ +data class ScaleTitleOptions( + val display: Boolean = false, + val labelString: String? = null, + val fontSize: Int = 12, + val fontStyle: FontStyle? = null, + val fontColor: Color? = null, + val fontFamily: String? = null +) + +/** + * An extension function to convert configuration class to JS object. + */ +fun ScaleTitleOptions.toJs(i18nTranslator: (String) -> (String)): dynamic { + return obj { + this.display = display + if (labelString != null) this.labelString = i18nTranslator(labelString) + this.fontSize = fontSize + if (fontStyle != null) this.fontStyle = fontStyle.name + if (fontColor != null) this.fontColor = fontColor.asString() + if (fontFamily != null) this.fontFamily = fontFamily + } +} + +/** + * Chart tick options. + */ +data class TickOptions( + val callback: ((value: Any, index: Any, values: Any) -> dynamic)? = null, + val display: Boolean = true, + val fontSize: Int = 12, + val fontStyle: FontStyle? = null, + val fontColor: Color? = null, + val fontFamily: String? = null, + val reverse: Boolean = false, + val minor: dynamic = null, + val major: dynamic = null +) + +/** + * An extension function to convert configuration class to JS object. + */ +fun TickOptions.toJs(): dynamic { + return obj { + if (callback != null) this.callback = callback + this.display = display + this.fontSize = fontSize + if (fontStyle != null) this.fontStyle = fontStyle.name + if (fontColor != null) this.fontColor = fontColor.asString() + if (fontFamily != null) this.fontFamily = fontFamily + this.reverse = reverse + if (minor != null) this.minor = minor + if (major != null) this.major = major + } +} + +/** + * Chart scales. + */ +data class ChartScales( + val type: ScalesType? = null, + val display: Boolean = true, + val position: Position? = null, + val gridLines: GridLineOptions? = null, + val scaleLabel: ScaleTitleOptions? = null, + val ticks: TickOptions? = null, + val xAxes: List<dynamic>? = null, + val yAxes: List<dynamic>? = null +) + +/** + * An extension function to convert configuration class to JS object. + */ +fun ChartScales.toJs(i18nTranslator: (String) -> (String)): dynamic { + return obj { + if (type != null) this.type = type.type + this.display = display + if (position != null) this.position = position.position + if (gridLines != null) this.gridLines = gridLines.toJs() + if (scaleLabel != null) this.scaleLabel = scaleLabel.toJs(i18nTranslator) + if (ticks != null) this.ticks = ticks.toJs() + if (xAxes != null) this.xAxes = xAxes.toTypedArray() + if (yAxes != null) this.yAxes = yAxes.toTypedArray() + } +} + +/** + * Chart options. + */ +data class Options( + val responsive: Boolean = true, + val responsiveAnimationDuration: Int = 0, + val aspectRatio: Int = 2, + val maintainAspectRatio: Boolean = true, + val onResize: ((chart: Chart, newSize: Chart.ChartSize) -> Unit)? = null, + val devicePixelRatio: Int? = null, + val hover: HoverOptions? = null, + val events: List<String>? = null, + val onHover: ((chart: Chart, event: MouseEvent, activeElements: Array<Any>) -> Any)? = null, + val onClick: ((chart: Chart, event: MouseEvent, activeElements: Array<Any>) -> Any)? = null, + val animation: AnimationOptions? = null, + val layout: LayoutOptions? = null, + val legend: LegendOptions? = null, + val legendCallback: ((chart: Chart) -> String)? = null, + val title: TitleOptions? = null, + val tooltips: TooltipOptions? = null, + val elements: ElementsOptions? = null, + val scales: ChartScales? = null, + val showLines: Boolean? = null, + val spanGaps: Boolean? = null, + val cutoutPercentage: Int? = null, + val circumference: Double? = null, + val rotation: Double? = null +) + +/** + * An extension function to convert configuration class to JS object. + */ +@Suppress("ComplexMethod") +fun Options.toJs(i18nTranslator: (String) -> (String)): dynamic { + return obj { + this.responsive = responsive + this.responsiveAnimationDuration = responsiveAnimationDuration + this.aspectRatio = aspectRatio + this.maintainAspectRatio = maintainAspectRatio + if (onResize != null) this.onResize = onResize + if (devicePixelRatio != null) this.devicePixelRatio = devicePixelRatio + if (hover != null) this.hover = hover.toJs() + if (events != null) this.events = events.toTypedArray() + if (onHover != null) this.onHover = onHover + if (onClick != null) this.onClick = onClick + if (animation != null) this.animation = animation.toJs() + if (layout != null) this.layout = layout.toJs() + if (legend != null) this.legend = legend.toJs() + if (legendCallback != null) this.legendCallback = legendCallback + if (title != null) this.title = title.toJs(i18nTranslator) + if (tooltips != null) this.tooltips = tooltips.toJs() + if (elements != null) this.elements = elements.toJs() + if (scales != null) this.scales = scales.toJs(i18nTranslator) + if (showLines != null) this.showLines = showLines + if (spanGaps != null) this.spanGaps = spanGaps + if (cutoutPercentage != null) this.cutoutPercentage = cutoutPercentage + if (circumference != null) this.circumference = circumference + if (rotation != null) this.rotation = rotation + } +} + +/** + * Chart data sets. + */ +data class DataSets( + val cubicInterpolationMode: InterpolationMode? = null, + val backgroundColor: List<Color>? = null, + val borderWidth: List<Int>? = null, + val borderColor: List<Color>? = null, + val borderCapStyle: List<LineCap>? = null, + val borderDash: List<Int>? = null, + val borderDashOffset: Int? = null, + val borderJoinStyle: List<LineJoin>? = null, + val borderSkipped: List<Position>? = null, + val data: List<dynamic>? = null, + val fill: Boolean? = null, + val hoverBackgroundColor: List<Color>? = null, + val hoverBorderColor: List<Color>? = null, + val hoverBorderWidth: List<Int>? = null, + val label: String? = null, + val lineTension: Number? = null, + val steppedLine: Boolean? = null, + val pointBorderColor: List<Color>? = null, + val pointBackgroundColor: List<Color>? = null, + val pointBorderWidth: List<Int>? = null, + val pointRadius: List<Int>? = null, + val pointHoverRadius: List<Int>? = null, + val pointHitRadius: List<Int>? = null, + val pointHoverBackgroundColor: List<Color>? = null, + val pointHoverBorderColor: List<Color>? = null, + val pointHoverBorderWidth: List<Int>? = null, + val pointStyle: List<PointStyle>? = null, + val xAxisID: String? = null, + val yAxisID: String? = null, + val type: ChartType? = null, + val hidden: Boolean? = null, + val hideInLegendAndTooltip: Boolean? = null, + val showLine: Boolean? = null, + val stack: String? = null, + val spanGaps: Boolean? = null +) + +/** + * An extension function to convert configuration class to JS object. + */ +@Suppress("ComplexMethod") +fun DataSets.toJs(i18nTranslator: (String) -> (String)): dynamic { + return obj { + if (cubicInterpolationMode != null) this.cubicInterpolationMode = cubicInterpolationMode.mode + if (backgroundColor != null) this.backgroundColor = + backgroundColor.map { it.asString() }.toTypedArray().checkSingleValue() + if (borderWidth != null) this.borderWidth = borderWidth.toTypedArray().checkSingleValue() + if (borderColor != null) this.borderColor = borderColor.map { it.asString() }.toTypedArray().checkSingleValue() + if (borderCapStyle != null) this.borderCapStyle = + borderCapStyle.map { it.mode }.toTypedArray().checkSingleValue() + if (borderDash != null) this.borderDash = borderDash.toTypedArray() + if (borderDashOffset != null) this.borderDashOffset = borderDashOffset + if (borderJoinStyle != null) this.borderJoinStyle = + borderJoinStyle.map { it.mode }.toTypedArray().checkSingleValue() + if (borderSkipped != null) this.borderSkipped = + borderSkipped.map { it.position }.toTypedArray().checkSingleValue() + if (data != null) this.data = data.toTypedArray() + if (fill != null) this.fill = fill + if (hoverBackgroundColor != null) this.hoverBackgroundColor = + hoverBackgroundColor.map { it.asString() }.toTypedArray().checkSingleValue() + if (hoverBorderColor != null) this.hoverBorderColor = + hoverBorderColor.map { it.asString() }.toTypedArray().checkSingleValue() + if (hoverBorderWidth != null) this.hoverBorderWidth = hoverBorderWidth.toTypedArray().checkSingleValue() + if (label != null) this.label = i18nTranslator(label) + if (lineTension != null) this.lineTension = lineTension + if (steppedLine != null) this.steppedLine = steppedLine + if (pointBorderColor != null) this.pointBorderColor = + pointBorderColor.map { it.asString() }.toTypedArray().checkSingleValue() + if (pointBackgroundColor != null) this.pointBackgroundColor = + pointBackgroundColor.map { it.asString() }.toTypedArray().checkSingleValue() + if (pointBorderWidth != null) this.pointBorderWidth = pointBorderWidth.toTypedArray().checkSingleValue() + if (pointRadius != null) this.pointRadius = pointRadius.toTypedArray().checkSingleValue() + if (pointHoverRadius != null) this.pointHoverRadius = pointHoverRadius.toTypedArray().checkSingleValue() + if (pointHitRadius != null) this.pointHitRadius = pointHitRadius.toTypedArray().checkSingleValue() + if (pointHoverBackgroundColor != null) this.pointHoverBackgroundColor = + pointHoverBackgroundColor.map { it.asString() }.toTypedArray().checkSingleValue() + if (pointHoverBorderColor != null) this.pointHoverBorderColor = + pointHoverBorderColor.map { it.asString() }.toTypedArray().checkSingleValue() + if (pointHoverBorderWidth != null) this.pointHoverBorderWidth = + pointHoverBorderWidth.toTypedArray().checkSingleValue() + if (pointStyle != null) this.pointStyle = pointStyle.map { it.style }.toTypedArray().checkSingleValue() + if (xAxisID != null) this.xAxisID = xAxisID + if (yAxisID != null) this.yAxisID = yAxisID + if (type != null) this.type = type.type + if (hidden != null) this.hidden = hidden + if (hideInLegendAndTooltip != null) this.hideInLegendAndTooltip = hideInLegendAndTooltip + if (showLine != null) this.showLine = showLine + if (stack != null) this.stack = stack + if (spanGaps != null) this.spanGaps = spanGaps + } +} + +/** + * Chart configuration. + */ +data class Configuration( + val type: ChartType, + val dataSets: List<DataSets>, + val labels: List<String>? = null, + val options: Options? = null +) + +/** + * An extension function to convert configuration class to JS object. + */ +@Suppress("UNCHECKED_CAST_TO_EXTERNAL_INTERFACE") +fun Configuration.toJs(i18nTranslator: (String) -> (String)): Chart.ChartConfiguration { + return obj { + this.type = type.type + this.data = obj { + if (labels != null) this.labels = labels.map(i18nTranslator).toTypedArray() + this.datasets = dataSets.map { + @Suppress("UnsafeCastFromDynamic") + it.toJs(i18nTranslator) + }.toTypedArray() + } + if (options != null) this.options = options.toJs(i18nTranslator) + } as Chart.ChartConfiguration +} + +private fun Array<dynamic>.checkSingleValue(): dynamic { + if (this.size == 1) { + return this[0] + } else { + return this + } +} diff --git a/kvision-modules/kvision-chart/src/main/kotlin/pl/treksoft/kvision/chart/js/Chart.kt b/kvision-modules/kvision-chart/src/main/kotlin/pl/treksoft/kvision/chart/js/Chart.kt new file mode 100644 index 00000000..7fb47bb0 --- /dev/null +++ b/kvision-modules/kvision-chart/src/main/kotlin/pl/treksoft/kvision/chart/js/Chart.kt @@ -0,0 +1,691 @@ +/* + * Copyright (c) 2017-present Robert Jaros + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ +@file:Suppress( + "INTERFACE_WITH_SUPERCLASS", + "OVERRIDING_FINAL_MEMBER", + "RETURN_TYPE_MISMATCH_ON_OVERRIDE", + "CONFLICTING_OVERLOADS", + "EXTERNAL_DELEGATION", + "NESTED_CLASS_IN_EXTERNAL_INTERFACE", + "unused", "PropertyName", "TooManyFunctions", "VariableNaming", "MaxLineLength" +) + +package pl.treksoft.kvision.chart.js + +import org.w3c.dom.CanvasRenderingContext2D +import org.w3c.dom.HTMLCanvasElement +import org.w3c.dom.events.Event +import org.w3c.dom.events.MouseEvent +import kotlin.js.Json + +external interface Defaults { + var global: Chart.ChartOptions /* Chart.ChartOptions & Chart.ChartFontOptions */ +} + +@Suppress("NOTHING_TO_INLINE", "UnsafeCastFromDynamic") +inline operator fun Defaults.get(key: String): Any? = asDynamic()[key] + +@Suppress("NOTHING_TO_INLINE") +inline operator fun Defaults.set(key: String, value: Any) { + asDynamic()[key] = value +} + +@Suppress("UNREACHABLE_CODE") +open external class Chart { + constructor(context: String, options: ChartConfiguration) + constructor(context: CanvasRenderingContext2D, options: ChartConfiguration) + constructor(context: HTMLCanvasElement, options: ChartConfiguration) + constructor( + context: Array<dynamic /* CanvasRenderingContext2D | HTMLCanvasElement */>, + options: ChartConfiguration + ) + + open var config: ChartConfiguration = definedExternally + open var data: ChartData = definedExternally + open fun destroy(): Any = definedExternally + open fun update(duration: Any? = definedExternally, lazy: Any? = definedExternally): Any = definedExternally + open fun render(duration: Any? = definedExternally, lazy: Any? = definedExternally): Any = definedExternally + open fun stop(): Any = definedExternally + open fun resize(): Any = definedExternally + open fun clear(): Any = definedExternally + open fun reset(): Any = definedExternally + open fun toBase64Image(): String = definedExternally + open fun generateLegend(): Any = definedExternally + open fun getElementAtEvent(e: Any): Any = definedExternally + open fun getElementsAtEvent(e: Any): Array<Any> = definedExternally + open fun getDatasetAtEvent(e: Any): Array<Any> = definedExternally + open fun getDatasetMeta(index: Number): Meta = definedExternally + open var ctx: CanvasRenderingContext2D? = definedExternally + open var canvas: HTMLCanvasElement? = definedExternally + open var chartArea: ChartArea = definedExternally + + companion object { + var Chart: Any? = definedExternally + var pluginService: PluginServiceStatic = definedExternally + var plugins: PluginServiceStatic = definedExternally + var defaults: Defaults = definedExternally + var controllers: Json = definedExternally + var helpers: Json = definedExternally + var Tooltip: ChartTooltipsStaticConfiguration = definedExternally + } + + interface ChartArea { + var top: Number + var right: Number + var bottom: Number + var left: Number + } + + interface ChartLegendItem { + var text: String? get() = definedExternally; set(value) = definedExternally + var fillStyle: String? get() = definedExternally; set(value) = definedExternally + var hidden: Boolean? get() = definedExternally; set(value) = definedExternally + var lineCap: dynamic /* String /* "butt" */ | String /* "round" */ | String /* "square" */ */ get() = definedExternally; set(value) = definedExternally + var lineDash: Array<Number>? get() = definedExternally; set(value) = definedExternally + var lineDashOffset: Number? get() = definedExternally; set(value) = definedExternally + var lineJoin: dynamic /* String /* "round" */ | String /* "bevel" */ | String /* "miter" */ */ get() = definedExternally; set(value) = definedExternally + var lineWidth: Number? get() = definedExternally; set(value) = definedExternally + var strokeStyle: String? get() = definedExternally; set(value) = definedExternally + var pointStyle: dynamic /* String /* "line" */ | String /* "circle" */ | String /* "cross" */ | String /* "crossRot" */ | String /* "dash" */ | String /* "rect" */ | String /* "rectRounded" */ | String /* "rectRot" */ | String /* "star" */ | String /* "triangle" */ */ get() = definedExternally; set(value) = definedExternally + } + + interface ChartLegendLabelItem : ChartLegendItem { + var datasetIndex: Number + } + + interface ChartTooltipItem { + var xLabel: String? get() = definedExternally; set(value) = definedExternally + var yLabel: String? get() = definedExternally; set(value) = definedExternally + var datasetIndex: Number? get() = definedExternally; set(value) = definedExternally + var index: Number? get() = definedExternally; set(value) = definedExternally + } + + interface ChartTooltipLabelColor { + var borderColor: dynamic /* String | CanvasGradient | CanvasPattern | Array<String> */ + var backgroundColor: dynamic /* String | CanvasGradient | CanvasPattern | Array<String> */ + } + + interface ChartTooltipCallback { + val beforeTitle: ((item: Array<ChartTooltipItem>, data: ChartData) -> dynamic /* String | Array<String> */)? get() = definedExternally + val title: ((item: Array<ChartTooltipItem>, data: ChartData) -> dynamic /* String | Array<String> */)? get() = definedExternally + val afterTitle: ((item: Array<ChartTooltipItem>, data: ChartData) -> dynamic /* String | Array<String> */)? get() = definedExternally + val beforeBody: ((item: Array<ChartTooltipItem>, data: ChartData) -> dynamic /* String | Array<String> */)? get() = definedExternally + val beforeLabel: ((tooltipItem: ChartTooltipItem, data: ChartData) -> dynamic /* String | Array<String> */)? get() = definedExternally + val label: ((tooltipItem: ChartTooltipItem, data: ChartData) -> dynamic /* String | Array<String> */)? get() = definedExternally + val labelColor: ((tooltipItem: ChartTooltipItem, chart: Chart) -> ChartTooltipLabelColor)? get() = definedExternally + val labelTextColor: ((tooltipItem: ChartTooltipItem, chart: Chart) -> String)? get() = definedExternally + val afterLabel: ((tooltipItem: ChartTooltipItem, data: ChartData) -> dynamic /* String | Array<String> */)? get() = definedExternally + val afterBody: ((item: Array<ChartTooltipItem>, data: ChartData) -> dynamic /* String | Array<String> */)? get() = definedExternally + val beforeFooter: ((item: Array<ChartTooltipItem>, data: ChartData) -> dynamic /* String | Array<String> */)? get() = definedExternally + val footer: ((item: Array<ChartTooltipItem>, data: ChartData) -> dynamic /* String | Array<String> */)? get() = definedExternally + val afterFooter: ((item: Array<ChartTooltipItem>, data: ChartData) -> dynamic /* String | Array<String> */)? get() = definedExternally + } + + interface ChartAnimationParameter { + var chartInstance: Any? get() = definedExternally; set(value) = definedExternally + var animationObject: Any? get() = definedExternally; set(value) = definedExternally + } + + interface ChartPoint { + var x: dynamic /* String | Number | Date */ get() = definedExternally; set(value) = definedExternally + var y: dynamic /* String | Number | Date */ get() = definedExternally; set(value) = definedExternally + var r: Number? get() = definedExternally; set(value) = definedExternally + var t: dynamic /* String | Number | Date */ get() = definedExternally; set(value) = definedExternally + } + + interface ChartConfiguration { + var type: dynamic /* String /* "line" */ | String /* "bar" */ | String /* "horizontalBar" */ | String /* "radar" */ | String /* "doughnut" */ | String /* "polarArea" */ | String /* "bubble" */ | String /* "pie" */ | String /* "scatter" */ | String */ get() = definedExternally; set(value) = definedExternally + var data: ChartData? get() = definedExternally; set(value) = definedExternally + var options: ChartOptions? get() = definedExternally; set(value) = definedExternally + var plugins: Array<PluginServiceRegistrationOptions>? get() = definedExternally; set(value) = definedExternally + } + + interface ChartData { + var labels: Array<dynamic /* String | Array<String> */>? get() = definedExternally; set(value) = definedExternally + var datasets: Array<ChartDataSets>? get() = definedExternally; set(value) = definedExternally + } + + interface RadialChartOptions : ChartOptions { + var scale: RadialLinearScale? get() = definedExternally; set(value) = definedExternally + } + + interface ChartSize { + var height: Number + var width: Number + } + + interface ChartOptions { + var responsive: Boolean? get() = definedExternally; set(value) = definedExternally + var responsiveAnimationDuration: Number? get() = definedExternally; set(value) = definedExternally + var aspectRatio: Number? get() = definedExternally; set(value) = definedExternally + var maintainAspectRatio: Boolean? get() = definedExternally; set(value) = definedExternally + var events: Array<String>? get() = definedExternally; set(value) = definedExternally + val legendCallback: ((chart: Chart) -> String)? get() = definedExternally + val onHover: ((`this`: Chart, event: MouseEvent, activeElements: Array<Any>) -> Any)? get() = definedExternally + val onClick: ((event: MouseEvent? /*= null*/, activeElements: Array<Any>? /*= null*/) -> Any)? get() = definedExternally + val onResize: ((`this`: Chart, newSize: ChartSize) -> Unit)? get() = definedExternally + var title: ChartTitleOptions? get() = definedExternally; set(value) = definedExternally + var legend: ChartLegendOptions? get() = definedExternally; set(value) = definedExternally + var tooltips: ChartTooltipOptions? get() = definedExternally; set(value) = definedExternally + var hover: ChartHoverOptions? get() = definedExternally; set(value) = definedExternally + var animation: ChartAnimationOptions? get() = definedExternally; set(value) = definedExternally + var elements: ChartElementsOptions? get() = definedExternally; set(value) = definedExternally + var layout: ChartLayoutOptions? get() = definedExternally; set(value) = definedExternally + var scales: ChartScales? get() = definedExternally; set(value) = definedExternally + var showLines: Boolean? get() = definedExternally; set(value) = definedExternally + var spanGaps: Boolean? get() = definedExternally; set(value) = definedExternally + var cutoutPercentage: Number? get() = definedExternally; set(value) = definedExternally + var circumference: Number? get() = definedExternally; set(value) = definedExternally + var rotation: Number? get() = definedExternally; set(value) = definedExternally + var devicePixelRatio: Number? get() = definedExternally; set(value) = definedExternally + var plugins: ChartPluginsOptions? get() = definedExternally; set(value) = definedExternally + } + + interface ChartFontOptions { + var defaultFontColor: dynamic /* String | CanvasGradient | CanvasPattern | Array<String> */ get() = definedExternally; set(value) = definedExternally + var defaultFontFamily: String? get() = definedExternally; set(value) = definedExternally + var defaultFontSize: Number? get() = definedExternally; set(value) = definedExternally + var defaultFontStyle: String? get() = definedExternally; set(value) = definedExternally + } + + interface ChartTitleOptions { + var display: Boolean? get() = definedExternally; set(value) = definedExternally + var position: dynamic /* String /* "left" */ | String /* "right" */ | String /* "top" */ | String /* "bottom" */ */ get() = definedExternally; set(value) = definedExternally + var fullWidth: Boolean? get() = definedExternally; set(value) = definedExternally + var fontSize: Number? get() = definedExternally; set(value) = definedExternally + var fontFamily: String? get() = definedExternally; set(value) = definedExternally + var fontColor: dynamic /* String | CanvasGradient | CanvasPattern | Array<String> */ get() = definedExternally; set(value) = definedExternally + var fontStyle: String? get() = definedExternally; set(value) = definedExternally + var padding: Number? get() = definedExternally; set(value) = definedExternally + var text: dynamic /* String | Array<String> */ get() = definedExternally; set(value) = definedExternally + } + + interface ChartLegendOptions { + var display: Boolean? get() = definedExternally; set(value) = definedExternally + var position: dynamic /* String /* "left" */ | String /* "right" */ | String /* "top" */ | String /* "bottom" */ */ get() = definedExternally; set(value) = definedExternally + var fullWidth: Boolean? get() = definedExternally; set(value) = definedExternally + val onClick: ((event: MouseEvent, legendItem: ChartLegendLabelItem) -> Unit)? get() = definedExternally + val onHover: ((event: MouseEvent, legendItem: ChartLegendLabelItem) -> Unit)? get() = definedExternally + var labels: ChartLegendLabelOptions? get() = definedExternally; set(value) = definedExternally + var reverse: Boolean? get() = definedExternally; set(value) = definedExternally + } + + interface ChartLegendLabelOptions { + var boxWidth: Number? get() = definedExternally; set(value) = definedExternally + var fontSize: Number? get() = definedExternally; set(value) = definedExternally + var fontStyle: String? get() = definedExternally; set(value) = definedExternally + var fontColor: dynamic /* String | CanvasGradient | CanvasPattern | Array<String> */ get() = definedExternally; set(value) = definedExternally + var fontFamily: String? get() = definedExternally; set(value) = definedExternally + var padding: Number? get() = definedExternally; set(value) = definedExternally + val generateLabels: ((chart: Any) -> Any)? get() = definedExternally + val filter: ((legendItem: ChartLegendLabelItem, data: ChartData) -> Any)? get() = definedExternally + var usePointStyle: Boolean? get() = definedExternally; set(value) = definedExternally + } + + interface ChartTooltipOptions { + var enabled: Boolean? get() = definedExternally; set(value) = definedExternally + val custom: ((a: Any) -> Unit)? get() = definedExternally + var mode: dynamic /* String /* "point" */ | String /* "nearest" */ | String /* "single" */ | String /* "label" */ | String /* "index" */ | String /* "x-axis" */ | String /* "dataset" */ | String /* "x" */ | String /* "y" */ */ get() = definedExternally; set(value) = definedExternally + var intersect: Boolean? get() = definedExternally; set(value) = definedExternally + var backgroundColor: dynamic /* String | CanvasGradient | CanvasPattern | Array<String> */ get() = definedExternally; set(value) = definedExternally + var titleFontFamily: String? get() = definedExternally; set(value) = definedExternally + var titleFontSize: Number? get() = definedExternally; set(value) = definedExternally + var titleFontStyle: String? get() = definedExternally; set(value) = definedExternally + var titleFontColor: dynamic /* String | CanvasGradient | CanvasPattern | Array<String> */ get() = definedExternally; set(value) = definedExternally + var titleSpacing: Number? get() = definedExternally; set(value) = definedExternally + var titleMarginBottom: Number? get() = definedExternally; set(value) = definedExternally + var bodyFontFamily: String? get() = definedExternally; set(value) = definedExternally + var bodyFontSize: Number? get() = definedExternally; set(value) = definedExternally + var bodyFontStyle: String? get() = definedExternally; set(value) = definedExternally + var bodyFontColor: dynamic /* String | CanvasGradient | CanvasPattern | Array<String> */ get() = definedExternally; set(value) = definedExternally + var bodySpacing: Number? get() = definedExternally; set(value) = definedExternally + var footerFontFamily: String? get() = definedExternally; set(value) = definedExternally + var footerFontSize: Number? get() = definedExternally; set(value) = definedExternally + var footerFontStyle: String? get() = definedExternally; set(value) = definedExternally + var footerFontColor: dynamic /* String | CanvasGradient | CanvasPattern | Array<String> */ get() = definedExternally; set(value) = definedExternally + var footerSpacing: Number? get() = definedExternally; set(value) = definedExternally + var footerMarginTop: Number? get() = definedExternally; set(value) = definedExternally + var xPadding: Number? get() = definedExternally; set(value) = definedExternally + var yPadding: Number? get() = definedExternally; set(value) = definedExternally + var caretSize: Number? get() = definedExternally; set(value) = definedExternally + var cornerRadius: Number? get() = definedExternally; set(value) = definedExternally + var multiKeyBackground: String? get() = definedExternally; set(value) = definedExternally + var callbacks: ChartTooltipCallback? get() = definedExternally; set(value) = definedExternally + val filter: ((item: ChartTooltipItem, data: ChartData) -> Boolean)? get() = definedExternally + val itemSort: ((itemA: ChartTooltipItem, itemB: ChartTooltipItem) -> Number)? get() = definedExternally + var position: String? get() = definedExternally; set(value) = definedExternally + var caretPadding: Number? get() = definedExternally; set(value) = definedExternally + var displayColors: Boolean? get() = definedExternally; set(value) = definedExternally + var borderColor: dynamic /* String | CanvasGradient | CanvasPattern | Array<String> */ get() = definedExternally; set(value) = definedExternally + var borderWidth: Number? get() = definedExternally; set(value) = definedExternally + } + + interface ChartPluginsOptions + + interface Positioners + + interface ChartTooltipsStaticConfiguration { + var positioners: Positioners + } + + interface ChartHoverOptions { + var mode: dynamic /* String /* "point" */ | String /* "nearest" */ | String /* "single" */ | String /* "label" */ | String /* "index" */ | String /* "x-axis" */ | String /* "dataset" */ | String /* "x" */ | String /* "y" */ */ get() = definedExternally; set(value) = definedExternally + var animationDuration: Number? get() = definedExternally; set(value) = definedExternally + var intersect: Boolean? get() = definedExternally; set(value) = definedExternally + val onHover: ((`this`: Chart, event: MouseEvent, activeElements: Array<Any>) -> Any)? get() = definedExternally + } + + interface ChartAnimationObject { + var currentStep: Number? get() = definedExternally; set(value) = definedExternally + var numSteps: Number? get() = definedExternally; set(value) = definedExternally + var easing: String? get() = definedExternally; set(value) = definedExternally + val render: ((arg: Any) -> Unit)? get() = definedExternally + val onAnimationProgress: ((arg: Any) -> Unit)? get() = definedExternally + val onAnimationComplete: ((arg: Any) -> Unit)? get() = definedExternally + } + + interface ChartAnimationOptions { + var duration: Number? get() = definedExternally; set(value) = definedExternally + var easing: String? get() = definedExternally; set(value) = definedExternally + val onProgress: ((chart: Any) -> Unit)? get() = definedExternally + val onComplete: ((chart: Any) -> Unit)? get() = definedExternally + var animateRotate: Boolean? get() = definedExternally; set(value) = definedExternally + var animateScale: Boolean? get() = definedExternally; set(value) = definedExternally + } + + interface ChartElementsOptions { + var point: ChartPointOptions? get() = definedExternally; set(value) = definedExternally + var line: ChartLineOptions? get() = definedExternally; set(value) = definedExternally + var arc: ChartArcOptions? get() = definedExternally; set(value) = definedExternally + var rectangle: ChartRectangleOptions? get() = definedExternally; set(value) = definedExternally + } + + interface ChartArcOptions { + var backgroundColor: dynamic /* String | CanvasGradient | CanvasPattern | Array<String> */ get() = definedExternally; set(value) = definedExternally + var borderColor: dynamic /* String | CanvasGradient | CanvasPattern | Array<String> */ get() = definedExternally; set(value) = definedExternally + var borderWidth: Number? get() = definedExternally; set(value) = definedExternally + } + + interface ChartLineOptions { + var cubicInterpolationMode: dynamic /* String /* "default" */ | String /* "monotone" */ */ get() = definedExternally; set(value) = definedExternally + var tension: Number? get() = definedExternally; set(value) = definedExternally + var backgroundColor: dynamic /* String | CanvasGradient | CanvasPattern | Array<String> */ get() = definedExternally; set(value) = definedExternally + var borderWidth: Number? get() = definedExternally; set(value) = definedExternally + var borderColor: dynamic /* String | CanvasGradient | CanvasPattern | Array<String> */ get() = definedExternally; set(value) = definedExternally + var borderCapStyle: String? get() = definedExternally; set(value) = definedExternally + var borderDash: Array<Any>? get() = definedExternally; set(value) = definedExternally + var borderDashOffset: Number? get() = definedExternally; set(value) = definedExternally + var borderJoinStyle: String? get() = definedExternally; set(value) = definedExternally + var capBezierPoints: Boolean? get() = definedExternally; set(value) = definedExternally + var fill: dynamic /* Boolean | String /* "top" */ | String /* "bottom" */ | String /* "zero" */ */ get() = definedExternally; set(value) = definedExternally + var stepped: Boolean? get() = definedExternally; set(value) = definedExternally + } + + interface ChartPointOptions { + var radius: Number? get() = definedExternally; set(value) = definedExternally + var pointStyle: dynamic /* String /* "line" */ | String /* "circle" */ | String /* "cross" */ | String /* "crossRot" */ | String /* "dash" */ | String /* "rect" */ | String /* "rectRounded" */ | String /* "rectRot" */ | String /* "star" */ | String /* "triangle" */ */ get() = definedExternally; set(value) = definedExternally + var backgroundColor: dynamic /* String | CanvasGradient | CanvasPattern | Array<String> */ get() = definedExternally; set(value) = definedExternally + var borderWidth: Number? get() = definedExternally; set(value) = definedExternally + var borderColor: dynamic /* String | CanvasGradient | CanvasPattern | Array<String> */ get() = definedExternally; set(value) = definedExternally + var hitRadius: Number? get() = definedExternally; set(value) = definedExternally + var hoverRadius: Number? get() = definedExternally; set(value) = definedExternally + var hoverBorderWidth: Number? get() = definedExternally; set(value) = definedExternally + } + + interface ChartRectangleOptions { + var backgroundColor: dynamic /* String | CanvasGradient | CanvasPattern | Array<String> */ get() = definedExternally; set(value) = definedExternally + var borderWidth: Number? get() = definedExternally; set(value) = definedExternally + var borderColor: dynamic /* String | CanvasGradient | CanvasPattern | Array<String> */ get() = definedExternally; set(value) = definedExternally + var borderSkipped: String? get() = definedExternally; set(value) = definedExternally + } + + interface ChartLayoutOptions { + var padding: dynamic /* Number | ChartLayoutPaddingObject */ get() = definedExternally; set(value) = definedExternally + } + + interface ChartLayoutPaddingObject { + var top: Number? get() = definedExternally; set(value) = definedExternally + var right: Number? get() = definedExternally; set(value) = definedExternally + var bottom: Number? get() = definedExternally; set(value) = definedExternally + var left: Number? get() = definedExternally; set(value) = definedExternally + } + + interface GridLineOptions { + var display: Boolean? get() = definedExternally; set(value) = definedExternally + var color: dynamic /* String | CanvasGradient | CanvasPattern | Array<String> */ get() = definedExternally; set(value) = definedExternally + var borderDash: Array<Number>? get() = definedExternally; set(value) = definedExternally + var borderDashOffset: Number? get() = definedExternally; set(value) = definedExternally + var lineWidth: Number? get() = definedExternally; set(value) = definedExternally + var drawBorder: Boolean? get() = definedExternally; set(value) = definedExternally + var drawOnChartArea: Boolean? get() = definedExternally; set(value) = definedExternally + var drawTicks: Boolean? get() = definedExternally; set(value) = definedExternally + var tickMarkLength: Number? get() = definedExternally; set(value) = definedExternally + var zeroLineWidth: Number? get() = definedExternally; set(value) = definedExternally + var zeroLineColor: dynamic /* String | CanvasGradient | CanvasPattern | Array<String> */ get() = definedExternally; set(value) = definedExternally + var zeroLineBorderDash: Array<Number>? get() = definedExternally; set(value) = definedExternally + var zeroLineBorderDashOffset: Number? get() = definedExternally; set(value) = definedExternally + var offsetGridLines: Boolean? get() = definedExternally; set(value) = definedExternally + } + + interface ScaleTitleOptions { + var display: Boolean? get() = definedExternally; set(value) = definedExternally + var labelString: String? get() = definedExternally; set(value) = definedExternally + var fontColor: dynamic /* String | CanvasGradient | CanvasPattern | Array<String> */ get() = definedExternally; set(value) = definedExternally + var fontFamily: String? get() = definedExternally; set(value) = definedExternally + var fontSize: Number? get() = definedExternally; set(value) = definedExternally + var fontStyle: String? get() = definedExternally; set(value) = definedExternally + } + + interface TickOptions : NestedTickOptions { + var minor: dynamic /* Boolean | NestedTickOptions */ get() = definedExternally; set(value) = definedExternally + var major: dynamic /* Boolean | NestedTickOptions */ get() = definedExternally; set(value) = definedExternally + } + + interface NestedTickOptions { + var autoSkip: Boolean? get() = definedExternally; set(value) = definedExternally + var autoSkipPadding: Number? get() = definedExternally; set(value) = definedExternally + var backdropColor: dynamic /* String | CanvasGradient | CanvasPattern | Array<String> */ get() = definedExternally; set(value) = definedExternally + var backdropPaddingX: Number? get() = definedExternally; set(value) = definedExternally + var backdropPaddingY: Number? get() = definedExternally; set(value) = definedExternally + var beginAtZero: Boolean? get() = definedExternally; set(value) = definedExternally + val callback: ((value: Any, index: Any, values: Any) -> dynamic /* String | Number */)? get() = definedExternally + var display: Boolean? get() = definedExternally; set(value) = definedExternally + var fontColor: dynamic /* String | CanvasGradient | CanvasPattern | Array<String> */ get() = definedExternally; set(value) = definedExternally + var fontFamily: String? get() = definedExternally; set(value) = definedExternally + var fontSize: Number? get() = definedExternally; set(value) = definedExternally + var fontStyle: String? get() = definedExternally; set(value) = definedExternally + var labelOffset: Number? get() = definedExternally; set(value) = definedExternally + var lineHeight: Number? get() = definedExternally; set(value) = definedExternally + var max: Any? get() = definedExternally; set(value) = definedExternally + var maxRotation: Number? get() = definedExternally; set(value) = definedExternally + var maxTicksLimit: Number? get() = definedExternally; set(value) = definedExternally + var min: Any? get() = definedExternally; set(value) = definedExternally + var minRotation: Number? get() = definedExternally; set(value) = definedExternally + var mirror: Boolean? get() = definedExternally; set(value) = definedExternally + var padding: Number? get() = definedExternally; set(value) = definedExternally + var reverse: Boolean? get() = definedExternally; set(value) = definedExternally + var showLabelBackdrop: Boolean? get() = definedExternally; set(value) = definedExternally + var source: dynamic /* String /* "auto" */ | String /* "data" */ | String /* "labels" */ */ get() = definedExternally; set(value) = definedExternally + var stepSize: Number? get() = definedExternally; set(value) = definedExternally + var suggestedMax: Number? get() = definedExternally; set(value) = definedExternally + var suggestedMin: Number? get() = definedExternally; set(value) = definedExternally + } + + interface AngleLineOptions { + var display: Boolean? get() = definedExternally; set(value) = definedExternally + var color: dynamic /* String | CanvasGradient | CanvasPattern | Array<String> */ get() = definedExternally; set(value) = definedExternally + var lineWidth: Number? get() = definedExternally; set(value) = definedExternally + } + + interface PointLabelOptions { + val callback: ((arg: Any) -> Any)? get() = definedExternally + var fontColor: dynamic /* String | CanvasGradient | CanvasPattern | Array<String> */ get() = definedExternally; set(value) = definedExternally + var fontFamily: String? get() = definedExternally; set(value) = definedExternally + var fontSize: Number? get() = definedExternally; set(value) = definedExternally + var fontStyle: String? get() = definedExternally; set(value) = definedExternally + } + + interface LinearTickOptions : TickOptions { + override var maxTicksLimit: Number? get() = definedExternally; set(value) = definedExternally + override var stepSize: Number? get() = definedExternally; set(value) = definedExternally + var precision: Number? get() = definedExternally; set(value) = definedExternally + override var suggestedMin: Number? get() = definedExternally; set(value) = definedExternally + override var suggestedMax: Number? get() = definedExternally; set(value) = definedExternally + } + + interface LogarithmicTickOptions : TickOptions + interface ChartDataSets { + var cubicInterpolationMode: dynamic /* String /* "default" */ | String /* "monotone" */ */ get() = definedExternally; set(value) = definedExternally + var backgroundColor: dynamic /* String | CanvasGradient | CanvasPattern | Array<String> | Array<dynamic /* String | CanvasGradient | CanvasPattern | Array<String> */> */ get() = definedExternally; set(value) = definedExternally + var borderWidth: dynamic /* Number | Array<Number> */ get() = definedExternally; set(value) = definedExternally + var borderColor: dynamic /* String | CanvasGradient | CanvasPattern | Array<String> | Array<dynamic /* String | CanvasGradient | CanvasPattern | Array<String> */> */ get() = definedExternally; set(value) = definedExternally + var borderCapStyle: dynamic /* String /* "butt" */ | String /* "round" */ | String /* "square" */ */ get() = definedExternally; set(value) = definedExternally + var borderDash: Array<Number>? get() = definedExternally; set(value) = definedExternally + var borderDashOffset: Number? get() = definedExternally; set(value) = definedExternally + var borderJoinStyle: dynamic /* String /* "round" */ | String /* "bevel" */ | String /* "miter" */ */ get() = definedExternally; set(value) = definedExternally + var borderSkipped: dynamic /* String /* "left" */ | String /* "right" */ | String /* "top" */ | String /* "bottom" */ */ get() = definedExternally; set(value) = definedExternally + var data: dynamic /* Array<Number> | Array<ChartPoint> */ get() = definedExternally; set(value) = definedExternally + var fill: dynamic /* String | Number | Boolean */ get() = definedExternally; set(value) = definedExternally + var hoverBackgroundColor: dynamic /* String | CanvasGradient | CanvasPattern | Array<String> | Array<dynamic /* String | CanvasGradient | CanvasPattern | Array<String> */> */ get() = definedExternally; set(value) = definedExternally + var hoverBorderColor: dynamic /* String | CanvasGradient | CanvasPattern | Array<String> | Array<dynamic /* String | CanvasGradient | CanvasPattern | Array<String> */> */ get() = definedExternally; set(value) = definedExternally + var hoverBorderWidth: dynamic /* Number | Array<Number> */ get() = definedExternally; set(value) = definedExternally + var label: String? get() = definedExternally; set(value) = definedExternally + var lineTension: Number? get() = definedExternally; set(value) = definedExternally + var steppedLine: dynamic /* Boolean | String /* "before" */ | String /* "after" */ */ get() = definedExternally; set(value) = definedExternally + var pointBorderColor: dynamic /* String | CanvasGradient | CanvasPattern | Array<String> | Array<dynamic /* String | CanvasGradient | CanvasPattern | Array<String> */> */ get() = definedExternally; set(value) = definedExternally + var pointBackgroundColor: dynamic /* String | CanvasGradient | CanvasPattern | Array<String> | Array<dynamic /* String | CanvasGradient | CanvasPattern | Array<String> */> */ get() = definedExternally; set(value) = definedExternally + var pointBorderWidth: dynamic /* Number | Array<Number> */ get() = definedExternally; set(value) = definedExternally + var pointRadius: dynamic /* Number | Array<Number> */ get() = definedExternally; set(value) = definedExternally + var pointHoverRadius: dynamic /* Number | Array<Number> */ get() = definedExternally; set(value) = definedExternally + var pointHitRadius: dynamic /* Number | Array<Number> */ get() = definedExternally; set(value) = definedExternally + var pointHoverBackgroundColor: dynamic /* String | CanvasGradient | CanvasPattern | Array<String> | Array<dynamic /* String | CanvasGradient | CanvasPattern | Array<String> */> */ get() = definedExternally; set(value) = definedExternally + var pointHoverBorderColor: dynamic /* String | CanvasGradient | CanvasPattern | Array<String> | Array<dynamic /* String | CanvasGradient | CanvasPattern | Array<String> */> */ get() = definedExternally; set(value) = definedExternally + var pointHoverBorderWidth: dynamic /* Number | Array<Number> */ get() = definedExternally; set(value) = definedExternally + var pointStyle: dynamic /* HTMLCanvasElement | String /* "line" */ | String /* "circle" */ | String /* "cross" */ | String /* "crossRot" */ | String /* "dash" */ | String /* "rect" */ | String /* "rectRounded" */ | String /* "rectRot" */ | String /* "star" */ | String /* "triangle" */ | HTMLImageElement | Array<dynamic /* HTMLCanvasElement | String /* "line" */ | String /* "circle" */ | String /* "cross" */ | String /* "crossRot" */ | String /* "dash" */ | String /* "rect" */ | String /* "rectRounded" */ | String /* "rectRot" */ | String /* "star" */ | String /* "triangle" */ | HTMLImageElement */> */ get() = definedExternally; set(value) = definedExternally + var xAxisID: String? get() = definedExternally; set(value) = definedExternally + var yAxisID: String? get() = definedExternally; set(value) = definedExternally + var type: dynamic /* String /* "line" */ | String /* "bar" */ | String /* "horizontalBar" */ | String /* "radar" */ | String /* "doughnut" */ | String /* "polarArea" */ | String /* "bubble" */ | String /* "pie" */ | String /* "scatter" */ | String */ get() = definedExternally; set(value) = definedExternally + var hidden: Boolean? get() = definedExternally; set(value) = definedExternally + var hideInLegendAndTooltip: Boolean? get() = definedExternally; set(value) = definedExternally + var showLine: Boolean? get() = definedExternally; set(value) = definedExternally + var stack: String? get() = definedExternally; set(value) = definedExternally + var spanGaps: Boolean? get() = definedExternally; set(value) = definedExternally + } + + interface ChartScales { + var type: dynamic /* String /* "category" */ | String /* "linear" */ | String /* "logarithmic" */ | String /* "time" */ | String /* "radialLinear" */ | String */ get() = definedExternally; set(value) = definedExternally + var display: Boolean? get() = definedExternally; set(value) = definedExternally + var position: dynamic /* String /* "left" */ | String /* "right" */ | String /* "top" */ | String /* "bottom" */ | String */ get() = definedExternally; set(value) = definedExternally + var gridLines: GridLineOptions? get() = definedExternally; set(value) = definedExternally + var scaleLabel: ScaleTitleOptions? get() = definedExternally; set(value) = definedExternally + var ticks: TickOptions? get() = definedExternally; set(value) = definedExternally + var xAxes: Array<ChartXAxe>? get() = definedExternally; set(value) = definedExternally + var yAxes: Array<ChartYAxe>? get() = definedExternally; set(value) = definedExternally + } + + interface CommonAxe { + var bounds: String? get() = definedExternally; set(value) = definedExternally + var type: dynamic /* String /* "category" */ | String /* "linear" */ | String /* "logarithmic" */ | String /* "time" */ | String /* "radialLinear" */ | String */ get() = definedExternally; set(value) = definedExternally + var display: Boolean? get() = definedExternally; set(value) = definedExternally + var id: String? get() = definedExternally; set(value) = definedExternally + var stacked: Boolean? get() = definedExternally; set(value) = definedExternally + var position: String? get() = definedExternally; set(value) = definedExternally + var ticks: TickOptions? get() = definedExternally; set(value) = definedExternally + var gridLines: GridLineOptions? get() = definedExternally; set(value) = definedExternally + var barThickness: dynamic /* Number | String /* "flex" */ */ get() = definedExternally; set(value) = definedExternally + var maxBarThickness: Number? get() = definedExternally; set(value) = definedExternally + var scaleLabel: ScaleTitleOptions? get() = definedExternally; set(value) = definedExternally + var time: TimeScale? get() = definedExternally; set(value) = definedExternally + var offset: Boolean? get() = definedExternally; set(value) = definedExternally + val beforeUpdate: ((scale: Any? /*= null*/) -> Unit)? get() = definedExternally + val beforeSetDimension: ((scale: Any? /*= null*/) -> Unit)? get() = definedExternally + val beforeDataLimits: ((scale: Any? /*= null*/) -> Unit)? get() = definedExternally + val beforeBuildTicks: ((scale: Any? /*= null*/) -> Unit)? get() = definedExternally + val beforeTickToLabelConversion: ((scale: Any? /*= null*/) -> Unit)? get() = definedExternally + val beforeCalculateTickRotation: ((scale: Any? /*= null*/) -> Unit)? get() = definedExternally + val beforeFit: ((scale: Any? /*= null*/) -> Unit)? get() = definedExternally + val afterUpdate: ((scale: Any? /*= null*/) -> Unit)? get() = definedExternally + val afterSetDimension: ((scale: Any? /*= null*/) -> Unit)? get() = definedExternally + val afterDataLimits: ((scale: Any? /*= null*/) -> Unit)? get() = definedExternally + val afterBuildTicks: ((scale: Any? /*= null*/) -> Unit)? get() = definedExternally + val afterTickToLabelConversion: ((scale: Any? /*= null*/) -> Unit)? get() = definedExternally + val afterCalculateTickRotation: ((scale: Any? /*= null*/) -> Unit)? get() = definedExternally + val afterFit: ((scale: Any? /*= null*/) -> Unit)? get() = definedExternally + } + + interface ChartXAxe : CommonAxe { + var categoryPercentage: Number? get() = definedExternally; set(value) = definedExternally + var barPercentage: Number? get() = definedExternally; set(value) = definedExternally + var distribution: dynamic /* String /* "linear" */ | String /* "series" */ */ get() = definedExternally; set(value) = definedExternally + } + + interface ChartYAxe : CommonAxe + interface LinearScale : ChartScales { + override var ticks: TickOptions? get() = definedExternally; set(value) = definedExternally + } + + interface LogarithmicScale : ChartScales { + override var ticks: TickOptions? get() = definedExternally; set(value) = definedExternally + } + + interface TimeDisplayFormat { + var millisecond: String? get() = definedExternally; set(value) = definedExternally + var second: String? get() = definedExternally; set(value) = definedExternally + var minute: String? get() = definedExternally; set(value) = definedExternally + var hour: String? get() = definedExternally; set(value) = definedExternally + var day: String? get() = definedExternally; set(value) = definedExternally + var week: String? get() = definedExternally; set(value) = definedExternally + var month: String? get() = definedExternally; set(value) = definedExternally + var quarter: String? get() = definedExternally; set(value) = definedExternally + var year: String? get() = definedExternally; set(value) = definedExternally + } + + interface TimeScale : ChartScales { + var displayFormats: TimeDisplayFormat? get() = definedExternally; set(value) = definedExternally + var isoWeekday: Boolean? get() = definedExternally; set(value) = definedExternally + var max: String? get() = definedExternally; set(value) = definedExternally + var min: String? get() = definedExternally; set(value) = definedExternally + var parser: dynamic /* String | (arg: Any) -> Any */ get() = definedExternally; set(value) = definedExternally + var round: dynamic /* String /* "millisecond" */ | String /* "second" */ | String /* "minute" */ | String /* "hour" */ | String /* "day" */ | String /* "week" */ | String /* "month" */ | String /* "quarter" */ | String /* "year" */ */ get() = definedExternally; set(value) = definedExternally + var tooltipFormat: String? get() = definedExternally; set(value) = definedExternally + var unit: dynamic /* String /* "millisecond" */ | String /* "second" */ | String /* "minute" */ | String /* "hour" */ | String /* "day" */ | String /* "week" */ | String /* "month" */ | String /* "quarter" */ | String /* "year" */ */ get() = definedExternally; set(value) = definedExternally + var unitStepSize: Number? get() = definedExternally; set(value) = definedExternally + var stepSize: Number? get() = definedExternally; set(value) = definedExternally + var minUnit: dynamic /* String /* "millisecond" */ | String /* "second" */ | String /* "minute" */ | String /* "hour" */ | String /* "day" */ | String /* "week" */ | String /* "month" */ | String /* "quarter" */ | String /* "year" */ */ get() = definedExternally; set(value) = definedExternally + } + + interface RadialLinearScale : LinearScale { + var lineArc: Boolean? get() = definedExternally; set(value) = definedExternally + var angleLines: AngleLineOptions? get() = definedExternally; set(value) = definedExternally + var pointLabels: PointLabelOptions? get() = definedExternally; set(value) = definedExternally + override var ticks: TickOptions? get() = definedExternally; set(value) = definedExternally + } + + interface Point { + var x: Number + var y: Number + } +} + +@Suppress("NOTHING_TO_INLINE", "UnsafeCastFromDynamic") +inline operator fun Chart.Positioners.get(mode: String): ((elements: Array<Any>, eventPosition: Chart.Point) -> Chart.Point)? = + asDynamic()[mode] + +@Suppress("NOTHING_TO_INLINE") +inline operator fun Chart.Positioners.set( + mode: String, + noinline value: (elements: Array<Any>, eventPosition: Chart.Point) -> Chart.Point +) { + asDynamic()[mode] = value +} + +@Suppress("NOTHING_TO_INLINE", "UnsafeCastFromDynamic") +inline operator fun Chart.ChartPluginsOptions.get(pluginId: String): Any? = asDynamic()[pluginId] + +@Suppress("NOTHING_TO_INLINE") +inline operator fun Chart.ChartPluginsOptions.set(pluginId: String, value: Any) { + asDynamic()[pluginId] = value +} + +open external class PluginServiceStatic { + open fun register(plugin: PluginServiceGlobalRegistration /* PluginServiceGlobalRegistration & PluginServiceRegistrationOptions */): Unit = + definedExternally + + open fun unregister(plugin: PluginServiceGlobalRegistration /* PluginServiceGlobalRegistration & PluginServiceRegistrationOptions */): Unit = + definedExternally +} + +external interface PluginServiceGlobalRegistration { + var id: String? get() = definedExternally; set(value) = definedExternally +} + +external interface PluginServiceRegistrationOptions { + val beforeInit: ((chartInstance: Chart, options: Any? /*= null*/) -> Unit)? get() = definedExternally + val afterInit: ((chartInstance: Chart, options: Any? /*= null*/) -> Unit)? get() = definedExternally + val beforeUpdate: ((chartInstance: Chart, options: Any? /*= null*/) -> Unit)? get() = definedExternally + val afterUpdate: ((chartInstance: Chart, options: Any? /*= null*/) -> Unit)? get() = definedExternally + val beforeLayout: ((chartInstance: Chart, options: Any? /*= null*/) -> Unit)? get() = definedExternally + val afterLayout: ((chartInstance: Chart, options: Any? /*= null*/) -> Unit)? get() = definedExternally + val beforeDatasetsUpdate: ((chartInstance: Chart, options: Any? /*= null*/) -> Unit)? get() = definedExternally + val afterDatasetsUpdate: ((chartInstance: Chart, options: Any? /*= null*/) -> Unit)? get() = definedExternally + val beforeDatasetUpdate: ((chartInstance: Chart, options: Any? /*= null*/) -> Unit)? get() = definedExternally + val afterDatasetUpdate: ((chartInstance: Chart, options: Any? /*= null*/) -> Unit)? get() = definedExternally + val beforeRender: ((chartInstance: Chart, options: Any? /*= null*/) -> Unit)? get() = definedExternally + val afterRender: ((chartInstance: Chart, options: Any? /*= null*/) -> Unit)? get() = definedExternally + val beforeDraw: ((chartInstance: Chart, easing: String, options: Any? /*= null*/) -> Unit)? get() = definedExternally + val afterDraw: ((chartInstance: Chart, easing: String, options: Any? /*= null*/) -> Unit)? get() = definedExternally + val beforeDatasetsDraw: ((chartInstance: Chart, easing: String, options: Any? /*= null*/) -> Unit)? get() = definedExternally + val afterDatasetsDraw: ((chartInstance: Chart, easing: String, options: Any? /*= null*/) -> Unit)? get() = definedExternally + val beforeDatasetDraw: ((chartInstance: Chart, easing: String, options: Any? /*= null*/) -> Unit)? get() = definedExternally + val afterDatasetDraw: ((chartInstance: Chart, easing: String, options: Any? /*= null*/) -> Unit)? get() = definedExternally + val beforeTooltipDraw: ((chartInstance: Chart, tooltipData: Any? /*= null*/, options: Any? /*= null*/) -> Unit)? get() = definedExternally + val afterTooltipDraw: ((chartInstance: Chart, tooltipData: Any? /*= null*/, options: Any? /*= null*/) -> Unit)? get() = definedExternally + val beforeEvent: ((chartInstance: Chart, event: Event, options: Any? /*= null*/) -> Unit)? get() = definedExternally + val afterEvent: ((chartInstance: Chart, event: Event, options: Any? /*= null*/) -> Unit)? get() = definedExternally + val resize: ((chartInstance: Chart, newChartSize: Chart.ChartSize, options: Any? /*= null*/) -> Unit)? get() = definedExternally + val destroy: ((chartInstance: Chart) -> Unit)? get() = definedExternally + val afterScaleUpdate: ((chartInstance: Chart, options: Any? /*= null*/) -> Unit)? get() = definedExternally +} + +external interface Meta { + var type: dynamic /* String /* "line" */ | String /* "bar" */ | String /* "horizontalBar" */ | String /* "radar" */ | String /* "doughnut" */ | String /* "polarArea" */ | String /* "bubble" */ | String /* "pie" */ | String /* "scatter" */ */ + var data: Array<MetaData> + var dataset: Chart.ChartDataSets? get() = definedExternally; set(value) = definedExternally + var controller: Json + var hidden: Boolean? get() = definedExternally; set(value) = definedExternally + var total: String? get() = definedExternally; set(value) = definedExternally + var xAxisID: String? get() = definedExternally; set(value) = definedExternally + var yAxisID: String? get() = definedExternally; set(value) = definedExternally + var `$filler`: Json? get() = definedExternally; set(value) = definedExternally +} + +external interface MetaData { + var _chart: Chart + var _datasetIndex: Number + var _index: Number + var _model: Model + var _start: Any? get() = definedExternally; set(value) = definedExternally + var _view: Model + var _xScale: Chart.ChartScales + var _yScale: Chart.ChartScales + var hidden: Boolean? get() = definedExternally; set(value) = definedExternally +} + +external interface Model { + var backgroundColor: String + var borderColor: String + var borderWidth: Number? get() = definedExternally; set(value) = definedExternally + var controlPointNextX: Number + var controlPointNextY: Number + var controlPointPreviousX: Number + var controlPointPreviousY: Number + var hitRadius: Number + var pointStyle: String + var radius: String + var skip: Boolean? get() = definedExternally; set(value) = definedExternally + var steppedLine: Nothing? get() = definedExternally; set(value) = definedExternally + var tension: Number + var x: Number + var y: Number + var base: Number + var head: Number +} diff --git a/kvision-modules/kvision-chart/src/test/kotlin/test/pl/treksoft/kvision/TestUtil.kt b/kvision-modules/kvision-chart/src/test/kotlin/test/pl/treksoft/kvision/TestUtil.kt new file mode 100644 index 00000000..9d86766c --- /dev/null +++ b/kvision-modules/kvision-chart/src/test/kotlin/test/pl/treksoft/kvision/TestUtil.kt @@ -0,0 +1,99 @@ +/* + * Copyright (c) 2017-present Robert Jaros + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ +package test.pl.treksoft.kvision + +import org.w3c.dom.Element +import pl.treksoft.jquery.jQuery +import pl.treksoft.kvision.core.Widget +import pl.treksoft.kvision.panel.Root +import kotlin.browser.document +import kotlin.test.assertEquals +import kotlin.test.assertTrue + +interface TestSpec { + fun beforeTest() + + fun afterTest() + + fun run(code: () -> Unit) { + beforeTest() + code() + afterTest() + } +} + +interface SimpleSpec : TestSpec { + + override fun beforeTest() { + } + + override fun afterTest() { + } + +} + +interface DomSpec : TestSpec { + + override fun beforeTest() { + val fixture = "<div style=\"display: none\" id=\"pretest\">" + + "<div id=\"test\"></div></div>" + document.body?.insertAdjacentHTML("afterbegin", fixture) + } + + override fun afterTest() { + val div = document.getElementById("pretest") + div?.let { jQuery(it).remove() } + jQuery(".modal-backdrop").remove() + } + + fun assertEqualsHtml(expected: String?, actual: String?, message: String?) { + if (expected != null && actual != null) { + val exp = jQuery(expected) + val act = jQuery(actual) + val result = exp[0]?.isEqualNode(act[0]) + if (result == true) { + assertTrue(result == true, message) + } else { + assertEquals(expected, actual, message) + } + } else { + assertEquals(expected, actual, message) + } + } +} + +interface WSpec : DomSpec { + + fun runW(code: (widget: Widget, element: Element?) -> Unit) { + run { + val root = Root("test", true) + val widget = Widget() + widget.id = "test_id" + root.add(widget) + val element = document.getElementById("test_id") + code(widget, element) + } + } + +} + +external fun require(name: String): dynamic diff --git a/kvision-modules/kvision-chart/src/test/kotlin/test/pl/treksoft/kvision/chart/ChartCanvasSpec.kt b/kvision-modules/kvision-chart/src/test/kotlin/test/pl/treksoft/kvision/chart/ChartCanvasSpec.kt new file mode 100644 index 00000000..9ea2ee6e --- /dev/null +++ b/kvision-modules/kvision-chart/src/test/kotlin/test/pl/treksoft/kvision/chart/ChartCanvasSpec.kt @@ -0,0 +1,77 @@ +/* + * Copyright (c) 2017-present Robert Jaros + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ +package test.pl.treksoft.kvision.chart + +import pl.treksoft.kvision.chart.ChartCanvas +import pl.treksoft.kvision.chart.ChartType +import pl.treksoft.kvision.chart.Configuration +import pl.treksoft.kvision.chart.DataSets +import pl.treksoft.kvision.chart.Options +import pl.treksoft.kvision.panel.Root +import test.pl.treksoft.kvision.DomSpec +import kotlin.browser.document +import kotlin.test.Test + +class ChartCanvasSpec : DomSpec { + + @Test + fun renderResponsive() { + run { + val root = Root("test", true) + val chart = ChartCanvas( + configuration = Configuration( + ChartType.SCATTER, + listOf(DataSets(label = "Chart", data = listOf(0, 1))) + ) + ) + root.add(chart) + val element = document.getElementById("test") + assertEqualsHtml( + "<canvas width=\"0\" height=\"0\" class=\"chartjs-render-monitor\" style=\"display: block; width: 0px; height: 0px;\"></canvas>", + element?.innerHTML, + "Should render correct responsive chart canvas" + ) + } + } + + @Test + fun renderNotResponsive() { + run { + val root = Root("test", true) + val chart = ChartCanvas( + 300, 600, + configuration = Configuration( + ChartType.SCATTER, + listOf(DataSets(label = "Chart", data = listOf(0, 1))), + options = Options(responsive = false) + ) + ) + root.add(chart) + val element = document.getElementById("test") + assertEqualsHtml( + "<canvas width=\"300\" height=\"600\" style=\"display: block;\"></canvas>", + element?.innerHTML, + "Should render correct not responsive chart canvas" + ) + } + } +}
\ No newline at end of file diff --git a/kvision-modules/kvision-chart/src/test/kotlin/test/pl/treksoft/kvision/chart/ChartSpec.kt b/kvision-modules/kvision-chart/src/test/kotlin/test/pl/treksoft/kvision/chart/ChartSpec.kt new file mode 100644 index 00000000..2e508107 --- /dev/null +++ b/kvision-modules/kvision-chart/src/test/kotlin/test/pl/treksoft/kvision/chart/ChartSpec.kt @@ -0,0 +1,81 @@ +/* + * Copyright (c) 2017-present Robert Jaros + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ +package test.pl.treksoft.kvision.chart + +import pl.treksoft.kvision.chart.Chart +import pl.treksoft.kvision.chart.ChartType +import pl.treksoft.kvision.chart.Configuration +import pl.treksoft.kvision.chart.DataSets +import pl.treksoft.kvision.chart.Options +import pl.treksoft.kvision.panel.Root +import pl.treksoft.kvision.utils.px +import test.pl.treksoft.kvision.DomSpec +import kotlin.browser.document +import kotlin.test.Test + +class ChartSpec : DomSpec { + + @Test + fun renderResponsive() { + run { + val root = Root("test", true) + val chart = Chart( + Configuration( + ChartType.SCATTER, + listOf(DataSets(label = "Chart", data = listOf(0, 1))) + ) + ).apply { + width = 300.px + height = 600.px + } + root.add(chart) + val element = document.getElementById("test") + assertEqualsHtml( + "<div style=\"width: 300px; height: 600px;\"><canvas height=\"0\" class=\"chartjs-render-monitor\" width=\"0\" style=\"display: block; width: 0px; height: 0px;\"></canvas></div>", + element?.innerHTML, + "Should render correct responsive chart" + ) + } + } + + @Test + fun renderNotResponsive() { + run { + val root = Root("test", true) + val chart = Chart( + Configuration( + ChartType.SCATTER, + listOf(DataSets(label = "Chart", data = listOf(0, 1))), + options = Options(responsive = false) + ), 300, 600 + ) + root.add(chart) + val element = document.getElementById("test") + assertEqualsHtml( + "<div><canvas width=\"300\" height=\"600\" style=\"display: block;\"></canvas></div>", + element?.innerHTML, + "Should render correct not responsive chart" + ) + } + } + +}
\ No newline at end of file diff --git a/settings.gradle b/settings.gradle index 25548bbc..f87752ef 100644 --- a/settings.gradle +++ b/settings.gradle @@ -11,6 +11,7 @@ include 'kvision-modules:kvision-base', 'kvision-modules:kvision-upload', 'kvision-modules:kvision-handlebars', 'kvision-modules:kvision-i18n', + 'kvision-modules:kvision-chart', 'kvision-modules:kvision-remote', 'kvision-modules:kvision-select-remote', 'kvision-modules:kvision-server-jooby', diff --git a/src/main/kotlin/pl/treksoft/kvision/core/Css.kt b/src/main/kotlin/pl/treksoft/kvision/core/Css.kt index d36a8d69..9fc50097 100644 --- a/src/main/kotlin/pl/treksoft/kvision/core/Css.kt +++ b/src/main/kotlin/pl/treksoft/kvision/core/Css.kt @@ -570,7 +570,7 @@ class Color private constructor(private val color: String? = null) { */ constructor(color: Col) : this(color.color) - internal fun asString(): String { + fun asString(): String { return color.orEmpty() } } |